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