#include "asterisk.h"
#include "asterisk/sha1.h"
Go to the source code of this file.
Defines | |
#define | SHA1CircularShift(bits, word) (((word) << (bits)) | ((word) >> (32-(bits)))) |
Functions | |
int | SHA1Input (SHA1Context *context, const uint8_t *message_array, unsigned length) |
SHA1Input. | |
void | SHA1PadMessage (SHA1Context *context) |
Pad message to be 512 bits. | |
void | SHA1ProcessMessageBlock (SHA1Context *context) |
Process the next 512 bits of the message stored in the Message_Block array. | |
int | SHA1Reset (SHA1Context *context) |
SHA1Reset. | |
int | SHA1Result (SHA1Context *context, uint8_t Message_Digest[SHA1HashSize]) |
SHA1Result. |
Full Copyright Statement
Copyright (C) The Internet Society (2001). All Rights Reserved.
This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Description: This file implements the Secure Hashing Algorithm 1 as defined in FIPS PUB 180-1 published April 17, 1995.
The SHA-1, produces a 160-bit message digest for a given data stream. It should take about 2**n steps to find a message with the same digest as a given message and 2**(n/2) to find any two messages with the same digest, when n is the digest size in bits. Therefore, this algorithm can serve as a means of providing a "fingerprint" for a message.
Portability Issues: SHA-1 is defined in terms of 32-bit "words". This code uses <stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned integer types. If your C compiler does not support 32 bit unsigned integers, this code is not appropriate.
Caveats: SHA-1 is designed to work with messages less than 2^64 bits long. Although SHA-1 allows a message digest to be generated for messages of any number of bits less than 2^64, this implementation only works with messages with a length that is a multiple of the size of an 8-bit character.
Definition in file sha1.c.
#define SHA1CircularShift | ( | bits, | |||
word | ) | (((word) << (bits)) | ((word) >> (32-(bits)))) |
Define the SHA1 circular left shift macro
Definition at line 67 of file sha1.c.
Referenced by SHA1ProcessMessageBlock().
int SHA1Input | ( | SHA1Context * | context, | |
const uint8_t * | message_array, | |||
unsigned | length | |||
) |
SHA1Input.
context | [in/out] The SHA context to update | |
message_array | [in] An array of characters representing the next portion of the message. | |
length | [in] The length of the message in message_array. This function accepts an array of octets as the next portion of the message. |
Definition at line 154 of file sha1.c.
References context, SHA1ProcessMessageBlock(), shaNull, shaStateError, and shaSuccess.
Referenced by ast_sha1_hash().
00155 { 00156 if (!length) { 00157 return shaSuccess; 00158 } 00159 00160 if (!context || !message_array) { 00161 return shaNull; 00162 } 00163 00164 if (context->Computed) { 00165 context->Corrupted = shaStateError; 00166 return shaStateError; 00167 } 00168 00169 if (context->Corrupted) { 00170 return context->Corrupted; 00171 } 00172 00173 while (length-- && !context->Corrupted) { 00174 context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF); 00175 00176 context->Length_Low += 8; 00177 if (context->Length_Low == 0) { 00178 context->Length_High++; 00179 if (context->Length_High == 0) { 00180 /* Message is too long */ 00181 context->Corrupted = 1; 00182 } 00183 } 00184 00185 if (context->Message_Block_Index == 64) { 00186 SHA1ProcessMessageBlock(context); 00187 } 00188 00189 message_array++; 00190 } 00191 00192 return shaSuccess; 00193 }
void SHA1PadMessage | ( | SHA1Context * | context | ) |
Pad message to be 512 bits.
context | [in/out] The context to pad. |
Definition at line 298 of file sha1.c.
References context, and SHA1ProcessMessageBlock().
Referenced by SHA1Result().
00299 { 00300 /* 00301 * Check to see if the current message block is too small to hold 00302 * the initial padding bits and length. If so, we will pad the 00303 * block, process it, and then continue padding into a second 00304 * block. 00305 */ 00306 if (context->Message_Block_Index > 55) { 00307 context->Message_Block[context->Message_Block_Index++] = 0x80; 00308 while (context->Message_Block_Index < 64) { 00309 context->Message_Block[context->Message_Block_Index++] = 0; 00310 } 00311 00312 SHA1ProcessMessageBlock(context); 00313 00314 while (context->Message_Block_Index < 56) { 00315 context->Message_Block[context->Message_Block_Index++] = 0; 00316 } 00317 } else { 00318 context->Message_Block[context->Message_Block_Index++] = 0x80; 00319 while (context->Message_Block_Index < 56) { 00320 context->Message_Block[context->Message_Block_Index++] = 0; 00321 } 00322 } 00323 00324 /* 00325 * Store the message length as the last 8 octets 00326 */ 00327 context->Message_Block[56] = context->Length_High >> 24; 00328 context->Message_Block[57] = context->Length_High >> 16; 00329 context->Message_Block[58] = context->Length_High >> 8; 00330 context->Message_Block[59] = context->Length_High; 00331 context->Message_Block[60] = context->Length_Low >> 24; 00332 context->Message_Block[61] = context->Length_Low >> 16; 00333 context->Message_Block[62] = context->Length_Low >> 8; 00334 context->Message_Block[63] = context->Length_Low; 00335 00336 SHA1ProcessMessageBlock(context); 00337 }
void SHA1ProcessMessageBlock | ( | SHA1Context * | context | ) |
Process the next 512 bits of the message stored in the Message_Block array.
context | [in/out] The SHA context to update |
Definition at line 203 of file sha1.c.
References context, and SHA1CircularShift.
Referenced by SHA1Input(), and SHA1PadMessage().
00204 { 00205 const uint32_t K[] = { /* Constants defined in SHA-1 */ 00206 0x5A827999, 00207 0x6ED9EBA1, 00208 0x8F1BBCDC, 00209 0xCA62C1D6 00210 }; 00211 int t; /* Loop counter */ 00212 uint32_t temp; /* Temporary word value */ 00213 uint32_t W[80]; /* Word sequence */ 00214 uint32_t A, B, C, D, E; /* Word buffers */ 00215 00216 /* 00217 * Initialize the first 16 words in the array W 00218 */ 00219 for (t = 0; t < 16; t++) { 00220 W[t] = context->Message_Block[t * 4] << 24; 00221 W[t] |= context->Message_Block[t * 4 + 1] << 16; 00222 W[t] |= context->Message_Block[t * 4 + 2] << 8; 00223 W[t] |= context->Message_Block[t * 4 + 3]; 00224 } 00225 00226 for (t = 16; t < 80; t++) { 00227 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 00228 } 00229 00230 A = context->Intermediate_Hash[0]; 00231 B = context->Intermediate_Hash[1]; 00232 C = context->Intermediate_Hash[2]; 00233 D = context->Intermediate_Hash[3]; 00234 E = context->Intermediate_Hash[4]; 00235 00236 for (t = 0; t < 20; t++) { 00237 temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; 00238 E = D; 00239 D = C; 00240 C = SHA1CircularShift(30,B); 00241 B = A; 00242 A = temp; 00243 } 00244 00245 for (t = 20; t < 40; t++) { 00246 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; 00247 E = D; 00248 D = C; 00249 C = SHA1CircularShift(30,B); 00250 B = A; 00251 A = temp; 00252 } 00253 00254 for (t = 40; t < 60; t++) { 00255 temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; 00256 E = D; 00257 D = C; 00258 C = SHA1CircularShift(30,B); 00259 B = A; 00260 A = temp; 00261 } 00262 00263 for (t = 60; t < 80; t++) { 00264 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; 00265 E = D; 00266 D = C; 00267 C = SHA1CircularShift(30,B); 00268 B = A; 00269 A = temp; 00270 } 00271 00272 context->Intermediate_Hash[0] += A; 00273 context->Intermediate_Hash[1] += B; 00274 context->Intermediate_Hash[2] += C; 00275 context->Intermediate_Hash[3] += D; 00276 context->Intermediate_Hash[4] += E; 00277 00278 context->Message_Block_Index = 0; 00279 }
int SHA1Reset | ( | SHA1Context * | context | ) |
SHA1Reset.
context | the context to be reset. This function will initialize the SHA1Context in preparation for computing a new SHA1 message digest. |
Definition at line 81 of file sha1.c.
References context, shaNull, and shaSuccess.
Referenced by ast_sha1_hash().
00082 { 00083 if (!context) { 00084 return shaNull; 00085 } 00086 00087 context->Length_Low = 0; 00088 context->Length_High = 0; 00089 context->Message_Block_Index = 0; 00090 00091 context->Intermediate_Hash[0] = 0x67452301; 00092 context->Intermediate_Hash[1] = 0xEFCDAB89; 00093 context->Intermediate_Hash[2] = 0x98BADCFE; 00094 context->Intermediate_Hash[3] = 0x10325476; 00095 context->Intermediate_Hash[4] = 0xC3D2E1F0; 00096 00097 context->Computed = 0; 00098 context->Corrupted = 0; 00099 00100 return shaSuccess; 00101 }
int SHA1Result | ( | SHA1Context * | context, | |
uint8_t | Message_Digest[SHA1HashSize] | |||
) |
SHA1Result.
context | [in/out] The context to use to calculate the SHA-1 hash. | |
Message_Digest | [out] Where the digest is returned. This function will return the 160-bit message digest into the Message_Digest array provided by the caller. |
Definition at line 113 of file sha1.c.
References context, SHA1PadMessage(), shaNull, and shaSuccess.
Referenced by ast_sha1_hash().
00115 { 00116 int i; 00117 00118 if (!context || !Message_Digest) { 00119 return shaNull; 00120 } 00121 00122 if (context->Corrupted) { 00123 return context->Corrupted; 00124 } 00125 00126 if (!context->Computed) { 00127 SHA1PadMessage(context); 00128 for (i = 0; i < 64; ++i) { 00129 /* message may be sensitive, clear it out */ 00130 context->Message_Block[i] = 0; 00131 } 00132 context->Length_Low = 0; /* and clear length */ 00133 context->Length_High = 0; 00134 context->Computed = 1; 00135 } 00136 00137 for (i = 0; i < SHA1HashSize; ++i) { 00138 Message_Digest[i] = context->Intermediate_Hash[i >> 2] >> 8 * ( 3 - ( i & 0x03 ) ); 00139 } 00140 00141 return shaSuccess; 00142 }