]> git.saurik.com Git - ldid.git/blame - sha1.c
Add the cryptid= value to decryption report.
[ldid.git] / sha1.c
CommitLineData
fdb119ef
JF
1/*\r
2 * sha1.c\r
3 *\r
4 * Description:\r
5 * This file implements the Secure Hashing Algorithm 1 as\r
6 * defined in FIPS PUB 180-1 published April 17, 1995.\r
7 *\r
8 * The SHA-1, produces a 160-bit message digest for a given\r
9 * data stream. It should take about 2**n steps to find a\r
10 * message with the same digest as a given message and\r
11 * 2**(n/2) to find any two messages with the same digest,\r
12 * when n is the digest size in bits. Therefore, this\r
13 * algorithm can serve as a means of providing a\r
14 * "fingerprint" for a message.\r
15 *\r
16 * Portability Issues:\r
17 * SHA-1 is defined in terms of 32-bit "words". This code\r
18 * uses <stdint.h> (included via "sha1.h" to define 32 and 8\r
19 * bit unsigned integer types. If your C compiler does not\r
20 * support 32 bit unsigned integers, this code is not\r
21 * appropriate.\r
22 *\r
23 * Caveats:\r
24 * SHA-1 is designed to work with messages less than 2^64 bits\r
25 * long. Although SHA-1 allows a message digest to be generated\r
26 * for messages of any number of bits less than 2^64, this\r
27 * implementation only works with messages with a length that is\r
28 * a multiple of the size of an 8-bit character.\r
29 *\r
30 */\r
31\r
32#include "sha1.h"\r
33\r
34/*\r
35 * Define the SHA1 circular left shift macro\r
36 */\r
37#define SHA1CircularShift(bits,word) \\r
38 (((word) << (bits)) | ((word) >> (32-(bits))))\r
39\r
40/* Local Function Prototyptes */\r
41void SHA1PadMessage(SHA1Context *);\r
42void SHA1ProcessMessageBlock(SHA1Context *);\r
43\r
44/*\r
45 * SHA1Reset\r
46 *\r
47 * Description:\r
48 * This function will initialize the SHA1Context in preparation\r
49 * for computing a new SHA1 message digest.\r
50 *\r
51 * Parameters:\r
52 * context: [in/out]\r
53 * The context to reset.\r
54 *\r
55 * Returns:\r
56 * sha Error Code.\r
57 *\r
58 */\r
59int SHA1Reset(SHA1Context *context)\r
60{\r
61 if (!context)\r
62 {\r
63 return shaNull;\r
64 }\r
65\r
66 context->Length_Low = 0;\r
67 context->Length_High = 0;\r
68 context->Message_Block_Index = 0;\r
69\r
70 context->Intermediate_Hash[0] = 0x67452301;\r
71 context->Intermediate_Hash[1] = 0xEFCDAB89;\r
72 context->Intermediate_Hash[2] = 0x98BADCFE;\r
73 context->Intermediate_Hash[3] = 0x10325476;\r
74 context->Intermediate_Hash[4] = 0xC3D2E1F0;\r
75\r
76 context->Computed = 0;\r
77 context->Corrupted = 0;\r
78\r
79 return shaSuccess;\r
80}\r
81\r
82/*\r
83 * SHA1Result\r
84 *\r
85 * Description:\r
86 * This function will return the 160-bit message digest into the\r
87 * Message_Digest array provided by the caller.\r
88 * NOTE: The first octet of hash is stored in the 0th element,\r
89 * the last octet of hash in the 19th element.\r
90 *\r
91 * Parameters:\r
92 * context: [in/out]\r
93 * The context to use to calculate the SHA-1 hash.\r
94 * Message_Digest: [out]\r
95 * Where the digest is returned.\r
96 *\r
97 * Returns:\r
98 * sha Error Code.\r
99 *\r
100 */\r
101int SHA1Result( SHA1Context *context,\r
102 uint8_t Message_Digest[SHA1HashSize])\r
103{\r
104 int i;\r
105\r
106 if (!context || !Message_Digest)\r
107 {\r
108 return shaNull;\r
109 }\r
110\r
111 if (context->Corrupted)\r
112 {\r
113 return context->Corrupted;\r
114 }\r
115\r
116 if (!context->Computed)\r
117 {\r
118 SHA1PadMessage(context);\r
119 for(i=0; i<64; ++i)\r
120 {\r
121 /* message may be sensitive, clear it out */\r
122 context->Message_Block[i] = 0;\r
123 }\r
124 context->Length_Low = 0; /* and clear length */\r
125 context->Length_High = 0;\r
126 context->Computed = 1;\r
127\r
128 }\r
129\r
130 for(i = 0; i < SHA1HashSize; ++i)\r
131 {\r
132 Message_Digest[i] = context->Intermediate_Hash[i>>2]\r
133 >> 8 * ( 3 - ( i & 0x03 ) );\r
134 }\r
135\r
136 return shaSuccess;\r
137}\r
138\r
139/*\r
140 * SHA1Input\r
141 *\r
142 * Description:\r
143 * This function accepts an array of octets as the next portion\r
144 * of the message.\r
145 *\r
146 * Parameters:\r
147 * context: [in/out]\r
148 * The SHA context to update\r
149 * message_array: [in]\r
150 * An array of characters representing the next portion of\r
151 * the message.\r
152 * length: [in]\r
153 * The length of the message in message_array\r
154 *\r
155 * Returns:\r
156 * sha Error Code.\r
157 *\r
158 */\r
159int SHA1Input( SHA1Context *context,\r
160 const uint8_t *message_array,\r
161 unsigned length)\r
162{\r
163 if (!length)\r
164 {\r
165 return shaSuccess;\r
166 }\r
167\r
168 if (!context || !message_array)\r
169 {\r
170 return shaNull;\r
171 }\r
172\r
173 if (context->Computed)\r
174 {\r
175 context->Corrupted = shaStateError;\r
176\r
177 return shaStateError;\r
178 }\r
179\r
180 if (context->Corrupted)\r
181 {\r
182 return context->Corrupted;\r
183 }\r
184 while(length-- && !context->Corrupted)\r
185 {\r
186 context->Message_Block[context->Message_Block_Index++] =\r
187 (*message_array & 0xFF);\r
188\r
189 context->Length_Low += 8;\r
190 if (context->Length_Low == 0)\r
191 {\r
192 context->Length_High++;\r
193 if (context->Length_High == 0)\r
194 {\r
195 /* Message is too long */\r
196 context->Corrupted = 1;\r
197 }\r
198 }\r
199\r
200 if (context->Message_Block_Index == 64)\r
201 {\r
202 SHA1ProcessMessageBlock(context);\r
203 }\r
204\r
205 message_array++;\r
206 }\r
207\r
208 return shaSuccess;\r
209}\r
210\r
211/*\r
212 * SHA1ProcessMessageBlock\r
213 *\r
214 * Description:\r
215 * This function will process the next 512 bits of the message\r
216 * stored in the Message_Block array.\r
217 *\r
218 * Parameters:\r
219 * None.\r
220 *\r
221 * Returns:\r
222 * Nothing.\r
223 *\r
224 * Comments:\r
225\r
226 * Many of the variable names in this code, especially the\r
227 * single character names, were used because those were the\r
228 * names used in the publication.\r
229 *\r
230 *\r
231 */\r
232void SHA1ProcessMessageBlock(SHA1Context *context)\r
233{\r
234 const uint32_t K[] = { /* Constants defined in SHA-1 */\r
235 0x5A827999,\r
236 0x6ED9EBA1,\r
237 0x8F1BBCDC,\r
238 0xCA62C1D6\r
239 };\r
240 int t; /* Loop counter */\r
241 uint32_t temp; /* Temporary word value */\r
242 uint32_t W[80]; /* Word sequence */\r
243 uint32_t A, B, C, D, E; /* Word buffers */\r
244\r
245 /*\r
246 * Initialize the first 16 words in the array W\r
247 */\r
248 for(t = 0; t < 16; t++)\r
249 {\r
250 W[t] = context->Message_Block[t * 4] << 24;\r
251 W[t] |= context->Message_Block[t * 4 + 1] << 16;\r
252 W[t] |= context->Message_Block[t * 4 + 2] << 8;\r
253 W[t] |= context->Message_Block[t * 4 + 3];\r
254 }\r
255\r
256 for(t = 16; t < 80; t++)\r
257 {\r
258 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);\r
259 }\r
260\r
261 A = context->Intermediate_Hash[0];\r
262 B = context->Intermediate_Hash[1];\r
263 C = context->Intermediate_Hash[2];\r
264 D = context->Intermediate_Hash[3];\r
265 E = context->Intermediate_Hash[4];\r
266\r
267 for(t = 0; t < 20; t++)\r
268 {\r
269 temp = SHA1CircularShift(5,A) +\r
270 ((B & C) | ((~B) & D)) + E + W[t] + K[0];\r
271 E = D;\r
272 D = C;\r
273 C = SHA1CircularShift(30,B);\r
274\r
275 B = A;\r
276 A = temp;\r
277 }\r
278\r
279 for(t = 20; t < 40; t++)\r
280 {\r
281 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];\r
282 E = D;\r
283 D = C;\r
284 C = SHA1CircularShift(30,B);\r
285 B = A;\r
286 A = temp;\r
287 }\r
288\r
289 for(t = 40; t < 60; t++)\r
290 {\r
291 temp = SHA1CircularShift(5,A) +\r
292 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];\r
293 E = D;\r
294 D = C;\r
295 C = SHA1CircularShift(30,B);\r
296 B = A;\r
297 A = temp;\r
298 }\r
299\r
300 for(t = 60; t < 80; t++)\r
301 {\r
302 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];\r
303 E = D;\r
304 D = C;\r
305 C = SHA1CircularShift(30,B);\r
306 B = A;\r
307 A = temp;\r
308 }\r
309\r
310 context->Intermediate_Hash[0] += A;\r
311 context->Intermediate_Hash[1] += B;\r
312 context->Intermediate_Hash[2] += C;\r
313 context->Intermediate_Hash[3] += D;\r
314 context->Intermediate_Hash[4] += E;\r
315\r
316 context->Message_Block_Index = 0;\r
317}\r
318\r
319/*\r
320 * SHA1PadMessage\r
321 *\r
322\r
323 * Description:\r
324 * According to the standard, the message must be padded to an even\r
325 * 512 bits. The first padding bit must be a '1'. The last 64\r
326 * bits represent the length of the original message. All bits in\r
327 * between should be 0. This function will pad the message\r
328 * according to those rules by filling the Message_Block array\r
329 * accordingly. It will also call the ProcessMessageBlock function\r
330 * provided appropriately. When it returns, it can be assumed that\r
331 * the message digest has been computed.\r
332 *\r
333 * Parameters:\r
334 * context: [in/out]\r
335 * The context to pad\r
336 * ProcessMessageBlock: [in]\r
337 * The appropriate SHA*ProcessMessageBlock function\r
338 * Returns:\r
339 * Nothing.\r
340 *\r
341 */\r
342\r
343void SHA1PadMessage(SHA1Context *context)\r
344{\r
345 /*\r
346 * Check to see if the current message block is too small to hold\r
347 * the initial padding bits and length. If so, we will pad the\r
348 * block, process it, and then continue padding into a second\r
349 * block.\r
350 */\r
351 if (context->Message_Block_Index > 55)\r
352 {\r
353 context->Message_Block[context->Message_Block_Index++] = 0x80;\r
354 while(context->Message_Block_Index < 64)\r
355 {\r
356 context->Message_Block[context->Message_Block_Index++] = 0;\r
357 }\r
358\r
359 SHA1ProcessMessageBlock(context);\r
360\r
361 while(context->Message_Block_Index < 56)\r
362 {\r
363 context->Message_Block[context->Message_Block_Index++] = 0;\r
364 }\r
365 }\r
366 else\r
367 {\r
368 context->Message_Block[context->Message_Block_Index++] = 0x80;\r
369 while(context->Message_Block_Index < 56)\r
370 {\r
371\r
372 context->Message_Block[context->Message_Block_Index++] = 0;\r
373 }\r
374 }\r
375\r
376 /*\r
377 * Store the message length as the last 8 octets\r
378 */\r
379 context->Message_Block[56] = context->Length_High >> 24;\r
380 context->Message_Block[57] = context->Length_High >> 16;\r
381 context->Message_Block[58] = context->Length_High >> 8;\r
382 context->Message_Block[59] = context->Length_High;\r
383 context->Message_Block[60] = context->Length_Low >> 24;\r
384 context->Message_Block[61] = context->Length_Low >> 16;\r
385 context->Message_Block[62] = context->Length_Low >> 8;\r
386 context->Message_Block[63] = context->Length_Low;\r
387\r
388 SHA1ProcessMessageBlock(context);\r
389}\r