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.
sha1.c
00001 /* 00002 * sha1.c 00003 * 00004 * Description: 00005 * This file implements the Secure Hashing Algorithm 1 as 00006 * defined in FIPS PUB 180-1 published April 17, 1995. 00007 * 00008 * The SHA-1, produces a 160-bit message digest for a given 00009 * data stream. It should take about 2**n steps to find a 00010 * message with the same digest as a given message and 00011 * 2**(n/2) to find any two messages with the same digest, 00012 * when n is the digest size in bits. Therefore, this 00013 * algorithm can serve as a means of providing a 00014 * "fingerprint" for a message. 00015 * 00016 * Portability Issues: 00017 * SHA-1 is defined in terms of 32-bit "words". This code 00018 * uses <stdint.h> (included via "sha1.h" to define 32 and 8 00019 * bit unsigned integer types. If your C compiler does not 00020 * support 32 bit unsigned integers, this code is not 00021 * appropriate. 00022 * 00023 * Caveats: 00024 * SHA-1 is designed to work with messages less than 2^64 bits 00025 * long. Although SHA-1 allows a message digest to be generated 00026 * for messages of any number of bits less than 2^64, this 00027 * implementation only works with messages with a length that is 00028 * a multiple of the size of an 8-bit character. 00029 * 00030 */ 00031 00032 #include "sha1.h" 00033 00034 00035 /* 00036 * Define the SHA1 circular left shift macro 00037 */ 00038 #define SHA1CircularShift(bits,word) \ 00039 (((word) << (bits)) | ((word) >> (32-(bits)))) 00040 00041 /* Local Function Prototyptes */ 00042 void SHA1PadMessage(SHA1Context *); 00043 void SHA1ProcessMessageBlock(SHA1Context *); 00044 00045 /* 00046 * SHA1Reset 00047 * 00048 * Description: 00049 * This function will initialize the SHA1Context in preparation 00050 * for computing a new SHA1 message digest. 00051 * 00052 * Parameters: 00053 * context: [in/out] 00054 * The context to reset. 00055 * 00056 * Returns: 00057 * sha Error Code. 00058 * 00059 */ 00060 int SHA1Reset(SHA1Context *context) 00061 { 00062 if (!context) 00063 { 00064 return shaNull; 00065 } 00066 00067 context->Length_Low = 0; 00068 context->Length_High = 0; 00069 context->Message_Block_Index = 0; 00070 00071 context->Intermediate_Hash[0] = 0x67452301; 00072 context->Intermediate_Hash[1] = 0xEFCDAB89; 00073 context->Intermediate_Hash[2] = 0x98BADCFE; 00074 context->Intermediate_Hash[3] = 0x10325476; 00075 context->Intermediate_Hash[4] = 0xC3D2E1F0; 00076 00077 context->Computed = 0; 00078 context->Corrupted = 0; 00079 00080 return shaSuccess; 00081 } 00082 00083 /* 00084 * SHA1Result 00085 * 00086 * Description: 00087 * This function will return the 160-bit message digest into the 00088 * Message_Digest array provided by the caller. 00089 * NOTE: The first octet of hash is stored in the 0th element, 00090 * the last octet of hash in the 19th element. 00091 * 00092 * Parameters: 00093 * context: [in/out] 00094 * The context to use to calculate the SHA-1 hash. 00095 * Message_Digest: [out] 00096 * Where the digest is returned. 00097 * 00098 * Returns: 00099 * sha Error Code. 00100 * 00101 */ 00102 int SHA1Result( SHA1Context *context, 00103 uint8_t Message_Digest[SHA1HashSize]) 00104 { 00105 int i; 00106 00107 if (!context || !Message_Digest) 00108 { 00109 return shaNull; 00110 } 00111 00112 if (context->Corrupted) 00113 { 00114 return context->Corrupted; 00115 } 00116 00117 if (!context->Computed) 00118 { 00119 SHA1PadMessage(context); 00120 for(i=0; i<64; ++i) 00121 { 00122 /* message may be sensitive, clear it out */ 00123 context->Message_Block[i] = 0; 00124 } 00125 context->Length_Low = 0; /* and clear length */ 00126 context->Length_High = 0; 00127 context->Computed = 1; 00128 } 00129 00130 for(i = 0; i < SHA1HashSize; ++i) 00131 { 00132 Message_Digest[i] = context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ); 00133 } 00134 00135 return shaSuccess; 00136 } 00137 00138 /* 00139 * SHA1Input 00140 * 00141 * Description: 00142 * This function accepts an array of octets as the next portion 00143 * of the message. 00144 * 00145 * Parameters: 00146 * context: [in/out] 00147 * The SHA context to update 00148 * message_array: [in] 00149 * An array of characters representing the next portion of 00150 * the message. 00151 * length: [in] 00152 * The length of the message in message_array 00153 * 00154 * Returns: 00155 * sha Error Code. 00156 * 00157 */ 00158 int SHA1Input( SHA1Context *context, 00159 const uint8_t *message_array, 00160 unsigned length) 00161 { 00162 if (!length) 00163 { 00164 return shaSuccess; 00165 } 00166 00167 if (!context || !message_array) 00168 { 00169 return shaNull; 00170 } 00171 00172 if (context->Computed) 00173 { 00174 context->Corrupted = shaStateError; 00175 return shaStateError; 00176 } 00177 00178 if (context->Corrupted) 00179 { 00180 return context->Corrupted; 00181 } 00182 while(length-- && !context->Corrupted) 00183 { 00184 context->Message_Block[context->Message_Block_Index++] = 00185 (*message_array & 0xFF); 00186 00187 context->Length_Low += 8; 00188 if (context->Length_Low == 0) 00189 { 00190 context->Length_High++; 00191 if (context->Length_High == 0) 00192 { 00193 /* Message is too long */ 00194 context->Corrupted = 1; 00195 } 00196 } 00197 00198 if (context->Message_Block_Index == 64) 00199 { 00200 SHA1ProcessMessageBlock(context); 00201 } 00202 00203 message_array++; 00204 } 00205 00206 return shaSuccess; 00207 } 00208 00209 /* 00210 * SHA1ProcessMessageBlock 00211 * 00212 * Description: 00213 * This function will process the next 512 bits of the message 00214 * stored in the Message_Block array. 00215 * 00216 * Parameters: 00217 * None. 00218 * 00219 * Returns: 00220 * Nothing. 00221 * 00222 * Comments: 00223 * Many of the variable names in this code, especially the 00224 * single character names, were used because those were the 00225 * names used in the publication. 00226 * 00227 * 00228 */ 00229 void SHA1ProcessMessageBlock(SHA1Context *context) 00230 { 00231 const uint32_t K[] = { /* Constants defined in SHA-1 */ 00232 0x5A827999, 00233 0x6ED9EBA1, 00234 0x8F1BBCDC, 00235 0xCA62C1D6 00236 }; 00237 int t; /* Loop counter */ 00238 uint32_t temp; /* Temporary word value */ 00239 uint32_t W[80]; /* Word sequence */ 00240 uint32_t A, B, C, D, E; /* Word buffers */ 00241 00242 /* 00243 * Initialize the first 16 words in the array W 00244 */ 00245 for(t = 0; t < 16; t++) 00246 { 00247 W[t] = context->Message_Block[t * 4] << 24; 00248 W[t] |= context->Message_Block[t * 4 + 1] << 16; 00249 W[t] |= context->Message_Block[t * 4 + 2] << 8; 00250 W[t] |= context->Message_Block[t * 4 + 3]; 00251 } 00252 00253 for(t = 16; t < 80; t++) 00254 { 00255 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 00256 } 00257 00258 A = context->Intermediate_Hash[0]; 00259 B = context->Intermediate_Hash[1]; 00260 C = context->Intermediate_Hash[2]; 00261 D = context->Intermediate_Hash[3]; 00262 E = context->Intermediate_Hash[4]; 00263 00264 for(t = 0; t < 20; t++) 00265 { 00266 temp = SHA1CircularShift(5,A) + 00267 ((B & C) | ((~B) & D)) + E + W[t] + K[0]; 00268 E = D; 00269 D = C; 00270 C = SHA1CircularShift(30,B); 00271 B = A; 00272 A = temp; 00273 } 00274 00275 for(t = 20; t < 40; t++) 00276 { 00277 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; 00278 E = D; 00279 D = C; 00280 C = SHA1CircularShift(30,B); 00281 B = A; 00282 A = temp; 00283 } 00284 00285 for(t = 40; t < 60; t++) 00286 { 00287 temp = SHA1CircularShift(5,A) + 00288 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; 00289 E = D; 00290 D = C; 00291 C = SHA1CircularShift(30,B); 00292 B = A; 00293 A = temp; 00294 } 00295 00296 for(t = 60; t < 80; t++) 00297 { 00298 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; 00299 E = D; 00300 D = C; 00301 C = SHA1CircularShift(30,B); 00302 B = A; 00303 A = temp; 00304 } 00305 00306 context->Intermediate_Hash[0] += A; 00307 context->Intermediate_Hash[1] += B; 00308 context->Intermediate_Hash[2] += C; 00309 context->Intermediate_Hash[3] += D; 00310 context->Intermediate_Hash[4] += E; 00311 00312 context->Message_Block_Index = 0; 00313 } 00314 00315 00316 /* 00317 * SHA1PadMessage 00318 * 00319 * Description: 00320 * According to the standard, the message must be padded to an even 00321 * 512 bits. The first padding bit must be a '1'. The last 64 00322 * bits represent the length of the original message. All bits in 00323 * between should be 0. This function will pad the message 00324 * according to those rules by filling the Message_Block array 00325 * accordingly. It will also call the ProcessMessageBlock function 00326 * provided appropriately. When it returns, it can be assumed that 00327 * the message digest has been computed. 00328 * 00329 * Parameters: 00330 * context: [in/out] 00331 * The context to pad 00332 * ProcessMessageBlock: [in] 00333 * The appropriate SHA*ProcessMessageBlock function 00334 * Returns: 00335 * Nothing. 00336 * 00337 */ 00338 00339 void SHA1PadMessage(SHA1Context *context) 00340 { 00341 /* 00342 * Check to see if the current message block is too small to hold 00343 * the initial padding bits and length. If so, we will pad the 00344 * block, process it, and then continue padding into a second 00345 * block. 00346 */ 00347 if (context->Message_Block_Index > 55) 00348 { 00349 context->Message_Block[context->Message_Block_Index++] = 0x80; 00350 while(context->Message_Block_Index < 64) 00351 { 00352 context->Message_Block[context->Message_Block_Index++] = 0; 00353 } 00354 00355 SHA1ProcessMessageBlock(context); 00356 00357 while(context->Message_Block_Index < 56) 00358 { 00359 context->Message_Block[context->Message_Block_Index++] = 0; 00360 } 00361 } 00362 else 00363 { 00364 context->Message_Block[context->Message_Block_Index++] = 0x80; 00365 while(context->Message_Block_Index < 56) 00366 { 00367 context->Message_Block[context->Message_Block_Index++] = 0; 00368 } 00369 } 00370 00371 /* 00372 * Store the message length as the last 8 octets 00373 */ 00374 context->Message_Block[56] = context->Length_High >> 24; 00375 context->Message_Block[57] = context->Length_High >> 16; 00376 context->Message_Block[58] = context->Length_High >> 8; 00377 context->Message_Block[59] = context->Length_High; 00378 context->Message_Block[60] = context->Length_Low >> 24; 00379 context->Message_Block[61] = context->Length_Low >> 16; 00380 context->Message_Block[62] = context->Length_Low >> 8; 00381 context->Message_Block[63] = context->Length_Low; 00382 00383 SHA1ProcessMessageBlock(context); 00384 } 00385
Generated on Wed Jul 20 2022 04:19:30 by
1.7.2