Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of azure_c_shared_utility by
hmac.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 /**************************** hmac.c ****************************/ 00005 /******************** See RFC 4634 for details ******************/ 00006 /* 00007 * Description: 00008 * This file implements the HMAC algorithm (Keyed-Hashing for 00009 * Message Authentication, RFC2104), expressed in terms of the 00010 * various SHA algorithms. 00011 */ 00012 00013 #include "azure_c_shared_utility/sha.h" 00014 00015 /* 00016 * hmac 00017 * 00018 * Description: 00019 * This function will compute an HMAC message digest. 00020 * 00021 * Parameters: 00022 * whichSha: [in] 00023 * One of SHA1, SHA224, SHA256, SHA384, SHA512 00024 * key: [in] 00025 * The secret shared key. 00026 * key_len: [in] 00027 * The length of the secret shared key. 00028 * message_array: [in] 00029 * An array of characters representing the message. 00030 * length: [in] 00031 * The length of the message in message_array 00032 * digest: [out] 00033 * Where the digest is returned. 00034 * NOTE: The length of the digest is determined by 00035 * the value of whichSha. 00036 * 00037 * Returns: 00038 * sha Error Code. 00039 * 00040 */ 00041 int hmac(SHAversion whichSha, const unsigned char *text, int text_len, 00042 const unsigned char *key, int key_len, 00043 uint8_t digest[USHAMaxHashSize]) 00044 { 00045 HMACContext ctx; 00046 return hmacReset(&ctx, whichSha, key, key_len) || 00047 hmacInput(&ctx, text, text_len) || 00048 hmacResult(&ctx, digest); 00049 } 00050 00051 /* 00052 * hmacReset 00053 * 00054 * Description: 00055 * This function will initialize the hmacContext in preparation 00056 * for computing a new HMAC message digest. 00057 * 00058 * Parameters: 00059 * context: [in/out] 00060 * The context to reset. 00061 * whichSha: [in] 00062 * One of SHA1, SHA224, SHA256, SHA384, SHA512 00063 * key: [in] 00064 * The secret shared key. 00065 * key_len: [in] 00066 * The length of the secret shared key. 00067 * 00068 * Returns: 00069 * sha Error Code. 00070 * 00071 */ 00072 int hmacReset(HMACContext *ctx, enum SHAversion whichSha, 00073 const unsigned char *key, int key_len) 00074 { 00075 int i, blocksize, hashsize; 00076 00077 /* inner padding - key XORd with ipad */ 00078 unsigned char k_ipad[USHA_Max_Message_Block_Size]; 00079 00080 /* temporary buffer when keylen > blocksize */ 00081 unsigned char tempkey[USHAMaxHashSize]; 00082 00083 if (!ctx) return shaNull; 00084 00085 blocksize = ctx->blockSize = USHABlockSize(whichSha); 00086 hashsize = ctx->hashSize = USHAHashSize(whichSha); 00087 00088 ctx->whichSha = whichSha; 00089 00090 /* 00091 * If key is longer than the hash blocksize, 00092 * reset it to key = HASH(key). 00093 */ 00094 if (key_len > blocksize) { 00095 USHAContext tctx; 00096 int err = USHAReset(&tctx, whichSha) || 00097 USHAInput(&tctx, key, key_len) || 00098 USHAResult(&tctx, tempkey); 00099 if (err != shaSuccess) return err; 00100 00101 key = tempkey; 00102 key_len = hashsize; 00103 } 00104 00105 /* 00106 * The HMAC transform looks like: 00107 * 00108 * SHA(K XOR opad, SHA(K XOR ipad, text)) 00109 * 00110 * where K is an n byte key. 00111 * ipad is the byte 0x36 repeated blocksize times 00112 * opad is the byte 0x5c repeated blocksize times 00113 * and text is the data being protected. 00114 */ 00115 00116 /* store key into the pads, XOR'd with ipad and opad values */ 00117 for (i = 0; i < key_len; i++) { 00118 k_ipad[i] = key[i] ^ 0x36; 00119 ctx->k_opad[i] = key[i] ^ 0x5c; 00120 } 00121 /* remaining pad bytes are '\0' XOR'd with ipad and opad values */ 00122 for (; i < blocksize; i++) { 00123 k_ipad[i] = 0x36; 00124 ctx->k_opad[i] = 0x5c; 00125 } 00126 00127 /* perform inner hash */ 00128 /* init context for 1st pass */ 00129 return USHAReset(&ctx->shaContext, whichSha) || 00130 /* and start with inner pad */ 00131 USHAInput(&ctx->shaContext, k_ipad, blocksize); 00132 } 00133 00134 /* 00135 * hmacInput 00136 * 00137 * Description: 00138 * This function accepts an array of octets as the next portion 00139 * of the message. 00140 * 00141 * Parameters: 00142 * context: [in/out] 00143 * The HMAC context to update 00144 * message_array: [in] 00145 * An array of characters representing the next portion of 00146 * the message. 00147 * length: [in] 00148 * The length of the message in message_array 00149 * 00150 * Returns: 00151 * sha Error Code. 00152 * 00153 */ 00154 int hmacInput(HMACContext *ctx, const unsigned char *text, 00155 int text_len) 00156 { 00157 if (!ctx) return shaNull; 00158 /* then text of datagram */ 00159 return USHAInput(&ctx->shaContext, text, text_len); 00160 } 00161 00162 /* 00163 * HMACFinalBits 00164 * 00165 * Description: 00166 * This function will add in any final bits of the message. 00167 * 00168 * Parameters: 00169 * context: [in/out] 00170 * The HMAC context to update 00171 * message_bits: [in] 00172 * The final bits of the message, in the upper portion of the 00173 * byte. (Use 0b###00000 instead of 0b00000### to input the 00174 * three bits ###.) 00175 * length: [in] 00176 * The number of bits in message_bits, between 1 and 7. 00177 * 00178 * Returns: 00179 * sha Error Code. 00180 */ 00181 int hmacFinalBits(HMACContext *ctx, 00182 const uint8_t bits, 00183 unsigned int bitcount) 00184 { 00185 if (!ctx) return shaNull; 00186 /* then final bits of datagram */ 00187 return USHAFinalBits(&ctx->shaContext, bits, bitcount); 00188 } 00189 00190 /* 00191 * HMACResult 00192 * 00193 * Description: 00194 * This function will return the N-byte message digest into the 00195 * Message_Digest array provided by the caller. 00196 * NOTE: The first octet of hash is stored in the 0th element, 00197 * the last octet of hash in the Nth element. 00198 * 00199 * Parameters: 00200 * context: [in/out] 00201 * The context to use to calculate the HMAC hash. 00202 * digest: [out] 00203 * Where the digest is returned. 00204 * NOTE 2: The length of the hash is determined by the value of 00205 * whichSha that was passed to hmacReset(). 00206 * 00207 * Returns: 00208 * sha Error Code. 00209 * 00210 */ 00211 int hmacResult(HMACContext *ctx, uint8_t *digest) 00212 { 00213 if (!ctx) return shaNull; 00214 00215 /* finish up 1st pass */ 00216 /* (Use digest here as a temporary buffer.) */ 00217 return USHAResult(&ctx->shaContext, digest) || 00218 00219 /* perform outer SHA */ 00220 /* init context for 2nd pass */ 00221 USHAReset(&ctx->shaContext, (SHAversion)ctx->whichSha) || 00222 00223 /* start with outer pad */ 00224 USHAInput(&ctx->shaContext, ctx->k_opad, ctx->blockSize) || 00225 00226 /* then results of 1st hash */ 00227 USHAInput(&ctx->shaContext, digest, ctx->hashSize) || 00228 00229 /* finish up 2nd pass */ 00230 USHAResult(&ctx->shaContext, digest); 00231 } 00232 00233
Generated on Tue Jul 12 2022 19:14:38 by
