Azure IoT common library

Dependents:   STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more

Committer:
Azure.IoT Build
Date:
Fri Apr 08 12:01:36 2016 -0700
Revision:
0:fa2de1b79154
Child:
19:2e0811512ceb
1.0.4

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