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