Nigel Rantor / azure_c_shared_utility

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