add rap file generation
[iso2ps2.git] / ps2classic / sha1.c
CommitLineData
1de93811
ML
1/*\r
2 * sha1.c\r
3 *\r
4 * Copyright (C) 1998\r
5 * Paul E. Jones <paulej@arid.us>\r
6 * All Rights Reserved\r
7 *\r
8 * This software is licensed as "freeware." Permission to distribute\r
9 * this software in source and binary forms is hereby granted without\r
10 * a fee. THIS SOFTWARE IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED\r
11 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
13 * THE AUTHOR SHALL NOT BE HELD LIABLE FOR ANY DAMAGES RESULTING\r
14 * FROM THE USE OF THIS SOFTWARE, EITHER DIRECTLY OR INDIRECTLY, INCLUDING,\r
15 * BUT NOT LIMITED TO, LOSS OF DATA OR DATA BEING RENDERED INACCURATE.\r
16 *\r
17 *****************************************************************************\r
18 * $Id: sha1.c,v 1.2 2004/03/27 18:00:33 paulej Exp $\r
19 *****************************************************************************\r
20 *\r
21 * Description:\r
22 * This file implements the Secure Hashing Standard as defined\r
23 * in FIPS PUB 180-1 published April 17, 1995.\r
24 *\r
25 * The Secure Hashing Standard, which uses the Secure Hashing\r
26 * Algorithm (SHA), produces a 160-bit message digest for a\r
27 * given data stream. In theory, it is highly improbable that\r
28 * two messages will produce the same message digest. Therefore,\r
29 * this algorithm can serve as a means of providing a "fingerprint"\r
30 * for a message.\r
31 *\r
32 * Portability Issues:\r
33 * SHA-1 is defined in terms of 32-bit "words". This code was\r
34 * written with the expectation that the processor has at least\r
35 * a 32-bit machine word size. If the machine word size is larger,\r
36 * the code should still function properly. One caveat to that\r
37 * is that the input functions taking characters and character\r
38 * arrays assume that only 8 bits of information are stored in each\r
39 * character.\r
40 *\r
41 * Caveats:\r
42 * SHA-1 is designed to work with messages less than 2^64 bits\r
43 * long. Although SHA-1 allows a message digest to be generated for\r
44 * messages of any number of bits less than 2^64, this\r
45 * implementation only works with messages with a length that is a\r
46 * multiple of the size of an 8-bit character.\r
47 *\r
48 */\r
49\r
50#include "sha1.h"\r
51\r
52/*\r
53 * Define the circular shift macro\r
54 */\r
55#define SHA1CircularShift(bits,word) \\r
56 ((((word) << (bits)) & 0xFFFFFFFF) | \\r
57 ((word) >> (32-(bits))))\r
58\r
59/* Function prototypes */\r
60void SHA1ProcessMessageBlock(SHA1Context *);\r
61void SHA1PadMessage(SHA1Context *);\r
62\r
63/* \r
64 * SHA1Reset\r
65 *\r
66 * Description:\r
67 * This function will initialize the SHA1Context in preparation\r
68 * for computing a new message digest.\r
69 *\r
70 * Parameters:\r
71 * context: [in/out]\r
72 * The context to reset.\r
73 *\r
74 * Returns:\r
75 * Nothing.\r
76 *\r
77 * Comments:\r
78 *\r
79 */\r
80void SHA1Reset(SHA1Context *context)\r
81{\r
82 context->Length_Low = 0;\r
83 context->Length_High = 0;\r
84 context->Message_Block_Index = 0;\r
85\r
86 context->Message_Digest[0] = 0x67452301;\r
87 context->Message_Digest[1] = 0xEFCDAB89;\r
88 context->Message_Digest[2] = 0x98BADCFE;\r
89 context->Message_Digest[3] = 0x10325476;\r
90 context->Message_Digest[4] = 0xC3D2E1F0;\r
91\r
92 context->Computed = 0;\r
93 context->Corrupted = 0;\r
94}\r
95\r
96/* \r
97 * SHA1Result\r
98 *\r
99 * Description:\r
100 * This function will return the 160-bit message digest into the\r
101 * Message_Digest array within the SHA1Context provided\r
102 *\r
103 * Parameters:\r
104 * context: [in/out]\r
105 * The context to use to calculate the SHA-1 hash.\r
106 *\r
107 * Returns:\r
108 * 1 if successful, 0 if it failed.\r
109 *\r
110 * Comments:\r
111 *\r
112 */\r
113int SHA1Result(SHA1Context *context)\r
114{\r
115\r
116 if (context->Corrupted)\r
117 {\r
118 return 0;\r
119 }\r
120\r
121 if (!context->Computed)\r
122 {\r
123 SHA1PadMessage(context);\r
124 context->Computed = 1;\r
125 }\r
126\r
127 return 1;\r
128}\r
129\r
130/* \r
131 * SHA1Input\r
132 *\r
133 * Description:\r
134 * This function accepts an array of octets as the next portion of\r
135 * the message.\r
136 *\r
137 * Parameters:\r
138 * context: [in/out]\r
139 * The SHA-1 context to update\r
140 * message_array: [in]\r
141 * An array of characters representing the next portion of the\r
142 * message.\r
143 * length: [in]\r
144 * The length of the message in message_array\r
145 *\r
146 * Returns:\r
147 * Nothing.\r
148 *\r
149 * Comments:\r
150 *\r
151 */\r
152void SHA1Input( SHA1Context *context,\r
153 const unsigned char *message_array,\r
154 unsigned length)\r
155{\r
156 if (!length)\r
157 {\r
158 return;\r
159 }\r
160\r
161 if (context->Computed || context->Corrupted)\r
162 {\r
163 context->Corrupted = 1;\r
164 return;\r
165 }\r
166\r
167 while(length-- && !context->Corrupted)\r
168 {\r
169 context->Message_Block[context->Message_Block_Index++] =\r
170 (*message_array & 0xFF);\r
171\r
172 context->Length_Low += 8;\r
173 /* Force it to 32 bits */\r
174 context->Length_Low &= 0xFFFFFFFF;\r
175 if (context->Length_Low == 0)\r
176 {\r
177 context->Length_High++;\r
178 /* Force it to 32 bits */\r
179 context->Length_High &= 0xFFFFFFFF;\r
180 if (context->Length_High == 0)\r
181 {\r
182 /* Message is too long */\r
183 context->Corrupted = 1;\r
184 }\r
185 }\r
186\r
187 if (context->Message_Block_Index == 64)\r
188 {\r
189 SHA1ProcessMessageBlock(context);\r
190 }\r
191\r
192 message_array++;\r
193 }\r
194}\r
195\r
196/* \r
197 * SHA1ProcessMessageBlock\r
198 *\r
199 * Description:\r
200 * This function will process the next 512 bits of the message\r
201 * stored in the Message_Block array.\r
202 *\r
203 * Parameters:\r
204 * None.\r
205 *\r
206 * Returns:\r
207 * Nothing.\r
208 *\r
209 * Comments:\r
210 * Many of the variable names in the SHAContext, especially the\r
211 * single character names, were used because those were the names\r
212 * used in the publication.\r
213 * \r
214 *\r
215 */\r
216void SHA1ProcessMessageBlock(SHA1Context *context)\r
217{\r
218 const unsigned K[] = /* Constants defined in SHA-1 */ \r
219 {\r
220 0x5A827999,\r
221 0x6ED9EBA1,\r
222 0x8F1BBCDC,\r
223 0xCA62C1D6\r
224 };\r
225 int t; /* Loop counter */\r
226 unsigned temp; /* Temporary word value */\r
227 unsigned W[80]; /* Word sequence */\r
228 unsigned A, B, C, D, E; /* Word buffers */\r
229\r
230 /*\r
231 * Initialize the first 16 words in the array W\r
232 */\r
233 for(t = 0; t < 16; t++)\r
234 {\r
235 W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;\r
236 W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;\r
237 W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;\r
238 W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);\r
239 }\r
240\r
241 for(t = 16; t < 80; t++)\r
242 {\r
243 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);\r
244 }\r
245\r
246 A = context->Message_Digest[0];\r
247 B = context->Message_Digest[1];\r
248 C = context->Message_Digest[2];\r
249 D = context->Message_Digest[3];\r
250 E = context->Message_Digest[4];\r
251\r
252 for(t = 0; t < 20; t++)\r
253 {\r
254 temp = SHA1CircularShift(5,A) +\r
255 ((B & C) | ((~B) & D)) + E + W[t] + K[0];\r
256 temp &= 0xFFFFFFFF;\r
257 E = D;\r
258 D = C;\r
259 C = SHA1CircularShift(30,B);\r
260 B = A;\r
261 A = temp;\r
262 }\r
263\r
264 for(t = 20; t < 40; t++)\r
265 {\r
266 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];\r
267 temp &= 0xFFFFFFFF;\r
268 E = D;\r
269 D = C;\r
270 C = SHA1CircularShift(30,B);\r
271 B = A;\r
272 A = temp;\r
273 }\r
274\r
275 for(t = 40; t < 60; t++)\r
276 {\r
277 temp = SHA1CircularShift(5,A) +\r
278 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];\r
279 temp &= 0xFFFFFFFF;\r
280 E = D;\r
281 D = C;\r
282 C = SHA1CircularShift(30,B);\r
283 B = A;\r
284 A = temp;\r
285 }\r
286\r
287 for(t = 60; t < 80; t++)\r
288 {\r
289 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];\r
290 temp &= 0xFFFFFFFF;\r
291 E = D;\r
292 D = C;\r
293 C = SHA1CircularShift(30,B);\r
294 B = A;\r
295 A = temp;\r
296 }\r
297\r
298 context->Message_Digest[0] =\r
299 (context->Message_Digest[0] + A) & 0xFFFFFFFF;\r
300 context->Message_Digest[1] =\r
301 (context->Message_Digest[1] + B) & 0xFFFFFFFF;\r
302 context->Message_Digest[2] =\r
303 (context->Message_Digest[2] + C) & 0xFFFFFFFF;\r
304 context->Message_Digest[3] =\r
305 (context->Message_Digest[3] + D) & 0xFFFFFFFF;\r
306 context->Message_Digest[4] =\r
307 (context->Message_Digest[4] + E) & 0xFFFFFFFF;\r
308\r
309 context->Message_Block_Index = 0;\r
310}\r
311\r
312/* \r
313 * SHA1PadMessage\r
314 *\r
315 * Description:\r
316 * According to the standard, the message must be padded to an even\r
317 * 512 bits. The first padding bit must be a '1'. The last 64\r
318 * bits represent the length of the original message. All bits in\r
319 * between should be 0. This function will pad the message\r
320 * according to those rules by filling the Message_Block array\r
321 * accordingly. It will also call SHA1ProcessMessageBlock()\r
322 * appropriately. When it returns, it can be assumed that the\r
323 * message digest has been computed.\r
324 *\r
325 * Parameters:\r
326 * context: [in/out]\r
327 * The context to pad\r
328 *\r
329 * Returns:\r
330 * Nothing.\r
331 *\r
332 * Comments:\r
333 *\r
334 */\r
335void SHA1PadMessage(SHA1Context *context)\r
336{\r
337 /*\r
338 * Check to see if the current message block is too small to hold\r
339 * the initial padding bits and length. If so, we will pad the\r
340 * block, process it, and then continue padding into a second\r
341 * block.\r
342 */\r
343 if (context->Message_Block_Index > 55)\r
344 {\r
345 context->Message_Block[context->Message_Block_Index++] = 0x80;\r
346 while(context->Message_Block_Index < 64)\r
347 {\r
348 context->Message_Block[context->Message_Block_Index++] = 0;\r
349 }\r
350\r
351 SHA1ProcessMessageBlock(context);\r
352\r
353 while(context->Message_Block_Index < 56)\r
354 {\r
355 context->Message_Block[context->Message_Block_Index++] = 0;\r
356 }\r
357 }\r
358 else\r
359 {\r
360 context->Message_Block[context->Message_Block_Index++] = 0x80;\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\r
367 /*\r
368 * Store the message length as the last 8 octets\r
369 */\r
370 context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;\r
371 context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;\r
372 context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;\r
373 context->Message_Block[59] = (context->Length_High) & 0xFF;\r
374 context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;\r
375 context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;\r
376 context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;\r
377 context->Message_Block[63] = (context->Length_Low) & 0xFF;\r
378\r
379 SHA1ProcessMessageBlock(context);\r
380}\r