Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8619 | maxcodehac | 1 | /* |
2 | SHA-1 in C |
||
3 | By Steve Reid |
||
4 | 100% Public Domain |
||
5 | |||
6 | ----------------- |
||
7 | Modified 7/98 |
||
8 | By James H. Brown |
||
9 | Still 100% Public Domain |
||
10 | |||
11 | Corrected a problem which generated improper hash values on 16 bit machines |
||
12 | Routine SHA1Update changed from |
||
13 | void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int |
||
14 | len) |
||
15 | to |
||
16 | void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned |
||
17 | long len) |
||
18 | |||
19 | The 'len' parameter was declared an int which works fine on 32 bit machines. |
||
20 | However, on 16 bit machines an int is too small for the shifts being done |
||
21 | against |
||
22 | it. This caused the hash function to generate incorrect values if len was |
||
23 | greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). |
||
24 | |||
25 | Since the file IO in main() reads 16K at a time, any file 8K or larger would |
||
26 | be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million |
||
27 | "a"s). |
||
28 | |||
29 | I also changed the declaration of variables i & j in SHA1Update to |
||
30 | unsigned long from unsigned int for the same reason. |
||
31 | |||
32 | These changes should make no difference to any 32 bit implementations since |
||
33 | an |
||
34 | int and a long are the same size in those environments. |
||
35 | |||
36 | -- |
||
37 | I also corrected a few compiler warnings generated by Borland C. |
||
38 | 1. Added #include |
||
39 | 2. Removed unused variable 'j' in SHA1Final |
||
40 | 3. Changed exit(0) to return(0) at end of main. |
||
41 | |||
42 | ALL changes I made can be located by searching for comments containing 'JHB' |
||
43 | ----------------- |
||
44 | Modified 8/98 |
||
45 | By Steve Reid |
||
46 | Still 100% public domain |
||
47 | |||
48 | 1- Removed #include |
||
49 | 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) |
||
50 | 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net |
||
51 | |||
52 | ----------------- |
||
53 | Modified 4/01 |
||
54 | By Saul Kravitz |
||
55 | Still 100% PD |
||
56 | Modified to run on Compaq Alpha hardware. |
||
57 | |||
58 | ----------------- |
||
59 | Modified 07/2002 |
||
60 | By Ralph Giles |
||
61 | Still 100% public domain |
||
62 | modified for use with stdint types, autoconf |
||
63 | code cleanup, removed attribution comments |
||
64 | switched SHA1Final() argument order for consistency |
||
65 | use SHA1_ prefix for public api |
||
66 | move public api to sha1.h |
||
67 | */ |
||
68 | |||
69 | /* |
||
70 | Test Vectors (from FIPS PUB 180-1) |
||
71 | "abc" |
||
72 | A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D |
||
73 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" |
||
74 | 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 |
||
75 | A million repetitions of "a" |
||
76 | 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F |
||
77 | */ |
||
78 | |||
79 | /* #define SHA1HANDSOFF */ |
||
80 | |||
81 | #ifdef HAVE_CONFIG_H |
||
82 | #include "config.h" |
||
83 | #endif |
||
84 | |||
85 | #include |
||
86 | #include |
||
87 | |||
88 | #include "os_types.h" |
||
89 | #include "sha1.h" |
||
90 | |||
91 | void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]); |
||
92 | |||
93 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
||
94 | |||
95 | /* blk0() and blk() perform the initial expand. */ |
||
96 | /* I got the idea of expanding during the round function from SSLeay */ |
||
97 | /* FIXME: can we do this in an endian-proof way? */ |
||
98 | #ifdef WORDS_BIGENDIAN |
||
99 | #define blk0(i) block->l[i] |
||
100 | #else |
||
101 | #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ |
||
102 | |(rol(block->l[i],8)&0x00FF00FF)) |
||
103 | #endif |
||
104 | #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ |
||
105 | ^block->l[(i+2)&15]^block->l[i&15],1)) |
||
106 | |||
107 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ |
||
108 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); |
||
109 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); |
||
110 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); |
||
111 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); |
||
112 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); |
||
113 | |||
114 | |||
115 | #ifdef VERBOSE /* SAK */ |
||
116 | void SHAPrintContext(SHA1_CTX *context, char *msg){ |
||
117 | printf("%s (%d,%d) %x %x %x %x %x\n", |
||
118 | msg, |
||
119 | context->count[0], context->count[1], |
||
120 | context->state[0], |
||
121 | context->state[1], |
||
122 | context->state[2], |
||
123 | context->state[3], |
||
124 | context->state[4]); |
||
125 | } |
||
126 | #endif /* VERBOSE */ |
||
127 | |||
128 | /* Hash a single 512-bit block. This is the core of the algorithm. */ |
||
129 | void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) |
||
130 | { |
||
131 | uint32_t a, b, c, d, e; |
||
132 | typedef union { |
||
133 | uint8_t c[64]; |
||
134 | uint32_t l[16]; |
||
135 | } CHAR64LONG16; |
||
136 | CHAR64LONG16* block; |
||
137 | |||
138 | #ifdef SHA1HANDSOFF |
||
139 | static uint8_t workspace[64]; |
||
140 | block = (CHAR64LONG16*)workspace; |
||
141 | memcpy(block, buffer, 64); |
||
142 | #else |
||
143 | block = (CHAR64LONG16*)buffer; |
||
144 | #endif |
||
145 | |||
146 | /* Copy context->state[] to working vars */ |
||
147 | a = state[0]; |
||
148 | b = state[1]; |
||
149 | c = state[2]; |
||
150 | d = state[3]; |
||
151 | e = state[4]; |
||
152 | |||
153 | /* 4 rounds of 20 operations each. Loop unrolled. */ |
||
154 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); |
||
155 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); |
||
156 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); |
||
157 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); |
||
158 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); |
||
159 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); |
||
160 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); |
||
161 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); |
||
162 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); |
||
163 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); |
||
164 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); |
||
165 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); |
||
166 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); |
||
167 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); |
||
168 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); |
||
169 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); |
||
170 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); |
||
171 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); |
||
172 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); |
||
173 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); |
||
174 | |||
175 | /* Add the working vars back into context.state[] */ |
||
176 | state[0] += a; |
||
177 | state[1] += b; |
||
178 | state[2] += c; |
||
179 | state[3] += d; |
||
180 | state[4] += e; |
||
181 | |||
182 | /* Wipe variables */ |
||
183 | a = b = c = d = e = 0; |
||
184 | } |
||
185 | |||
186 | |||
187 | /* SHA1Init - Initialize new context */ |
||
188 | void SHA1_Init(SHA1_CTX* context) |
||
189 | { |
||
190 | /* SHA1 initialization constants */ |
||
191 | context->state[0] = 0x67452301; |
||
192 | context->state[1] = 0xEFCDAB89; |
||
193 | context->state[2] = 0x98BADCFE; |
||
194 | context->state[3] = 0x10325476; |
||
195 | context->state[4] = 0xC3D2E1F0; |
||
196 | context->count[0] = context->count[1] = 0; |
||
197 | } |
||
198 | |||
199 | |||
200 | /* Run your data through this. */ |
||
201 | void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len) |
||
202 | { |
||
203 | size_t i, j; |
||
204 | |||
205 | #ifdef VERBOSE |
||
206 | SHAPrintContext(context, "before"); |
||
207 | #endif |
||
208 | |||
209 | j = (context->count[0] >> 3) & 63; |
||
210 | if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; |
||
211 | context->count[1] += (len >> 29); |
||
212 | if ((j + len) > 63) { |
||
213 | memcpy(&context->buffer[j], data, (i = 64-j)); |
||
214 | SHA1_Transform(context->state, context->buffer); |
||
215 | for ( ; i + 63 < len; i += 64) { |
||
216 | SHA1_Transform(context->state, data + i); |
||
217 | } |
||
218 | j = 0; |
||
219 | } |
||
220 | else i = 0; |
||
221 | memcpy(&context->buffer[j], &data[i], len - i); |
||
222 | |||
223 | #ifdef VERBOSE |
||
224 | SHAPrintContext(context, "after "); |
||
225 | #endif |
||
226 | } |
||
227 | |||
228 | |||
229 | /* Add padding and return the message digest. */ |
||
230 | void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE]) |
||
231 | { |
||
232 | uint32_t i; |
||
233 | uint8_t finalcount[8]; |
||
234 | |||
235 | for (i = 0; i < 8; i++) { |
||
236 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] |
||
237 | >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ |
||
238 | } |
||
239 | SHA1_Update(context, (uint8_t *)"\200", 1); |
||
240 | while ((context->count[0] & 504) != 448) { |
||
241 | SHA1_Update(context, (uint8_t *)"\0", 1); |
||
242 | } |
||
243 | SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ |
||
244 | for (i = 0; i < SHA1_DIGEST_SIZE; i++) { |
||
245 | digest[i] = (uint8_t) |
||
246 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); |
||
247 | } |
||
248 | |||
249 | /* Wipe variables */ |
||
250 | i = 0; |
||
251 | memset(context->buffer, 0, 64); |
||
252 | memset(context->state, 0, 20); |
||
253 | memset(context->count, 0, 8); |
||
254 | memset(finalcount, 0, 8); /* SWR */ |
||
255 | |||
256 | #ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ |
||
257 | SHA1_Transform(context->state, context->buffer); |
||
258 | #endif |
||
259 | } |
||
260 | |||
261 | /*************************************************************/ |
||
262 | |||
263 | #if 0 |
||
264 | int main(int argc, char** argv) |
||
265 | { |
||
266 | int i, j; |
||
267 | SHA1_CTX context; |
||
268 | unsigned char digest[SHA1_DIGEST_SIZE], buffer[16384]; |
||
269 | FILE* file; |
||
270 | |||
271 | if (argc > 2) { |
||
272 | puts("Public domain SHA-1 implementation - by Steve Reid |
||
273 | puts("Modified for 16 bit environments 7/98 - by James H. Brown |
||
274 | puts("Produces the SHA-1 hash of a file, or stdin if no file is specified."); |
||
275 | return(0); |
||
276 | } |
||
277 | if (argc < 2) { |
||
278 | file = stdin; |
||
279 | } |
||
280 | else { |
||
281 | if (!(file = fopen(argv[1], "rb"))) { |
||
282 | fputs("Unable to open file.", stderr); |
||
283 | return(-1); |
||
284 | } |
||
285 | } |
||
286 | SHA1_Init(&context); |
||
287 | while (!feof(file)) { /* note: what if ferror(file) */ |
||
288 | i = fread(buffer, 1, 16384, file); |
||
289 | SHA1_Update(&context, buffer, i); |
||
290 | } |
||
291 | SHA1_Final(&context, digest); |
||
292 | fclose(file); |
||
293 | for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) { |
||
294 | for (j = 0; j < 4; j++) { |
||
295 | printf("%02X", digest[i*4+j]); |
||
296 | } |
||
297 | putchar(' '); |
||
298 | } |
||
299 | putchar('\n'); |
||
300 | return(0); /* JHB */ |
||
301 | } |
||
302 | #endif |
||
303 | |||
304 | /* self test */ |
||
305 | |||
306 | #ifdef TEST |
||
307 | |||
308 | static char *test_data[] = { |
||
309 | "abc", |
||
310 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", |
||
311 | "A million repetitions of 'a'"}; |
||
312 | static char *test_results[] = { |
||
313 | "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D", |
||
314 | "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1", |
||
315 | "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"}; |
||
316 | |||
317 | |||
318 | void digest_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], char *output) |
||
319 | { |
||
320 | int i,j; |
||
321 | char *c = output; |
||
322 | |||
323 | for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) { |
||
324 | for (j = 0; j < 4; j++) { |
||
325 | sprintf(c,"%02X", digest[i*4+j]); |
||
326 | c += 2; |
||
327 | } |
||
328 | sprintf(c, " "); |
||
329 | c += 1; |
||
330 | } |
||
331 | *(c - 1) = '\0'; |
||
332 | } |
||
333 | |||
334 | int main(int argc, char** argv) |
||
335 | { |
||
336 | int k; |
||
337 | SHA1_CTX context; |
||
338 | uint8_t digest[20]; |
||
339 | char output[80]; |
||
340 | |||
341 | fprintf(stdout, "verifying SHA-1 implementation... "); |
||
342 | |||
343 | for (k = 0; k < 2; k++){ |
||
344 | SHA1_Init(&context); |
||
345 | SHA1_Update(&context, (uint8_t*)test_data[k], strlen(test_data[k])); |
||
346 | SHA1_Final(&context, digest); |
||
347 | digest_to_hex(digest, output); |
||
348 | |||
349 | if (strcmp(output, test_results[k])) { |
||
350 | fprintf(stdout, "FAIL\n"); |
||
351 | fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[k]); |
||
352 | fprintf(stderr,"\t%s returned\n", output); |
||
353 | fprintf(stderr,"\t%s is correct\n", test_results[k]); |
||
354 | return (1); |
||
355 | } |
||
356 | } |
||
357 | /* million 'a' vector we feed separately */ |
||
358 | SHA1_Init(&context); |
||
359 | for (k = 0; k < 1000000; k++) |
||
360 | SHA1_Update(&context, (uint8_t*)"a", 1); |
||
361 | SHA1_Final(&context, digest); |
||
362 | digest_to_hex(digest, output); |
||
363 | if (strcmp(output, test_results[2])) { |
||
364 | fprintf(stdout, "FAIL\n"); |
||
365 | fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[2]); |
||
366 | fprintf(stderr,"\t%s returned\n", output); |
||
367 | fprintf(stderr,"\t%s is correct\n", test_results[2]); |
||
368 | return (1); |
||
369 | } |
||
370 | |||
371 | /* success */ |
||
372 | fprintf(stdout, "ok\n"); |
||
373 | return(0); |
||
374 | } |
||
375 | #endif /* TEST */>>>>>>>>>>><>>><>><>><> |