Demo using MBED TLS

Dependencies:   EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed

Fork of iothub_client_sample_amqp by Azure IoT

Committer:
markrad
Date:
Thu Jan 05 00:20:03 2017 +0000
Revision:
58:f50b97b08851
Sample using MBED TLS

Who changed what in which revision?

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