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 sha224.c Source File

sha224.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 /*************************** sha224-256.c ***************************/
00005 /********************* See RFC 4634 for details *********************/
00006 /*
00007 * Description:
00008 *   This file implements the Secure Hash Signature Standard
00009 *   algorithms as defined in the National Institute of Standards
00010 *   and Technology Federal Information Processing Standards
00011 *   Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
00012 *   published on August 1, 2002, and the FIPS PUB 180-2 Change
00013 *   Notice published on February 28, 2004.
00014 *
00015 *   A combined document showing all algorithms is available at
00016 *       http://csrc.nist.gov/publications/fips/
00017 *       fips180-2/fips180-2withchangenotice.pdf
00018 *
00019 *   The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
00020 *   message digests for a given data stream. It should take about
00021 *   2**n steps to find a message with the same digest as a given
00022 *   message and 2**(n/2) to find any two messages with the same
00023 *   digest, when n is the digest size in bits. Therefore, this
00024 *   algorithm can serve as a means of providing a
00025 *   "fingerprint" for a message.
00026 *
00027 * Portability Issues:
00028 *   SHA-224 and SHA-256 are defined in terms of 32-bit "words".
00029 *   This code uses <stdint.h> (included via "sha.h") to define 32
00030 *   and 8 bit unsigned integer types. If your C compiler does not
00031 *   support 32 bit unsigned integers, this code is not
00032 *   appropriate.
00033 *
00034 * Caveats:
00035 *   SHA-224 and SHA-256 are designed to work with messages less
00036 *   than 2^64 bits long. This implementation uses SHA224/256Input()
00037 *   to hash the bits that are a multiple of the size of an 8-bit
00038 *   character, and then uses SHA224/256FinalBits() to hash the
00039 *   final few bits of the input.
00040 */
00041 
00042 #include <stdlib.h>
00043 #ifdef _CRTDBG_MAP_ALLOC
00044 #include <crtdbg.h>
00045 #endif
00046 #include "azure_c_shared_utility/gballoc.h"
00047 
00048 #include "azure_c_shared_utility/sha.h"
00049 #include "azure_c_shared_utility/sha-private.h"
00050 /* Define the SHA shift, rotate left and rotate right macro */
00051 #define SHA256_SHR(bits,word)      ((word) >> (bits))
00052 #define SHA256_ROTL(bits,word)                         \
00053   (((word) << (bits)) | ((word) >> (32-(bits))))
00054 #define SHA256_ROTR(bits,word)                         \
00055   (((word) >> (bits)) | ((word) << (32-(bits))))
00056 
00057 /* Define the SHA SIGMA and sigma macros */
00058 #define SHA256_SIGMA0(word)   \
00059   (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
00060 #define SHA256_SIGMA1(word)   \
00061   (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
00062 #define SHA256_sigma0(word)   \
00063   (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
00064 #define SHA256_sigma1(word)   \
00065   (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
00066 
00067 /*
00068 * add "length" to the length
00069 */
00070 #define SHA224_256AddLength(context, length)               \
00071   (addTemp = (context)->Length_Low, (context)->Corrupted = \
00072     (((context)->Length_Low += (length)) < addTemp) &&     \
00073     (++(context)->Length_High == 0) ? 1 : 0)
00074 
00075 /* Local Function Prototypes */
00076 static void SHA224_256Finalize(SHA256Context *context,
00077     uint8_t Pad_Byte);
00078 static void SHA224_256PadMessage(SHA256Context *context,
00079     uint8_t Pad_Byte);
00080 static void SHA224_256ProcessMessageBlock(SHA256Context *context);
00081 static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
00082 static int SHA224_256ResultN(SHA256Context *context,
00083     uint8_t Message_Digest[], int HashSize);
00084 
00085 /* Initial Hash Values: FIPS-180-2 Change Notice 1 */
00086 static uint32_t SHA224_H0[SHA256HashSize / 4] = {
00087     0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
00088     0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
00089 };
00090 
00091 /* Initial Hash Values: FIPS-180-2 section 5.3.2 */
00092 static uint32_t SHA256_H0[SHA256HashSize / 4] = {
00093     0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
00094     0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
00095 };
00096 
00097 /*
00098 * SHA224Reset
00099 *
00100 * Description:
00101 *   This function will initialize the SHA384Context in preparation
00102 *   for computing a new SHA224 message digest.
00103 *
00104 * Parameters:
00105 *   context: [in/out]
00106 *     The context to reset.
00107 *
00108 * Returns:
00109 *   sha Error Code.
00110 */
00111 int SHA224Reset(SHA224Context *context)
00112 {
00113     return SHA224_256Reset(context, SHA224_H0);
00114 }
00115 
00116 /*
00117 * SHA224Input
00118 *
00119 * Description:
00120 *   This function accepts an array of octets as the next portion
00121 *   of the message.
00122 *
00123 * Parameters:
00124 *   context: [in/out]
00125 *     The SHA context to update
00126 *   message_array: [in]
00127 *     An array of characters representing the next portion of
00128 *     the message.
00129 *   length: [in]
00130 *     The length of the message in message_array
00131 *
00132 * Returns:
00133 *   sha Error Code.
00134 *
00135 */
00136 int SHA224Input(SHA224Context *context, const uint8_t *message_array,
00137     unsigned int length)
00138 {
00139     return SHA256Input(context, message_array, length);
00140 }
00141 
00142 /*
00143 * SHA224FinalBits
00144 *
00145 * Description:
00146 *   This function will add in any final bits of the message.
00147 *
00148 * Parameters:
00149 *   context: [in/out]
00150 *     The SHA context to update
00151 *   message_bits: [in]
00152 *     The final bits of the message, in the upper portion of the
00153 *     byte. (Use 0b###00000 instead of 0b00000### to input the
00154 *     three bits ###.)
00155 *   length: [in]
00156 *     The number of bits in message_bits, between 1 and 7.
00157 *
00158 * Returns:
00159 *   sha Error Code.
00160 */
00161 int SHA224FinalBits(SHA224Context *context,
00162     const uint8_t message_bits, unsigned int length)
00163 {
00164     return SHA256FinalBits(context, message_bits, length);
00165 }
00166 
00167 /*
00168 * SHA224Result
00169 *
00170 * Description:
00171 *   This function will return the 224-bit message
00172 *   digest into the Message_Digest array provided by the caller.
00173 *   NOTE: The first octet of hash is stored in the 0th element,
00174 *      the last octet of hash in the 28th element.
00175 *
00176 * Parameters:
00177 *   context: [in/out]
00178 *     The context to use to calculate the SHA hash.
00179 *   Message_Digest: [out]
00180 *     Where the digest is returned.
00181 *
00182 * Returns:
00183 *   sha Error Code.
00184 */
00185 int SHA224Result(SHA224Context *context,
00186     uint8_t Message_Digest[SHA224HashSize])
00187 {
00188     return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
00189 }
00190 
00191 /*
00192 * SHA256Reset
00193 *
00194 * Description:
00195 *   This function will initialize the SHA256Context in preparation
00196 *   for computing a new SHA256 message digest.
00197 *
00198 * Parameters:
00199 *   context: [in/out]
00200 *     The context to reset.
00201 *
00202 * Returns:
00203 *   sha Error Code.
00204 */
00205 int SHA256Reset(SHA256Context *context)
00206 {
00207     return SHA224_256Reset(context, SHA256_H0);
00208 }
00209 
00210 /*
00211 * SHA256Input
00212 *
00213 * Description:
00214 *   This function accepts an array of octets as the next portion
00215 *   of the message.
00216 *
00217 * Parameters:
00218 *   context: [in/out]
00219 *     The SHA context to update
00220 *   message_array: [in]
00221 *     An array of characters representing the next portion of
00222 *     the message.
00223 *   length: [in]
00224 *     The length of the message in message_array
00225 *
00226 * Returns:
00227 *   sha Error Code.
00228 */
00229 int SHA256Input(SHA256Context *context, const uint8_t *message_array,
00230     unsigned int length)
00231 {
00232     uint32_t addTemp;
00233     if (!length)
00234         return shaSuccess;
00235 
00236     if (!context || !message_array)
00237         return shaNull;
00238 
00239     if (context->Computed) {
00240         context->Corrupted = shaStateError;
00241         return shaStateError;
00242     }
00243 
00244     if (context->Corrupted)
00245         return context->Corrupted;
00246 
00247     while (length-- && !context->Corrupted) {
00248         context->Message_Block[context->Message_Block_Index++] =
00249             (*message_array & 0xFF);
00250 
00251         if (!SHA224_256AddLength(context, 8) &&
00252             (context->Message_Block_Index == SHA256_Message_Block_Size))
00253             SHA224_256ProcessMessageBlock(context);
00254 
00255         message_array++;
00256     }
00257 
00258     return shaSuccess;
00259 
00260 }
00261 
00262 /*
00263 * SHA256FinalBits
00264 *
00265 * Description:
00266 *   This function will add in any final bits of the message.
00267 *
00268 * Parameters:
00269 *   context: [in/out]
00270 *     The SHA context to update
00271 *   message_bits: [in]
00272 *     The final bits of the message, in the upper portion of the
00273 *     byte. (Use 0b###00000 instead of 0b00000### to input the
00274 *     three bits ###.)
00275 *   length: [in]
00276 *     The number of bits in message_bits, between 1 and 7.
00277 *
00278 * Returns:
00279 *   sha Error Code.
00280 */
00281 int SHA256FinalBits(SHA256Context *context,
00282     const uint8_t message_bits, unsigned int length)
00283 {
00284     uint32_t addTemp;
00285     uint8_t masks[8] = {
00286         /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
00287         /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
00288         /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
00289         /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
00290     };
00291 
00292     uint8_t markbit[8] = {
00293         /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
00294         /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
00295         /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
00296         /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
00297     };
00298 
00299     if (!length)
00300         return shaSuccess;
00301 
00302     if (!context)
00303         return shaNull;
00304 
00305     if ((context->Computed) || (length >= 8) || (length == 0)) {
00306         context->Corrupted = shaStateError;
00307         return shaStateError;
00308     }
00309 
00310     if (context->Corrupted)
00311         return context->Corrupted;
00312 
00313     SHA224_256AddLength(context, length);
00314     SHA224_256Finalize(context, (uint8_t)
00315         ((message_bits & masks[length]) | markbit[length]));
00316 
00317     return shaSuccess;
00318 }
00319 
00320 /*
00321 * SHA256Result
00322 *
00323 * Description:
00324 *   This function will return the 256-bit message
00325 *   digest into the Message_Digest array provided by the caller.
00326 *   NOTE: The first octet of hash is stored in the 0th element,
00327 *      the last octet of hash in the 32nd element.
00328 *
00329 * Parameters:
00330 *   context: [in/out]
00331 *     The context to use to calculate the SHA hash.
00332 *   Message_Digest: [out]
00333 *     Where the digest is returned.
00334 *
00335 * Returns:
00336 *   sha Error Code.
00337 */
00338 int SHA256Result(SHA256Context *context, uint8_t Message_Digest[])
00339 {
00340         return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
00341 }
00342 
00343 /*
00344 * SHA224_256Finalize
00345 *
00346 * Description:
00347 *   This helper function finishes off the digest calculations.
00348 *
00349 * Parameters:
00350 *   context: [in/out]
00351 *     The SHA context to update
00352 *   Pad_Byte: [in]
00353 *     The last byte to add to the digest before the 0-padding
00354 *     and length. This will contain the last bits of the message
00355 *     followed by another single bit. If the message was an
00356 *     exact multiple of 8-bits long, Pad_Byte will be 0x80.
00357 *
00358 * Returns:
00359 *   sha Error Code.
00360 */
00361 static void SHA224_256Finalize(SHA256Context *context,
00362     uint8_t Pad_Byte)
00363 {
00364     int i;
00365     SHA224_256PadMessage(context, Pad_Byte);
00366     /* message may be sensitive, so clear it out */
00367     for (i = 0; i < SHA256_Message_Block_Size; ++i)
00368         context->Message_Block[i] = 0;
00369     context->Length_Low = 0;  /* and clear length */
00370     context->Length_High = 0;
00371     context->Computed = 1;
00372 }
00373 
00374 /*
00375 * SHA224_256PadMessage
00376 *
00377 * Description:
00378 *   According to the standard, the message must be padded to an
00379 *   even 512 bits. The first padding bit must be a '1'. The
00380 *   last 64 bits represent the length of the original message.
00381 *   All bits in between should be 0. This helper function will pad
00382 *   the message according to those rules by filling the
00383 *   Message_Block array accordingly. When it returns, it can be
00384 *   assumed that the message digest has been computed.
00385 *
00386 * Parameters:
00387 *   context: [in/out]
00388 *     The context to pad
00389 *   Pad_Byte: [in]
00390 *     The last byte to add to the digest before the 0-padding
00391 *     and length. This will contain the last bits of the message
00392 *     followed by another single bit. If the message was an
00393 *     exact multiple of 8-bits long, Pad_Byte will be 0x80.
00394 *
00395 * Returns:
00396 *   Nothing.
00397 */
00398 static void SHA224_256PadMessage(SHA256Context *context,
00399     uint8_t Pad_Byte)
00400 {
00401     /*
00402     * Check to see if the current message block is too small to hold
00403     * the initial padding bits and length. If so, we will pad the
00404     * block, process it, and then continue padding into a second
00405     * block.
00406     */
00407     if (context->Message_Block_Index >= (SHA256_Message_Block_Size - 8)) {
00408         context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
00409         while (context->Message_Block_Index < SHA256_Message_Block_Size)
00410             context->Message_Block[context->Message_Block_Index++] = 0;
00411         SHA224_256ProcessMessageBlock(context);
00412     }
00413     else
00414         context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
00415 
00416     while (context->Message_Block_Index < (SHA256_Message_Block_Size - 8))
00417         context->Message_Block[context->Message_Block_Index++] = 0;
00418 
00419     /*
00420     * Store the message length as the last 8 octets
00421     */
00422     context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
00423     context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
00424     context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
00425     context->Message_Block[59] = (uint8_t)(context->Length_High);
00426     context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
00427     context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
00428     context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
00429     context->Message_Block[63] = (uint8_t)(context->Length_Low);
00430 
00431     SHA224_256ProcessMessageBlock(context);
00432 }
00433 
00434 /*
00435 * SHA224_256ProcessMessageBlock
00436 *
00437 * Description:
00438 *   This function will process the next 512 bits of the message
00439 *   stored in the Message_Block array.
00440 *
00441 * Parameters:
00442 *   context: [in/out]
00443 *     The SHA context to update
00444 *
00445 * Returns:
00446 *   Nothing.
00447 *
00448 * Comments:
00449 *   Many of the variable names in this code, especially the
00450 *   single character names, were used because those were the
00451 *   names used in the publication.
00452 */
00453 static void SHA224_256ProcessMessageBlock(SHA256Context *context)
00454 {
00455     /* Constants defined in FIPS-180-2, section 4.2.2 */
00456     static const uint32_t K[64] = {
00457         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
00458         0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
00459         0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
00460         0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
00461         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
00462         0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
00463         0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
00464         0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
00465         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
00466         0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
00467         0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
00468         0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
00469         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
00470     };
00471     int        t, t4;                   /* Loop counter */
00472     uint32_t   temp1, temp2;            /* Temporary word value */
00473     uint32_t   W[64];                   /* Word sequence */
00474     uint32_t   A, B, C, D, E, F, G, H;  /* Word buffers */
00475 
00476     /*
00477     * Initialize the first 16 words in the array W
00478     */
00479     for (t = t4 = 0; t < 16; t++, t4 += 4)
00480         W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
00481         (((uint32_t)context->Message_Block[t4 + 1]) << 16) |
00482         (((uint32_t)context->Message_Block[t4 + 2]) << 8) |
00483         (((uint32_t)context->Message_Block[t4 + 3]));
00484 
00485     for (t = 16; t < 64; t++)
00486         W[t] = SHA256_sigma1(W[t - 2]) + W[t - 7] +
00487         SHA256_sigma0(W[t - 15]) + W[t - 16];
00488 
00489     A = context->Intermediate_Hash[0];
00490     B = context->Intermediate_Hash[1];
00491     C = context->Intermediate_Hash[2];
00492     D = context->Intermediate_Hash[3];
00493     E = context->Intermediate_Hash[4];
00494     F = context->Intermediate_Hash[5];
00495     G = context->Intermediate_Hash[6];
00496     H = context->Intermediate_Hash[7];
00497 
00498     for (t = 0; t < 64; t++) {
00499         temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E, F, G) + K[t] + W[t];
00500         temp2 = SHA256_SIGMA0(A) + SHA_Maj(A, B, C);
00501         H = G;
00502         G = F;
00503         F = E;
00504         E = D + temp1;
00505         D = C;
00506         C = B;
00507         B = A;
00508         A = temp1 + temp2;
00509     }
00510 
00511     context->Intermediate_Hash[0] += A;
00512     context->Intermediate_Hash[1] += B;
00513     context->Intermediate_Hash[2] += C;
00514     context->Intermediate_Hash[3] += D;
00515     context->Intermediate_Hash[4] += E;
00516     context->Intermediate_Hash[5] += F;
00517     context->Intermediate_Hash[6] += G;
00518     context->Intermediate_Hash[7] += H;
00519 
00520     context->Message_Block_Index = 0;
00521 }
00522 
00523 /*
00524 * SHA224_256Reset
00525 *
00526 * Description:
00527 *   This helper function will initialize the SHA256Context in
00528 *   preparation for computing a new SHA256 message digest.
00529 *
00530 * Parameters:
00531 *   context: [in/out]
00532 *     The context to reset.
00533 *   H0
00534 *     The initial hash value to use.
00535 *
00536 * Returns:
00537 *   sha Error Code.
00538 */
00539 static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
00540 {
00541     if (!context)
00542         return shaNull;
00543 
00544     context->Length_Low = 0;
00545     context->Length_High = 0;
00546     context->Message_Block_Index = 0;
00547 
00548     context->Intermediate_Hash[0] = H0[0];
00549     context->Intermediate_Hash[1] = H0[1];
00550     context->Intermediate_Hash[2] = H0[2];
00551     context->Intermediate_Hash[3] = H0[3];
00552     context->Intermediate_Hash[4] = H0[4];
00553     context->Intermediate_Hash[5] = H0[5];
00554     context->Intermediate_Hash[6] = H0[6];
00555     context->Intermediate_Hash[7] = H0[7];
00556 
00557     context->Computed = 0;
00558     context->Corrupted = 0;
00559 
00560     return shaSuccess;
00561 }
00562 
00563 /*
00564 * SHA224_256ResultN
00565 *
00566 * Description:
00567 *   This helper function will return the 224-bit or 256-bit message
00568 *   digest into the Message_Digest array provided by the caller.
00569 *   NOTE: The first octet of hash is stored in the 0th element,
00570 *      the last octet of hash in the 28th/32nd element.
00571 *
00572 * Parameters:
00573 *   context: [in/out]
00574 *     The context to use to calculate the SHA hash.
00575 *   Message_Digest: [out]
00576 *     Where the digest is returned.
00577 *   HashSize: [in]
00578 *     The size of the hash, either 28 or 32.
00579 *
00580 * Returns:
00581 *   sha Error Code.
00582 */
00583 static int SHA224_256ResultN(SHA256Context *context,
00584     uint8_t Message_Digest[], int HashSize)
00585 {
00586     int i;
00587 
00588     if (!context || !Message_Digest)
00589         return shaNull;
00590 
00591     if (context->Corrupted)
00592         return context->Corrupted;
00593 
00594     if (!context->Computed)
00595         SHA224_256Finalize(context, 0x80);
00596 
00597     for (i = 0; i < HashSize; ++i)
00598         Message_Digest[i] = (uint8_t)
00599         (context->Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
00600 
00601     return shaSuccess;
00602 }
00603