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@25:8507bf644fdf, 2017-04-21 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Fri Apr 21 14:51:10 2017 -0700
- Revision:
- 25:8507bf644fdf
- Parent:
- 19:2e0811512ceb
1.1.13
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Azure.IoT Build | 0:fa2de1b79154 | 1 | // Copyright (c) Microsoft. All rights reserved. |
| Azure.IoT Build | 0:fa2de1b79154 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
| Azure.IoT Build | 0:fa2de1b79154 | 3 | |
| Azure.IoT Build | 0:fa2de1b79154 | 4 | /**************************** hmac.c ****************************/ |
| Azure.IoT Build | 0:fa2de1b79154 | 5 | /******************** See RFC 4634 for details ******************/ |
| Azure.IoT Build | 0:fa2de1b79154 | 6 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 7 | * Description: |
| Azure.IoT Build | 0:fa2de1b79154 | 8 | * This file implements the HMAC algorithm (Keyed-Hashing for |
| Azure.IoT Build | 0:fa2de1b79154 | 9 | * Message Authentication, RFC2104), expressed in terms of the |
| Azure.IoT Build | 0:fa2de1b79154 | 10 | * various SHA algorithms. |
| Azure.IoT Build | 0:fa2de1b79154 | 11 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 12 | |
| Azure.IoT Build | 0:fa2de1b79154 | 13 | #include "azure_c_shared_utility/sha.h" |
| Azure.IoT Build | 0:fa2de1b79154 | 14 | |
| Azure.IoT Build | 0:fa2de1b79154 | 15 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 16 | * hmac |
| Azure.IoT Build | 0:fa2de1b79154 | 17 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 18 | * Description: |
| Azure.IoT Build | 0:fa2de1b79154 | 19 | * This function will compute an HMAC message digest. |
| Azure.IoT Build | 0:fa2de1b79154 | 20 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 21 | * Parameters: |
| Azure.IoT Build | 0:fa2de1b79154 | 22 | * whichSha: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 23 | * One of SHA1, SHA224, SHA256, SHA384, SHA512 |
| Azure.IoT Build | 0:fa2de1b79154 | 24 | * key: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 25 | * The secret shared key. |
| Azure.IoT Build | 0:fa2de1b79154 | 26 | * key_len: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 27 | * The length of the secret shared key. |
| Azure.IoT Build | 0:fa2de1b79154 | 28 | * message_array: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 29 | * An array of characters representing the message. |
| Azure.IoT Build | 0:fa2de1b79154 | 30 | * length: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 31 | * The length of the message in message_array |
| Azure.IoT Build | 0:fa2de1b79154 | 32 | * digest: [out] |
| Azure.IoT Build | 0:fa2de1b79154 | 33 | * Where the digest is returned. |
| Azure.IoT Build | 0:fa2de1b79154 | 34 | * NOTE: The length of the digest is determined by |
| Azure.IoT Build | 0:fa2de1b79154 | 35 | * the value of whichSha. |
| Azure.IoT Build | 0:fa2de1b79154 | 36 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 37 | * Returns: |
| Azure.IoT Build | 0:fa2de1b79154 | 38 | * sha Error Code. |
| Azure.IoT Build | 0:fa2de1b79154 | 39 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 40 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 41 | int hmac(SHAversion whichSha, const unsigned char *text, int text_len, |
| Azure.IoT Build | 0:fa2de1b79154 | 42 | const unsigned char *key, int key_len, |
| Azure.IoT Build | 0:fa2de1b79154 | 43 | uint8_t digest[USHAMaxHashSize]) |
| Azure.IoT Build | 0:fa2de1b79154 | 44 | { |
| Azure.IoT Build | 0:fa2de1b79154 | 45 | HMACContext ctx; |
| Azure.IoT Build | 0:fa2de1b79154 | 46 | return hmacReset(&ctx, whichSha, key, key_len) || |
| Azure.IoT Build | 0:fa2de1b79154 | 47 | hmacInput(&ctx, text, text_len) || |
| Azure.IoT Build | 0:fa2de1b79154 | 48 | hmacResult(&ctx, digest); |
| Azure.IoT Build | 0:fa2de1b79154 | 49 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 50 | |
| Azure.IoT Build | 0:fa2de1b79154 | 51 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 52 | * hmacReset |
| Azure.IoT Build | 0:fa2de1b79154 | 53 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 54 | * Description: |
| Azure.IoT Build | 0:fa2de1b79154 | 55 | * This function will initialize the hmacContext in preparation |
| Azure.IoT Build | 0:fa2de1b79154 | 56 | * for computing a new HMAC message digest. |
| Azure.IoT Build | 0:fa2de1b79154 | 57 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 58 | * Parameters: |
| Azure.IoT Build | 0:fa2de1b79154 | 59 | * context: [in/out] |
| Azure.IoT Build | 0:fa2de1b79154 | 60 | * The context to reset. |
| Azure.IoT Build | 0:fa2de1b79154 | 61 | * whichSha: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 62 | * One of SHA1, SHA224, SHA256, SHA384, SHA512 |
| Azure.IoT Build | 0:fa2de1b79154 | 63 | * key: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 64 | * The secret shared key. |
| Azure.IoT Build | 0:fa2de1b79154 | 65 | * key_len: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 66 | * The length of the secret shared key. |
| Azure.IoT Build | 0:fa2de1b79154 | 67 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 68 | * Returns: |
| Azure.IoT Build | 0:fa2de1b79154 | 69 | * sha Error Code. |
| Azure.IoT Build | 0:fa2de1b79154 | 70 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 71 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 72 | int hmacReset(HMACContext *ctx, enum SHAversion whichSha, |
| Azure.IoT Build | 0:fa2de1b79154 | 73 | const unsigned char *key, int key_len) |
| Azure.IoT Build | 0:fa2de1b79154 | 74 | { |
| Azure.IoT Build | 0:fa2de1b79154 | 75 | int i, blocksize, hashsize; |
| Azure.IoT Build | 0:fa2de1b79154 | 76 | |
| Azure.IoT Build | 0:fa2de1b79154 | 77 | /* inner padding - key XORd with ipad */ |
| Azure.IoT Build | 0:fa2de1b79154 | 78 | unsigned char k_ipad[USHA_Max_Message_Block_Size]; |
| Azure.IoT Build | 0:fa2de1b79154 | 79 | |
| Azure.IoT Build | 0:fa2de1b79154 | 80 | /* temporary buffer when keylen > blocksize */ |
| Azure.IoT Build | 0:fa2de1b79154 | 81 | unsigned char tempkey[USHAMaxHashSize]; |
| Azure.IoT Build | 0:fa2de1b79154 | 82 | |
| Azure.IoT Build | 0:fa2de1b79154 | 83 | if (!ctx) return shaNull; |
| Azure.IoT Build | 0:fa2de1b79154 | 84 | |
| Azure.IoT Build | 0:fa2de1b79154 | 85 | blocksize = ctx->blockSize = USHABlockSize(whichSha); |
| Azure.IoT Build | 0:fa2de1b79154 | 86 | hashsize = ctx->hashSize = USHAHashSize(whichSha); |
| Azure.IoT Build | 0:fa2de1b79154 | 87 | |
| Azure.IoT Build | 0:fa2de1b79154 | 88 | ctx->whichSha = whichSha; |
| Azure.IoT Build | 0:fa2de1b79154 | 89 | |
| Azure.IoT Build | 0:fa2de1b79154 | 90 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 91 | * If key is longer than the hash blocksize, |
| Azure.IoT Build | 0:fa2de1b79154 | 92 | * reset it to key = HASH(key). |
| Azure.IoT Build | 0:fa2de1b79154 | 93 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 94 | if (key_len > blocksize) { |
| Azure.IoT Build | 0:fa2de1b79154 | 95 | USHAContext tctx; |
| Azure.IoT Build | 0:fa2de1b79154 | 96 | int err = USHAReset(&tctx, whichSha) || |
| Azure.IoT Build | 0:fa2de1b79154 | 97 | USHAInput(&tctx, key, key_len) || |
| Azure.IoT Build | 0:fa2de1b79154 | 98 | USHAResult(&tctx, tempkey); |
| Azure.IoT Build | 0:fa2de1b79154 | 99 | if (err != shaSuccess) return err; |
| Azure.IoT Build | 0:fa2de1b79154 | 100 | |
| Azure.IoT Build | 0:fa2de1b79154 | 101 | key = tempkey; |
| Azure.IoT Build | 0:fa2de1b79154 | 102 | key_len = hashsize; |
| Azure.IoT Build | 0:fa2de1b79154 | 103 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 104 | |
| Azure.IoT Build | 0:fa2de1b79154 | 105 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 106 | * The HMAC transform looks like: |
| Azure.IoT Build | 0:fa2de1b79154 | 107 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 108 | * SHA(K XOR opad, SHA(K XOR ipad, text)) |
| Azure.IoT Build | 0:fa2de1b79154 | 109 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 110 | * where K is an n byte key. |
| Azure.IoT Build | 0:fa2de1b79154 | 111 | * ipad is the byte 0x36 repeated blocksize times |
| Azure.IoT Build | 0:fa2de1b79154 | 112 | * opad is the byte 0x5c repeated blocksize times |
| Azure.IoT Build | 0:fa2de1b79154 | 113 | * and text is the data being protected. |
| Azure.IoT Build | 0:fa2de1b79154 | 114 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 115 | |
| Azure.IoT Build | 0:fa2de1b79154 | 116 | /* store key into the pads, XOR'd with ipad and opad values */ |
| Azure.IoT Build | 0:fa2de1b79154 | 117 | for (i = 0; i < key_len; i++) { |
| Azure.IoT Build | 0:fa2de1b79154 | 118 | k_ipad[i] = key[i] ^ 0x36; |
| Azure.IoT Build | 0:fa2de1b79154 | 119 | ctx->k_opad[i] = key[i] ^ 0x5c; |
| Azure.IoT Build | 0:fa2de1b79154 | 120 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 121 | /* remaining pad bytes are '\0' XOR'd with ipad and opad values */ |
| Azure.IoT Build | 0:fa2de1b79154 | 122 | for (; i < blocksize; i++) { |
| Azure.IoT Build | 0:fa2de1b79154 | 123 | k_ipad[i] = 0x36; |
| Azure.IoT Build | 0:fa2de1b79154 | 124 | ctx->k_opad[i] = 0x5c; |
| Azure.IoT Build | 0:fa2de1b79154 | 125 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 126 | |
| Azure.IoT Build | 0:fa2de1b79154 | 127 | /* perform inner hash */ |
| Azure.IoT Build | 0:fa2de1b79154 | 128 | /* init context for 1st pass */ |
| Azure.IoT Build | 0:fa2de1b79154 | 129 | return USHAReset(&ctx->shaContext, whichSha) || |
| Azure.IoT Build | 0:fa2de1b79154 | 130 | /* and start with inner pad */ |
| Azure.IoT Build | 0:fa2de1b79154 | 131 | USHAInput(&ctx->shaContext, k_ipad, blocksize); |
| Azure.IoT Build | 0:fa2de1b79154 | 132 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 133 | |
| Azure.IoT Build | 0:fa2de1b79154 | 134 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 135 | * hmacInput |
| Azure.IoT Build | 0:fa2de1b79154 | 136 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 137 | * Description: |
| Azure.IoT Build | 0:fa2de1b79154 | 138 | * This function accepts an array of octets as the next portion |
| Azure.IoT Build | 0:fa2de1b79154 | 139 | * of the message. |
| Azure.IoT Build | 0:fa2de1b79154 | 140 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 141 | * Parameters: |
| Azure.IoT Build | 0:fa2de1b79154 | 142 | * context: [in/out] |
| Azure.IoT Build | 0:fa2de1b79154 | 143 | * The HMAC context to update |
| Azure.IoT Build | 0:fa2de1b79154 | 144 | * message_array: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 145 | * An array of characters representing the next portion of |
| Azure.IoT Build | 0:fa2de1b79154 | 146 | * the message. |
| Azure.IoT Build | 0:fa2de1b79154 | 147 | * length: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 148 | * The length of the message in message_array |
| Azure.IoT Build | 0:fa2de1b79154 | 149 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 150 | * Returns: |
| Azure.IoT Build | 0:fa2de1b79154 | 151 | * sha Error Code. |
| Azure.IoT Build | 0:fa2de1b79154 | 152 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 153 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 154 | int hmacInput(HMACContext *ctx, const unsigned char *text, |
| Azure.IoT Build | 0:fa2de1b79154 | 155 | int text_len) |
| Azure.IoT Build | 0:fa2de1b79154 | 156 | { |
| Azure.IoT Build | 0:fa2de1b79154 | 157 | if (!ctx) return shaNull; |
| Azure.IoT Build | 0:fa2de1b79154 | 158 | /* then text of datagram */ |
| Azure.IoT Build | 0:fa2de1b79154 | 159 | return USHAInput(&ctx->shaContext, text, text_len); |
| Azure.IoT Build | 0:fa2de1b79154 | 160 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 161 | |
| Azure.IoT Build | 0:fa2de1b79154 | 162 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 163 | * HMACFinalBits |
| Azure.IoT Build | 0:fa2de1b79154 | 164 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 165 | * Description: |
| Azure.IoT Build | 0:fa2de1b79154 | 166 | * This function will add in any final bits of the message. |
| Azure.IoT Build | 0:fa2de1b79154 | 167 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 168 | * Parameters: |
| Azure.IoT Build | 0:fa2de1b79154 | 169 | * context: [in/out] |
| Azure.IoT Build | 0:fa2de1b79154 | 170 | * The HMAC context to update |
| Azure.IoT Build | 0:fa2de1b79154 | 171 | * message_bits: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 172 | * The final bits of the message, in the upper portion of the |
| Azure.IoT Build | 0:fa2de1b79154 | 173 | * byte. (Use 0b###00000 instead of 0b00000### to input the |
| Azure.IoT Build | 0:fa2de1b79154 | 174 | * three bits ###.) |
| Azure.IoT Build | 0:fa2de1b79154 | 175 | * length: [in] |
| Azure.IoT Build | 0:fa2de1b79154 | 176 | * The number of bits in message_bits, between 1 and 7. |
| Azure.IoT Build | 0:fa2de1b79154 | 177 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 178 | * Returns: |
| Azure.IoT Build | 0:fa2de1b79154 | 179 | * sha Error Code. |
| Azure.IoT Build | 0:fa2de1b79154 | 180 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 181 | int hmacFinalBits(HMACContext *ctx, |
| Azure.IoT Build | 0:fa2de1b79154 | 182 | const uint8_t bits, |
| Azure.IoT Build | 0:fa2de1b79154 | 183 | unsigned int bitcount) |
| Azure.IoT Build | 0:fa2de1b79154 | 184 | { |
| Azure.IoT Build | 0:fa2de1b79154 | 185 | if (!ctx) return shaNull; |
| Azure.IoT Build | 0:fa2de1b79154 | 186 | /* then final bits of datagram */ |
| Azure.IoT Build | 0:fa2de1b79154 | 187 | return USHAFinalBits(&ctx->shaContext, bits, bitcount); |
| Azure.IoT Build | 0:fa2de1b79154 | 188 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 189 | |
| Azure.IoT Build | 0:fa2de1b79154 | 190 | /* |
| Azure.IoT Build | 0:fa2de1b79154 | 191 | * HMACResult |
| Azure.IoT Build | 0:fa2de1b79154 | 192 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 193 | * Description: |
| Azure.IoT Build | 0:fa2de1b79154 | 194 | * This function will return the N-byte message digest into the |
| Azure.IoT Build | 0:fa2de1b79154 | 195 | * Message_Digest array provided by the caller. |
| Azure.IoT Build | 0:fa2de1b79154 | 196 | * NOTE: The first octet of hash is stored in the 0th element, |
| Azure.IoT Build | 0:fa2de1b79154 | 197 | * the last octet of hash in the Nth element. |
| Azure.IoT Build | 0:fa2de1b79154 | 198 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 199 | * Parameters: |
| Azure.IoT Build | 0:fa2de1b79154 | 200 | * context: [in/out] |
| Azure.IoT Build | 0:fa2de1b79154 | 201 | * The context to use to calculate the HMAC hash. |
| Azure.IoT Build | 0:fa2de1b79154 | 202 | * digest: [out] |
| Azure.IoT Build | 0:fa2de1b79154 | 203 | * Where the digest is returned. |
| Azure.IoT Build | 0:fa2de1b79154 | 204 | * NOTE 2: The length of the hash is determined by the value of |
| Azure.IoT Build | 0:fa2de1b79154 | 205 | * whichSha that was passed to hmacReset(). |
| Azure.IoT Build | 0:fa2de1b79154 | 206 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 207 | * Returns: |
| Azure.IoT Build | 0:fa2de1b79154 | 208 | * sha Error Code. |
| Azure.IoT Build | 0:fa2de1b79154 | 209 | * |
| Azure.IoT Build | 0:fa2de1b79154 | 210 | */ |
| Azure.IoT Build | 0:fa2de1b79154 | 211 | int hmacResult(HMACContext *ctx, uint8_t *digest) |
| Azure.IoT Build | 0:fa2de1b79154 | 212 | { |
| Azure.IoT Build | 0:fa2de1b79154 | 213 | if (!ctx) return shaNull; |
| Azure.IoT Build | 0:fa2de1b79154 | 214 | |
| Azure.IoT Build | 0:fa2de1b79154 | 215 | /* finish up 1st pass */ |
| Azure.IoT Build | 0:fa2de1b79154 | 216 | /* (Use digest here as a temporary buffer.) */ |
| Azure.IoT Build | 0:fa2de1b79154 | 217 | return USHAResult(&ctx->shaContext, digest) || |
| Azure.IoT Build | 0:fa2de1b79154 | 218 | |
| Azure.IoT Build | 0:fa2de1b79154 | 219 | /* perform outer SHA */ |
| Azure.IoT Build | 0:fa2de1b79154 | 220 | /* init context for 2nd pass */ |
| AzureIoTClient | 25:8507bf644fdf | 221 | USHAReset(&ctx->shaContext, (SHAversion)ctx->whichSha) || |
| Azure.IoT Build | 0:fa2de1b79154 | 222 | |
| Azure.IoT Build | 0:fa2de1b79154 | 223 | /* start with outer pad */ |
| Azure.IoT Build | 0:fa2de1b79154 | 224 | USHAInput(&ctx->shaContext, ctx->k_opad, ctx->blockSize) || |
| Azure.IoT Build | 0:fa2de1b79154 | 225 | |
| Azure.IoT Build | 0:fa2de1b79154 | 226 | /* then results of 1st hash */ |
| Azure.IoT Build | 0:fa2de1b79154 | 227 | USHAInput(&ctx->shaContext, digest, ctx->hashSize) || |
| Azure.IoT Build | 0:fa2de1b79154 | 228 | |
| Azure.IoT Build | 0:fa2de1b79154 | 229 | /* finish up 2nd pass */ |
| Azure.IoT Build | 0:fa2de1b79154 | 230 | USHAResult(&ctx->shaContext, digest); |
| Azure.IoT Build | 0:fa2de1b79154 | 231 | } |
| Azure.IoT Build | 0:fa2de1b79154 | 232 | |
| Azure.IoT Build | 0:fa2de1b79154 | 233 |
