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.
Dependents: STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more
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 Wed Jul 13 2022 23:38:02 by
1.7.2