1 /* This file is derived from libdex project */
2
3 /*
4 * Tweaked in various ways for Google/Android:
5 * - Changed from .cpp to .c.
6 * - Made argument to SHA1Update a const pointer, and enabled
7 * SHA1HANDSOFF. This incurs a speed penalty but prevents us from
8 * trashing the input.
9 * - Include <endian.h> to get endian info.
10 * - Split a small piece into a header file.
11 */
12
13 /*
14 sha1sum: inspired by md5sum.
15
16 SHA-1 in C
17 By Steve Reid <steve@edmweb.com>
18 100% Public Domain
19
20 -----------------
21 Modified 7/98
22 By James H. Brown <jbrown@burgoyne.com>
23 Still 100% Public Domain
24
25 bit machines
26 Routine SHA1Update changed from
27 void SHA1Update(SHA1_CTX* context, unsigned char* data,
28 unsigned int len)
29 to
30 void SHA1Update(SHA1_CTX* context, unsigned char* data,
31 unsigned long len)
32
33 The 'len' parameter was declared an int which works fine on 32
34 bit machines. However, on 16 bit machines an int is too small
35 for the shifts being done against it. This caused the hash
36 function to generate incorrect values if len was greater than
37 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
38
39 Since the file IO in main() reads 16K at a time, any file 8K or
40 larger would be guaranteed to generate the wrong hash (e.g.
41 Test Vector #3, a million "a"s).
42
43 I also changed the declaration of variables i & j in SHA1Update
44 to unsigned long from unsigned int for the same reason.
45
46 These changes should make no difference to any 32 bit
47 implementations since an int and a long are the same size in
48 those environments.
49
50 --
51 I also corrected a few compiler warnings generated by Borland
52 C.
53 1. Added #include <process.h> for exit() prototype
54 2. Removed unused variable 'j' in SHA1Final
55 3. Changed exit(0) to return(0) at end of main.
56
57 ALL changes I made can be located by searching for comments
58 containing 'JHB'
59
60 -----------------
61 Modified 13 August 2000
62 By Michael Paul Johnson <mpj@cryptography.org>
63 Still 100% Public Domain
64
65 Changed command line syntax, added feature to automatically
66 check files against their previous SHA-1 check values, kind of
67 like md5sum does. Added functions hexval, verifyfile,
68 and sha1file. Rewrote main().
69 -----------------
70
71 Test Vectors (from FIPS PUB 180-1)
72 "abc"
73 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
74 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
75 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
76 A million repetitions of "a"
77 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
78 */
79
80 #define SHA1HANDSOFF /*Copies data before messing with it.*/
81
82 /*#define CMDLINE * include main() and file processing */
83 //#ifdef CMDLINE
84 //# undef CMDLINE /* Never include main() for libbcc */
85 //#endif
86
87 #include "sha1.h"
88
89 #include <stdio.h>
90 #include <string.h>
91 #ifdef __BORLANDC__
92 #include <dir.h>
93 #include <dos.h>
94 #include <process.h> /* prototype for exit() - JHB
95 needed for Win32, but chokes Linux - MPJ */
96 #define X_LITTLE_ENDIAN /* This should be #define'd if true.*/
97 #else
98 # define X_LITTLE_ENDIAN
99 # include <unistd.h>
100 # include <stdlib.h>
101 #endif
102 #include <ctype.h>
103
104 #define LINESIZE 2048
105
106 static void SHA1Transform(uint32_t state[5], const uint8_t buffer[64]);
107
108 #define rol(value,bits) \
109 (((value)<<(bits))|((value)>>(32-(bits))))
110
111 /* blk0() and blk() perform the initial expand. */
112 /* I got the idea of expanding during the round function from
113 SSLeay */
114 #ifdef X_LITTLE_ENDIAN
115 #define blk0(i) (block->l[i]=(rol(block->l[i],24)&0xFF00FF00) \
116 |(rol(block->l[i],8)&0x00FF00FF))
117 #else
118 #define blk0(i) block->l[i]
119 #endif
120 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
121 ^block->l[(i+2)&15]^block->l[i&15],1))
122
123 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
124 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
125 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
126 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
127 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
128 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
129
130
131 /* Hash a single 512-bit block. This is the core of the algorithm. */
132
SHA1Transform(uint32_t state[5],const uint8_t buffer[64])133 static void SHA1Transform(uint32_t state[5],
134 const uint8_t buffer[64])
135 {
136 uint32_t a, b, c, d, e;
137 typedef union {
138 uint8_t c[64];
139 uint32_t l[16];
140 } CHAR64LONG16;
141 CHAR64LONG16* block;
142 #ifdef SHA1HANDSOFF
143 static uint8_t workspace[64];
144 block = (CHAR64LONG16*)workspace;
145 memcpy(block, buffer, 64);
146 #else
147 block = (CHAR64LONG16*)buffer;
148 #endif
149 /* Copy context->state[] to working vars */
150 a = state[0];
151 b = state[1];
152 c = state[2];
153 d = state[3];
154 e = state[4];
155 /* 4 rounds of 20 operations each. Loop unrolled. */
156 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2);
157 R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5);
158 R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8);
159 R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
160 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14);
161 R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17);
162 R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20);
163 R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
164 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26);
165 R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29);
166 R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32);
167 R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
168 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38);
169 R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41);
170 R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44);
171 R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
172 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50);
173 R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53);
174 R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56);
175 R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
176 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62);
177 R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65);
178 R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68);
179 R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
180 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74);
181 R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77);
182 R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
183
184 /* Add the working vars back into context.state[] */
185 state[0] += a;
186 state[1] += b;
187 state[2] += c;
188 state[3] += d;
189 state[4] += e;
190 /* Wipe variables */
191 /* a = b = c = d = e = 0; Nice try, but the compiler
192 optimizes this out, anyway, and it produces an annoying
193 warning. */
194 }
195
196
197 /* SHA1Init - Initialize new context */
198
SHA1Init(SHA1_CTX * context)199 void SHA1Init(SHA1_CTX* context)
200 {
201 /* SHA1 initialization constants */
202 context->state[0] = 0x67452301;
203 context->state[1] = 0xEFCDAB89;
204 context->state[2] = 0x98BADCFE;
205 context->state[3] = 0x10325476;
206 context->state[4] = 0xC3D2E1F0;
207 context->count[0] = context->count[1] = 0;
208 }
209
210
211 /* Run your data through this. */
212
SHA1Update(SHA1_CTX * context,const uint8_t * data,uint32_t len)213 void SHA1Update(SHA1_CTX* context, const uint8_t* data,
214 uint32_t len) /* JHB */
215 {
216 uint32_t i, j; /* JHB */
217
218 j = (context->count[0] >> 3) & 63;
219 if ((context->count[0] += len << 3) < (len << 3))
220 context->count[1]++;
221 context->count[1] += (len >> 29);
222 if ((j + len) > 63)
223 {
224 memcpy(&context->buffer[j], data, (i = 64-j));
225 SHA1Transform(context->state, context->buffer);
226 for ( ; i + 63 < len; i += 64) {
227 SHA1Transform(context->state, &data[i]);
228 }
229 j = 0;
230 }
231 else
232 i = 0;
233 memcpy(&context->buffer[j], &data[i], len - i);
234 }
235
236
237 /* Add padding and return the message digest. */
238
SHA1Final(uint8_t digest[HASHSIZE],SHA1_CTX * context)239 void SHA1Final(uint8_t digest[HASHSIZE], SHA1_CTX*
240 context)
241 {
242 uint32_t i; /* JHB */
243 uint8_t finalcount[8];
244
245 for (i = 0; i < 8; i++)
246 {
247 finalcount[i] = (uint8_t)((context->count[(i>=4?
248 0:1)]>>((3-(i&3))*8))&255);
249 /* Endian independent */
250 }
251 SHA1Update(context, (uint8_t *)"\200", 1);
252 while ((context->count[0] & 504) != 448) {
253 SHA1Update(context, (uint8_t *)"\0", 1);
254 }
255 SHA1Update(context, finalcount, 8);
256 /* Should cause a SHA1Transform() */
257 for (i = 0; i < HASHSIZE; i++) {
258 digest[i] = (uint8_t)
259 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
260 }
261 /* Wipe variables */
262 memset(context->buffer, 0, 64);
263 memset(context->state, 0, HASHSIZE);
264 memset(context->count, 0, 8);
265 memset(&finalcount, 0, 8);
266 #ifdef SHA1HANDSOFF
267 /* make SHA1Transform overwrite it's own static vars */
268 SHA1Transform(context->state, context->buffer);
269 #endif
270 }
271
272
273
274 #ifdef CMDLINE
275
276 /* sha1file computes the SHA-1 hash of the named file and puts
277 it in the 20-byte array digest. If fname is NULL, stdin is
278 assumed.
279 */
sha1file(char * fname,uint8_t * digest)280 void sha1file(char *fname, uint8_t* digest)
281 {
282 int bytesread;
283 SHA1_CTX context;
284 uint8_t buffer[16384];
285 FILE* f;
286
287 if (fname)
288 {
289 f = fopen(fname, "rb");
290 if (!f)
291 {
292 fprintf(stderr, "Can't open %s\n", fname);
293 memset(digest, 0, HASHSIZE);
294 return;
295 }
296 }
297 else
298 {
299 f = stdin;
300 }
301 SHA1Init(&context);
302 while (!feof(f))
303 {
304 bytesread = fread(buffer, 1, 16384, f);
305 SHA1Update(&context, buffer, bytesread);
306 }
307 SHA1Final(digest, &context);
308 if (fname)
309 fclose(f);
310 }
311
312 /* Convert ASCII hexidecimal digit to 4-bit value. */
hexval(char c)313 uint8_t hexval(char c)
314 {
315 uint8_t h;
316
317 c = toupper(c);
318 if (c >= 'A')
319 h = c - 'A' + 10;
320 else
321 h = c - '0';
322 return h;
323 }
324
325 /* Verify a file created with sha1sum by redirecting output
326 to a file. */
verifyfile(char * fname)327 int verifyfile(char *fname)
328 {
329 int j, k;
330 int found = 0;
331 uint8_t digest[HASHSIZE];
332 uint8_t expected_digest[HASHSIZE];
333 FILE *checkfile;
334 char checkline[LINESIZE];
335 char *s;
336 uint8_t err;
337
338 checkfile = fopen(fname, "rt");
339 if (!checkfile)
340 {
341 fprintf(stderr, "Can't open %s\n", fname);
342 return(0);
343 }
344 do
345 {
346 s = fgets(checkline, LINESIZE, checkfile);
347 if (s)
348 {
349 if ((strlen(checkline)>26)&&
350 1 /*(!strncmp(checkline,"SHA1=", 5))*/)
351 {
352 /* Overwrite newline. */
353 checkline[strlen(checkline)-1]=0;
354 found = 1;
355
356 /* Read expected check value. */
357 for (k=0, j=5; k < HASHSIZE; k++)
358 {
359 expected_digest[k]=hexval(checkline[j++]);
360 expected_digest[k]=(expected_digest[k]<<4)
361 +hexval(checkline[j++]);
362 }
363
364 /* Compute fingerprints */
365 s = checkline+46;
366 sha1file(s, digest);
367
368 /* Compare fingerprints */
369 err = 0;
370 for (k=0; k<HASHSIZE; k++)
371 err |= digest[k]-
372 expected_digest[k];
373 if (err)
374 {
375 fprintf(stderr, "FAILED: %s\n"
376 " EXPECTED: ", s);
377 for (k=0; k<HASHSIZE; k++)
378 fprintf(stderr, "%02X",
379 expected_digest[k]);
380 fprintf(stderr,"\n FOUND: ");
381 for (k=0; k<HASHSIZE; k++)
382 fprintf(stderr, "%02X", digest[k]);
383 fprintf(stderr, "\n");
384 }
385 else
386 {
387 printf("OK: %s\n", s);
388 }
389 }
390 }
391 } while (s);
392 return found;
393 }
394
395
396
syntax(char * progname)397 void syntax(char *progname)
398 {
399 printf("\nsyntax:\n"
400 "%s [-c|-h][-q] file name[s]\n"
401 " -c = check files against previous check values\n"
402 " -g = generate SHA-1 check values (default action)\n"
403 " -h = display this help\n"
404 "For example,\n"
405 "sha1sum test.txt > check.txt\n"
406 "generates check value for test.txt in check.txt, and\n"
407 "sha1sum -c check.txt\n"
408 "checks test.txt against the check value in check.txt\n",
409 progname);
410 exit(1);
411 }
412
413
414 /**********************************************************/
415
main(int argc,char ** argv)416 int main(int argc, char** argv)
417 {
418 int i, j, k;
419 int check = 0;
420 int found = 0;
421 uint8_t digest[HASHSIZE];
422 uint8_t expected_digest[HASHSIZE];
423 FILE *checkfile;
424 char checkline[LINESIZE];
425 char *s;
426 #ifdef __BORLANDC__
427 struct ffblk f;
428 int done;
429 char path[MAXPATH];
430 char drive[MAXDRIVE];
431 char dir[MAXDIR];
432 char name[MAXFILE];
433 char ext[MAXEXT];
434 #endif
435 uint8_t err;
436 const char *binary_output_file = 0;
437
438 for (i = 1; i < argc; i++)
439 {
440 if (argv[i][0] == '-')
441 {
442 switch (argv[i][1])
443 {
444 case 'B':
445 ++i;
446 binary_output_file = argv[i];
447 break;
448 case 'c':
449 case 'C':
450 check = 1;
451 break;
452 case 'g':
453 case 'G':
454 check = 0;
455 break;
456 default:
457 syntax(argv[0]);
458 }
459 }
460 }
461
462 // Read from STDIN
463 sha1file(NULL, digest);
464 if (binary_output_file) {
465 FILE *fout = fopen(binary_output_file, "wb");
466 if (!fout) {
467 fprintf(stderr, "Error: Can not write to %s.\n", binary_output_file);
468 return 1;
469 }
470 fwrite(digest, 1, HASHSIZE, fout);
471 fclose(fout);
472 return 0;
473 }
474 for (j = 0; j < HASHSIZE; j++)
475 printf("%02x", digest[j]);
476 return 0;
477
478 for (i=1; i<argc; i++)
479 {
480 if (argv[i][0] != '-')
481 {
482 #ifdef __BORLANDC__
483 fnsplit(argv[i], drive, dir, name, ext);
484 done = findfirst(argv[i], &f, FA_RDONLY |
485 FA_HIDDEN|FA_SYSTEM|FA_ARCH);
486 while (!done)
487 {
488 sprintf(path, "%s%s%s", drive, dir, f.ff_name);
489 s = path;
490 #else
491 s = argv[i];
492 #endif
493
494 if (check)
495 { /* Check fingerprint file. */
496 found |= verifyfile(s);
497 }
498 else
499 { /* Generate fingerprints & write to
500 stdout. */
501 sha1file(s, digest);
502 //printf("SHA1=");
503 for (j=0; j<HASHSIZE; j++)
504 printf("%02x", digest[j]);
505 printf(" %s\n", s);
506 found = 1;
507 }
508
509 #ifdef __BORLANDC__
510 done = findnext(&f);
511 }
512 #endif
513
514 }
515 }
516 if (!found)
517 {
518 if (check)
519 {
520 fprintf(stderr,
521 "No SHA1 lines found in %s\n",
522 argv[i]);
523 }
524 else
525 {
526 fprintf(stderr, "No files checked.\n");
527 syntax(argv[0]);
528 }
529 }
530 return(0); /* JHB */
531 }
532
533 #endif /*CMDLINE*/
534