Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

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