Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Committer:
AzureIoTClient
Date:
Sat Jan 28 09:35:22 2017 -0800
Revision:
19:2e0811512ceb
Parent:
0:fa2de1b79154
Child:
25:8507bf644fdf
1.1.6

Who changed what in which revision?

UserRevisionLine numberNew 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 */
Azure.IoT Build 0:fa2de1b79154 221 USHAReset(&ctx->shaContext, 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