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.
Fork of azure_c_shared_utility by
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 Tue Jul 12 2022 19:14:38 by
