Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: azure_umqtt_c iothub_mqtt_transport mbed-rtos mbed wolfSSL Socket lwip-eth lwip-sys lwip
sha1.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 /**************************** sha1.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-1 algorithm produces a 160-bit message digest for a 00020 * given data stream. It should take about 2**n steps to find a 00021 * message with the same digest as a given message and 00022 * 2**(n/2) to find any two messages with the same digest, 00023 * 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-1 is defined in terms of 32-bit "words". This code 00029 * uses <stdint.h> (included via "sha.h") to define 32 and 8 00030 * 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-1 is designed to work with messages less than 2^64 bits 00036 * long. This implementation uses SHA1Input() to hash the bits 00037 * that are a multiple of the size of an 8-bit character, and then 00038 * uses SHA1FinalBits() to hash the final few bits of the input. 00039 */ 00040 00041 #include <stdlib.h> 00042 #ifdef _CRTDBG_MAP_ALLOC 00043 #include <crtdbg.h> 00044 #endif 00045 #include "azure_c_shared_utility/gballoc.h" 00046 00047 #include "azure_c_shared_utility/sha.h" 00048 #include "azure_c_shared_utility/sha-private.h" 00049 00050 /* 00051 * Define the SHA1 circular left shift macro 00052 */ 00053 #define SHA1_ROTL(bits,word) \ 00054 (((word) << (bits)) | ((word) >> (32-(bits)))) 00055 00056 /* 00057 * add "length" to the length 00058 */ 00059 #define SHA1AddLength(context, length) \ 00060 (addTemp = (context)->Length_Low, \ 00061 (context)->Corrupted = \ 00062 (((context)->Length_Low += (length)) < addTemp) && \ 00063 (++(context)->Length_High == 0) ? 1 : 0) 00064 00065 /* Local Function Prototypes */ 00066 static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte); 00067 static void SHA1PadMessage(SHA1Context *, uint8_t Pad_Byte); 00068 static void SHA1ProcessMessageBlock(SHA1Context *); 00069 00070 /* 00071 * SHA1Reset 00072 * 00073 * Description: 00074 * This function will initialize the SHA1Context in preparation 00075 * for computing a new SHA1 message digest. 00076 * 00077 * Parameters: 00078 * context: [in/out] 00079 * The context to reset. 00080 * 00081 * Returns: 00082 * sha Error Code. 00083 * 00084 */ 00085 int SHA1Reset(SHA1Context *context) 00086 { 00087 if (!context) 00088 return shaNull; 00089 00090 context->Length_Low = 0; 00091 context->Length_High = 0; 00092 context->Message_Block_Index = 0; 00093 00094 00095 /* Initial Hash Values: FIPS-180-2 section 5.3.1 */ 00096 context->Intermediate_Hash[0] = 0x67452301; 00097 context->Intermediate_Hash[1] = 0xEFCDAB89; 00098 context->Intermediate_Hash[2] = 0x98BADCFE; 00099 context->Intermediate_Hash[3] = 0x10325476; 00100 context->Intermediate_Hash[4] = 0xC3D2E1F0; 00101 00102 context->Computed = 0; 00103 context->Corrupted = 0; 00104 00105 return shaSuccess; 00106 } 00107 00108 /* 00109 * SHA1Input 00110 * 00111 * Description: 00112 * This function accepts an array of octets as the next portion 00113 * of the message. 00114 * 00115 * Parameters: 00116 * context: [in/out] 00117 * The SHA context to update 00118 * message_array: [in] 00119 * An array of characters representing the next portion of 00120 * the message. 00121 * length: [in] 00122 * The length of the message in message_array 00123 * 00124 * Returns: 00125 * sha Error Code. 00126 * 00127 */ 00128 int SHA1Input(SHA1Context *context, 00129 const uint8_t *message_array, unsigned length) 00130 { 00131 uint32_t addTemp; 00132 if (!length) 00133 return shaSuccess; 00134 00135 if (!context || !message_array) 00136 return shaNull; 00137 00138 if (context->Computed) { 00139 context->Corrupted = shaStateError; 00140 return shaStateError; 00141 } 00142 00143 if (context->Corrupted) 00144 return context->Corrupted; 00145 00146 while (length-- && !context->Corrupted) { 00147 context->Message_Block[context->Message_Block_Index++] = 00148 (*message_array & 0xFF); 00149 00150 if (!SHA1AddLength(context, 8) && 00151 (context->Message_Block_Index == SHA1_Message_Block_Size)) 00152 SHA1ProcessMessageBlock(context); 00153 00154 message_array++; 00155 } 00156 00157 return shaSuccess; 00158 } 00159 00160 /* 00161 * SHA1FinalBits 00162 * 00163 * Description: 00164 * This function will add in any final bits of the message. 00165 * 00166 * Parameters: 00167 * context: [in/out] 00168 * The SHA context to update 00169 * message_bits: [in] 00170 * The final bits of the message, in the upper portion of the 00171 * byte. (Use 0b###00000 instead of 0b00000### to input the 00172 * three bits ###.) 00173 * length: [in] 00174 * The number of bits in message_bits, between 1 and 7. 00175 * 00176 * Returns: 00177 * sha Error Code. 00178 */ 00179 int SHA1FinalBits(SHA1Context *context, const uint8_t message_bits, 00180 unsigned int length) 00181 { 00182 uint32_t addTemp; 00183 00184 uint8_t masks[8] = { 00185 /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80, 00186 /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0, 00187 /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8, 00188 /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE 00189 }; 00190 uint8_t markbit[8] = { 00191 /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40, 00192 /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10, 00193 /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04, 00194 /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01 00195 }; 00196 00197 if (!length) 00198 return shaSuccess; 00199 00200 if (!context) 00201 return shaNull; 00202 00203 if (context->Computed || (length >= 8) || (length == 0)) { 00204 context->Corrupted = shaStateError; 00205 return shaStateError; 00206 } 00207 00208 if (context->Corrupted) 00209 return context->Corrupted; 00210 00211 SHA1AddLength(context, length); 00212 SHA1Finalize(context, 00213 (uint8_t)((message_bits & masks[length]) | markbit[length])); 00214 00215 return shaSuccess; 00216 } 00217 00218 /* 00219 * SHA1Result 00220 * 00221 * Description: 00222 * This function will return the 160-bit message digest into the 00223 * Message_Digest array provided by the caller. 00224 * NOTE: The first octet of hash is stored in the 0th element, 00225 * the last octet of hash in the 19th element. 00226 * 00227 * Parameters: 00228 * context: [in/out] 00229 * The context to use to calculate the SHA-1 hash. 00230 * Message_Digest: [out] 00231 * Where the digest is returned. 00232 * 00233 * Returns: 00234 * sha Error Code. 00235 * 00236 */ 00237 int SHA1Result(SHA1Context *context, 00238 uint8_t Message_Digest[SHA1HashSize]) 00239 { 00240 int i; 00241 00242 if (!context || !Message_Digest) 00243 return shaNull; 00244 00245 if (context->Corrupted) 00246 return context->Corrupted; 00247 00248 if (!context->Computed) 00249 SHA1Finalize(context, 0x80); 00250 00251 for (i = 0; i < SHA1HashSize; ++i) 00252 Message_Digest[i] = (uint8_t)(context->Intermediate_Hash[i >> 2] 00253 >> 8 * (3 - (i & 0x03))); 00254 00255 return shaSuccess; 00256 } 00257 00258 /* 00259 * SHA1Finalize 00260 * 00261 * Description: 00262 * This helper function finishes off the digest calculations. 00263 * 00264 * Parameters: 00265 * context: [in/out] 00266 * The SHA context to update 00267 * Pad_Byte: [in] 00268 * The last byte to add to the digest before the 0-padding 00269 * and length. This will contain the last bits of the message 00270 * followed by another single bit. If the message was an 00271 * exact multiple of 8-bits long, Pad_Byte will be 0x80. 00272 * 00273 * Returns: 00274 * sha Error Code. 00275 * 00276 */ 00277 static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte) 00278 { 00279 int i; 00280 SHA1PadMessage(context, Pad_Byte); 00281 /* message may be sensitive, clear it out */ 00282 for (i = 0; i < SHA1_Message_Block_Size; ++i) 00283 context->Message_Block[i] = 0; 00284 context->Length_Low = 0; /* and clear length */ 00285 context->Length_High = 0; 00286 context->Computed = 1; 00287 } 00288 00289 /* 00290 * SHA1PadMessage 00291 * 00292 * Description: 00293 * According to the standard, the message must be padded to an 00294 * even 512 bits. The first padding bit must be a '1'. The last 00295 * 64 bits represent the length of the original message. All bits 00296 * in between should be 0. This helper function will pad the 00297 * message according to those rules by filling the Message_Block 00298 * array accordingly. When it returns, it can be assumed that the 00299 * message digest has been computed. 00300 * 00301 * Parameters: 00302 * context: [in/out] 00303 * The context to pad 00304 * Pad_Byte: [in] 00305 * The last byte to add to the digest before the 0-padding 00306 * and length. This will contain the last bits of the message 00307 * followed by another single bit. If the message was an 00308 * exact multiple of 8-bits long, Pad_Byte will be 0x80. 00309 * 00310 * Returns: 00311 * Nothing. 00312 */ 00313 static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte) 00314 { 00315 /* 00316 * Check to see if the current message block is too small to hold 00317 * the initial padding bits and length. If so, we will pad the 00318 * block, process it, and then continue padding into a second 00319 * block. 00320 */ 00321 if (context->Message_Block_Index >= (SHA1_Message_Block_Size - 8)) { 00322 context->Message_Block[context->Message_Block_Index++] = Pad_Byte; 00323 while (context->Message_Block_Index < SHA1_Message_Block_Size) 00324 context->Message_Block[context->Message_Block_Index++] = 0; 00325 00326 SHA1ProcessMessageBlock(context); 00327 } 00328 else 00329 context->Message_Block[context->Message_Block_Index++] = Pad_Byte; 00330 00331 while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8)) 00332 context->Message_Block[context->Message_Block_Index++] = 0; 00333 00334 /* 00335 * Store the message length as the last 8 octets 00336 */ 00337 context->Message_Block[56] = (uint8_t)(context->Length_High >> 24); 00338 context->Message_Block[57] = (uint8_t)(context->Length_High >> 16); 00339 00340 context->Message_Block[58] = (uint8_t)(context->Length_High >> 8); 00341 context->Message_Block[59] = (uint8_t)(context->Length_High); 00342 context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24); 00343 context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16); 00344 context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8); 00345 context->Message_Block[63] = (uint8_t)(context->Length_Low); 00346 00347 SHA1ProcessMessageBlock(context); 00348 } 00349 00350 /* 00351 * SHA1ProcessMessageBlock 00352 * 00353 * Description: 00354 * This helper function will process the next 512 bits of the 00355 * message stored in the Message_Block array. 00356 * 00357 * Parameters: 00358 * None. 00359 * 00360 * Returns: 00361 * Nothing. 00362 * 00363 * Comments: 00364 * Many of the variable names in this code, especially the 00365 * single character names, were used because those were the 00366 * names used in the publication. 00367 */ 00368 static void SHA1ProcessMessageBlock(SHA1Context *context) 00369 { 00370 /* Constants defined in FIPS-180-2, section 4.2.1 */ 00371 const uint32_t K[4] = { 00372 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 00373 }; 00374 int t; /* Loop counter */ 00375 uint32_t temp; /* Temporary word value */ 00376 uint32_t W[80]; /* Word sequence */ 00377 uint32_t A, B, C, D, E; /* Word buffers */ 00378 00379 /* 00380 * Initialize the first 16 words in the array W 00381 */ 00382 for (t = 0; t < 16; t++) { 00383 W[t] = ((uint32_t)context->Message_Block[t * 4]) << 24; 00384 W[t] |= ((uint32_t)context->Message_Block[t * 4 + 1]) << 16; 00385 W[t] |= ((uint32_t)context->Message_Block[t * 4 + 2]) << 8; 00386 W[t] |= ((uint32_t)context->Message_Block[t * 4 + 3]); 00387 } 00388 00389 for (t = 16; t < 80; t++) 00390 W[t] = SHA1_ROTL(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); 00391 00392 A = context->Intermediate_Hash[0]; 00393 B = context->Intermediate_Hash[1]; 00394 C = context->Intermediate_Hash[2]; 00395 D = context->Intermediate_Hash[3]; 00396 E = context->Intermediate_Hash[4]; 00397 00398 for (t = 0; t < 20; t++) { 00399 temp = SHA1_ROTL(5, A) + SHA_Ch(B, C, D) + E + W[t] + K[0]; 00400 E = D; 00401 D = C; 00402 C = SHA1_ROTL(30, B); 00403 B = A; 00404 A = temp; 00405 } 00406 00407 for (t = 20; t < 40; t++) { 00408 temp = SHA1_ROTL(5, A) + SHA_Parity(B, C, D) + E + W[t] + K[1]; 00409 E = D; 00410 D = C; 00411 C = SHA1_ROTL(30, B); 00412 B = A; 00413 A = temp; 00414 } 00415 00416 for (t = 40; t < 60; t++) { 00417 temp = SHA1_ROTL(5, A) + SHA_Maj(B, C, D) + E + W[t] + K[2]; 00418 E = D; 00419 D = C; 00420 C = SHA1_ROTL(30, B); 00421 B = A; 00422 A = temp; 00423 } 00424 00425 for (t = 60; t < 80; t++) { 00426 temp = SHA1_ROTL(5, A) + SHA_Parity(B, C, D) + E + W[t] + K[3]; 00427 E = D; 00428 D = C; 00429 C = SHA1_ROTL(30, B); 00430 B = A; 00431 A = temp; 00432 } 00433 00434 context->Intermediate_Hash[0] += A; 00435 context->Intermediate_Hash[1] += B; 00436 context->Intermediate_Hash[2] += C; 00437 00438 context->Intermediate_Hash[3] += D; 00439 context->Intermediate_Hash[4] += E; 00440 00441 context->Message_Block_Index = 0; 00442 } 00443
Generated on Wed Jul 13 2022 07:19:04 by
1.7.2