Mark Radbourne / Mbed 2 deprecated iothub_client_sample_amqp

Dependencies:   EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed

Fork of iothub_client_sample_amqp by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hmac.c Source File

hmac.c

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 /**************************** hmac.c ****************************/
00005 /******************** See RFC 4634 for details ******************/
00006 /*
00007 *  Description:
00008 *      This file implements the HMAC algorithm (Keyed-Hashing for
00009 *      Message Authentication, RFC2104), expressed in terms of the
00010 *      various SHA algorithms.
00011 */
00012 
00013 #include <stdlib.h>
00014 #ifdef _CRTDBG_MAP_ALLOC
00015 #include <crtdbg.h>
00016 #endif
00017 #include "azure_c_shared_utility/gballoc.h"
00018 
00019 #include "azure_c_shared_utility/sha.h"
00020 
00021 /*
00022 *  hmac
00023 *
00024 *  Description:
00025 *      This function will compute an HMAC message digest.
00026 *
00027 *  Parameters:
00028 *      whichSha: [in]
00029 *          One of SHA1, SHA224, SHA256, SHA384, SHA512
00030 *      key: [in]
00031 *          The secret shared key.
00032 *      key_len: [in]
00033 *          The length of the secret shared key.
00034 *      message_array: [in]
00035 *          An array of characters representing the message.
00036 *      length: [in]
00037 *          The length of the message in message_array
00038 *      digest: [out]
00039 *          Where the digest is returned.
00040 *          NOTE: The length of the digest is determined by
00041 *              the value of whichSha.
00042 *
00043 *  Returns:
00044 *      sha Error Code.
00045 *
00046 */
00047 int hmac(SHAversion whichSha, const unsigned char *text, int text_len,
00048     const unsigned char *key, int key_len,
00049     uint8_t digest[USHAMaxHashSize])
00050 {
00051     HMACContext ctx;
00052     return hmacReset(&ctx, whichSha, key, key_len) ||
00053         hmacInput(&ctx, text, text_len) ||
00054         hmacResult(&ctx, digest);
00055 }
00056 
00057 /*
00058 *  hmacReset
00059 *
00060 *  Description:
00061 *      This function will initialize the hmacContext in preparation
00062 *      for computing a new HMAC message digest.
00063 *
00064 *  Parameters:
00065 *      context: [in/out]
00066 *          The context to reset.
00067 *      whichSha: [in]
00068 *          One of SHA1, SHA224, SHA256, SHA384, SHA512
00069 *      key: [in]
00070 *          The secret shared key.
00071 *      key_len: [in]
00072 *          The length of the secret shared key.
00073 *
00074 *  Returns:
00075 *      sha Error Code.
00076 *
00077 */
00078 int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
00079     const unsigned char *key, int key_len)
00080 {
00081     int i, blocksize, hashsize;
00082 
00083     /* inner padding - key XORd with ipad */
00084     unsigned char k_ipad[USHA_Max_Message_Block_Size];
00085 
00086     /* temporary buffer when keylen > blocksize */
00087     unsigned char tempkey[USHAMaxHashSize];
00088 
00089     if (!ctx) return shaNull;
00090 
00091     blocksize = ctx->blockSize = USHABlockSize(whichSha);
00092     hashsize = ctx->hashSize = USHAHashSize(whichSha);
00093 
00094     ctx->whichSha = whichSha;
00095 
00096     /*
00097     * If key is longer than the hash blocksize,
00098     * reset it to key = HASH(key).
00099     */
00100     if (key_len > blocksize) {
00101         USHAContext tctx;
00102         int err = USHAReset(&tctx, whichSha) ||
00103             USHAInput(&tctx, key, key_len) ||
00104             USHAResult(&tctx, tempkey);
00105         if (err != shaSuccess) return err;
00106 
00107         key = tempkey;
00108         key_len = hashsize;
00109     }
00110 
00111     /*
00112     * The HMAC transform looks like:
00113     *
00114     * SHA(K XOR opad, SHA(K XOR ipad, text))
00115     *
00116     * where K is an n byte key.
00117     * ipad is the byte 0x36 repeated blocksize times
00118     * opad is the byte 0x5c repeated blocksize times
00119     * and text is the data being protected.
00120     */
00121 
00122     /* store key into the pads, XOR'd with ipad and opad values */
00123     for (i = 0; i < key_len; i++) {
00124         k_ipad[i] = key[i] ^ 0x36;
00125         ctx->k_opad[i] = key[i] ^ 0x5c;
00126     }
00127     /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
00128     for (; i < blocksize; i++) {
00129         k_ipad[i] = 0x36;
00130         ctx->k_opad[i] = 0x5c;
00131     }
00132 
00133     /* perform inner hash */
00134     /* init context for 1st pass */
00135     return USHAReset(&ctx->shaContext, whichSha) ||
00136         /* and start with inner pad */
00137         USHAInput(&ctx->shaContext, k_ipad, blocksize);
00138 }
00139 
00140 /*
00141 *  hmacInput
00142 *
00143 *  Description:
00144 *      This function accepts an array of octets as the next portion
00145 *      of the message.
00146 *
00147 *  Parameters:
00148 *      context: [in/out]
00149 *          The HMAC context to update
00150 *      message_array: [in]
00151 *          An array of characters representing the next portion of
00152 *          the message.
00153 *      length: [in]
00154 *          The length of the message in message_array
00155 *
00156 *  Returns:
00157 *      sha Error Code.
00158 *
00159 */
00160 int hmacInput(HMACContext *ctx, const unsigned char *text,
00161     int text_len)
00162 {
00163     if (!ctx) return shaNull;
00164     /* then text of datagram */
00165     return USHAInput(&ctx->shaContext, text, text_len);
00166 }
00167 
00168 /*
00169 * HMACFinalBits
00170 *
00171 * Description:
00172 *   This function will add in any final bits of the message.
00173 *
00174 * Parameters:
00175 *   context: [in/out]
00176 *     The HMAC context to update
00177 *   message_bits: [in]
00178 *     The final bits of the message, in the upper portion of the
00179 *     byte. (Use 0b###00000 instead of 0b00000### to input the
00180 *     three bits ###.)
00181 *   length: [in]
00182 *     The number of bits in message_bits, between 1 and 7.
00183 *
00184 * Returns:
00185 *   sha Error Code.
00186 */
00187 int hmacFinalBits(HMACContext *ctx,
00188     const uint8_t bits,
00189     unsigned int bitcount)
00190 {
00191     if (!ctx) return shaNull;
00192     /* then final bits of datagram */
00193     return USHAFinalBits(&ctx->shaContext, bits, bitcount);
00194 }
00195 
00196 /*
00197 * HMACResult
00198 *
00199 * Description:
00200 *   This function will return the N-byte message digest into the
00201 *   Message_Digest array provided by the caller.
00202 *   NOTE: The first octet of hash is stored in the 0th element,
00203 *      the last octet of hash in the Nth element.
00204 *
00205 * Parameters:
00206 *   context: [in/out]
00207 *     The context to use to calculate the HMAC hash.
00208 *   digest: [out]
00209 *     Where the digest is returned.
00210 *   NOTE 2: The length of the hash is determined by the value of
00211 *      whichSha that was passed to hmacReset().
00212 *
00213 * Returns:
00214 *   sha Error Code.
00215 *
00216 */
00217 int hmacResult(HMACContext *ctx, uint8_t *digest)
00218 {
00219     if (!ctx) return shaNull;
00220 
00221     /* finish up 1st pass */
00222     /* (Use digest here as a temporary buffer.) */
00223     return USHAResult(&ctx->shaContext, digest) ||
00224 
00225         /* perform outer SHA */
00226         /* init context for 2nd pass */
00227         USHAReset(&ctx->shaContext, ctx->whichSha) ||
00228 
00229         /* start with outer pad */
00230         USHAInput(&ctx->shaContext, ctx->k_opad, ctx->blockSize) ||
00231 
00232         /* then results of 1st hash */
00233         USHAInput(&ctx->shaContext, digest, ctx->hashSize) ||
00234 
00235         /* finish up 2nd pass */
00236         USHAResult(&ctx->shaContext, digest);
00237 }
00238 
00239