hmac.c
Go to the documentation of this file.
1 /**
2  * @file hmac.c
3  * @brief HMAC (Keyed-Hashing for Message Authentication)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * HMAC is a mechanism for message authentication using cryptographic hash
28  * functions. HMAC can be used with any iterative cryptographic hash
29  * function (MD5, SHA-1 or SHA-256) in combination with a secret shared
30  * key. Refer to RFC 2104 for more details
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 1.9.0
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "mac/hmac.h"
42 
43 //Check crypto library configuration
44 #if (HMAC_SUPPORT == ENABLED)
45 
46 //HMAC with MD5 OID (1.3.6.1.5.5.8.1.1)
47 const uint8_t HMAC_WITH_MD5_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x01};
48 //HMAC with Tiger OID (1.3.6.1.5.5.8.1.3)
49 const uint8_t HMAC_WITH_TIGER_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x03};
50 //HMAC with RIPEMD-160 OID (1.3.6.1.5.5.8.1.4)
51 const uint8_t HMAC_WITH_RIPEMD160_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x04};
52 //HMAC with SHA-1 OID (1.2.840.113549.2.7)
53 const uint8_t HMAC_WITH_SHA1_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x07};
54 //HMAC with SHA-224 OID (1.2.840.113549.2.8)
55 const uint8_t HMAC_WITH_SHA224_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x08};
56 //HMAC with SHA-256 OID (1.2.840.113549.2.9)
57 const uint8_t HMAC_WITH_SHA256_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x09};
58 //HMAC with SHA-384 OID (1.2.840.113549.2.10)
59 const uint8_t HMAC_WITH_SHA384_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0A};
60 //HMAC with SHA-512 OID (1.2.840.113549.2.11)
61 const uint8_t HMAC_WITH_SHA512_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0B};
62 //HMAC with SHA-3-224 object identifier (2.16.840.1.101.3.4.2.13)
63 const uint8_t HMAC_WITH_SHA3_224_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0D};
64 //HMAC with SHA-3-256 object identifier (2.16.840.1.101.3.4.2.14)
65 const uint8_t HMAC_WITH_SHA3_256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0E};
66 //HMAC with SHA-3-384 object identifier (2.16.840.1.101.3.4.2.15)
67 const uint8_t HMAC_WITH_SHA3_384_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0F};
68 //HMAC with SHA-3-512 object identifier (2.16.840.1.101.3.4.2.16)
69 const uint8_t HMAC_WITH_SHA3_512_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x10};
70 
71 
72 /**
73  * @brief Compute HMAC using the specified hash function
74  * @param[in] hash Hash algorithm used to compute HMAC
75  * @param[in] key Key to use in the hash algorithm
76  * @param[in] keyLen Length of the key
77  * @param[in] data The input data for which to compute the hash code
78  * @param[in] dataLen Length of the input data
79  * @param[out] digest The computed HMAC value
80  * @return Error code
81  **/
82 
83 error_t hmacCompute(const HashAlgo *hash, const void *key, size_t keyLen,
84  const void *data, size_t dataLen, uint8_t *digest)
85 {
86  HmacContext *context;
87 
88  //Allocate a memory buffer to hold the HMAC context
89  context = cryptoAllocMem(sizeof(HmacContext));
90  //Failed to allocate memory?
91  if(context == NULL)
92  return ERROR_OUT_OF_MEMORY;
93 
94  //Initialize the HMAC context
95  hmacInit(context, hash, key, keyLen);
96  //Digest the message
97  hmacUpdate(context, data, dataLen);
98  //Finalize the HMAC computation
99  hmacFinal(context, digest);
100 
101  //Free previously allocated memory
102  cryptoFreeMem(context);
103  //Successful processing
104  return NO_ERROR;
105 }
106 
107 
108 /**
109  * @brief Initialize HMAC calculation
110  * @param[in] context Pointer to the HMAC context to initialize
111  * @param[in] hash Hash algorithm used to compute HMAC
112  * @param[in] key Key to use in the hash algorithm
113  * @param[in] keyLen Length of the key
114  **/
115 
116 void hmacInit(HmacContext *context, const HashAlgo *hash,
117  const void *key, size_t keyLen)
118 {
119  uint_t i;
120 
121  //Hash algorithm used to compute HMAC
122  context->hash = hash;
123 
124  //The key is longer than the block size?
125  if(keyLen > hash->blockSize)
126  {
127  //Initialize the hash function context
128  hash->init(context->hashContext);
129  //Digest the original key
130  hash->update(context->hashContext, key, keyLen);
131  //Finalize the message digest computation
132  hash->final(context->hashContext, context->key);
133 
134  //Key is padded to the right with extra zeros
135  cryptoMemset(context->key + hash->digestSize, 0,
136  hash->blockSize - hash->digestSize);
137  }
138  else
139  {
140  //Copy the key
141  cryptoMemcpy(context->key, key, keyLen);
142  //Key is padded to the right with extra zeros
143  cryptoMemset(context->key + keyLen, 0, hash->blockSize - keyLen);
144  }
145 
146  //XOR the resulting key with ipad
147  for(i = 0; i < hash->blockSize; i++)
148  {
149  context->key[i] ^= HMAC_IPAD;
150  }
151 
152  //Initialize context for the first pass
153  hash->init(context->hashContext);
154  //Start with the inner pad
155  hash->update(context->hashContext, context->key, hash->blockSize);
156 }
157 
158 
159 /**
160  * @brief Update the HMAC context with a portion of the message being hashed
161  * @param[in] context Pointer to the HMAC context
162  * @param[in] data Pointer to the buffer being hashed
163  * @param[in] length Length of the buffer
164  **/
165 
166 void hmacUpdate(HmacContext *context, const void *data, size_t length)
167 {
168  const HashAlgo *hash;
169 
170  //Hash algorithm used to compute HMAC
171  hash = context->hash;
172  //Digest the message (first pass)
173  hash->update(context->hashContext, data, length);
174 }
175 
176 
177 /**
178  * @brief Finish the HMAC calculation
179  * @param[in] context Pointer to the HMAC context
180  * @param[out] digest Calculated HMAC value (optional parameter)
181  **/
182 
183 void hmacFinal(HmacContext *context, uint8_t *digest)
184 {
185  uint_t i;
186  const HashAlgo *hash;
187 
188  //Hash algorithm used to compute HMAC
189  hash = context->hash;
190  //Finish the first pass
191  hash->final(context->hashContext, context->digest);
192 
193  //XOR the original key with opad
194  for(i = 0; i < hash->blockSize; i++)
195  {
196  context->key[i] ^= HMAC_IPAD ^ HMAC_OPAD;
197  }
198 
199  //Initialize context for the second pass
200  hash->init(context->hashContext);
201  //Start with outer pad
202  hash->update(context->hashContext, context->key, hash->blockSize);
203  //Then digest the result of the first hash
204  hash->update(context->hashContext, context->digest, hash->digestSize);
205  //Finish the second pass
206  hash->final(context->hashContext, context->digest);
207 
208  //Copy the resulting HMAC value
209  if(digest != NULL)
210  cryptoMemcpy(digest, context->digest, hash->digestSize);
211 }
212 
213 #endif
uint8_t hashContext[MAX_HASH_CONTEXT_SIZE]
Definition: hmac.h:183
const uint8_t HMAC_WITH_SHA3_512_OID[9]
Definition: hmac.c:69
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
const uint8_t HMAC_WITH_SHA512_OID[8]
Definition: hmac.c:61
#define cryptoFreeMem(p)
Definition: crypto.h:578
uint8_t hash
Definition: tls.h:1363
#define cryptoAllocMem(size)
Definition: crypto.h:573
General definitions for cryptographic algorithms.
void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:183
const uint8_t HMAC_WITH_SHA224_OID[8]
Definition: hmac.c:55
const HashAlgo * hash
Definition: hmac.h:182
HMAC algorithm context.
Definition: hmac.h:180
HMAC (Keyed-Hashing for Message Authentication)
uint8_t digest[MAX_HASH_DIGEST_SIZE]
Definition: hmac.h:185
const uint8_t HMAC_WITH_TIGER_OID[8]
Definition: hmac.c:49
Success.
Definition: error.h:42
const uint8_t HMAC_WITH_SHA3_384_OID[9]
Definition: hmac.c:67
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
const uint8_t HMAC_WITH_SHA384_OID[8]
Definition: hmac.c:59
uint8_t data[]
Definition: dtls_misc.h:167
const uint8_t HMAC_WITH_SHA256_OID[8]
Definition: hmac.c:57
uint8_t key[MAX_HASH_BLOCK_SIZE]
Definition: hmac.h:184
#define HMAC_OPAD
Definition: hmac.h:168
error_t hmacCompute(const HashAlgo *hash, const void *key, size_t keyLen, const void *data, size_t dataLen, uint8_t *digest)
Compute HMAC using the specified hash function.
Definition: hmac.c:83
#define HMAC_IPAD
Definition: hmac.h:166
const uint8_t HMAC_WITH_SHA3_224_OID[9]
Definition: hmac.c:63
const uint8_t HMAC_WITH_MD5_OID[8]
Definition: hmac.c:47
void hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:116
#define cryptoMemset(p, value, length)
Definition: crypto.h:584
void hmacUpdate(HmacContext *context, const void *data, size_t length)
Update the HMAC context with a portion of the message being hashed.
Definition: hmac.c:166
Common interface for hash algorithms.
Definition: crypto.h:1054
uint8_t length
Definition: dtls_misc.h:140
const uint8_t HMAC_WITH_SHA1_OID[8]
Definition: hmac.c:53
const uint8_t HMAC_WITH_SHA3_256_OID[9]
Definition: hmac.c:65
const uint8_t HMAC_WITH_RIPEMD160_OID[8]
Definition: hmac.c:51