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(unsigned long state[5],
107 const unsigned char buffer[64]);
108
109 #define rol(value,bits) \
110 (((value)<<(bits))|((value)>>(32-(bits))))
111
112 /* blk0() and blk() perform the initial expand. */
113 /* I got the idea of expanding during the round function from
114 SSLeay */
115 #ifdef X_LITTLE_ENDIAN
116 #define blk0(i) (block->l[i]=(rol(block->l[i],24)&0xFF00FF00) \
117 |(rol(block->l[i],8)&0x00FF00FF))
118 #else
119 #define blk0(i) block->l[i]
120 #endif
121 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
122 ^block->l[(i+2)&15]^block->l[i&15],1))
123
124 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
125 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
126 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
127 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
128 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
129 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
130
131
132 /* Hash a single 512-bit block. This is the core of the algorithm. */
133
SHA1Transform(unsigned long state[5],const unsigned char buffer[64])134 static void SHA1Transform(unsigned long state[5],
135 const unsigned char buffer[64])
136 {
137 unsigned long a, b, c, d, e;
138 typedef union {
139 unsigned char c[64];
140 unsigned long l[16];
141 } CHAR64LONG16;
142 CHAR64LONG16* block;
143 #ifdef SHA1HANDSOFF
144 static unsigned char workspace[64];
145 block = (CHAR64LONG16*)workspace;
146 memcpy(block, buffer, 64);
147 #else
148 block = (CHAR64LONG16*)buffer;
149 #endif
150 /* Copy context->state[] to working vars */
151 a = state[0];
152 b = state[1];
153 c = state[2];
154 d = state[3];
155 e = state[4];
156 /* 4 rounds of 20 operations each. Loop unrolled. */
157 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2);
158 R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5);
159 R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8);
160 R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
161 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14);
162 R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17);
163 R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20);
164 R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
165 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26);
166 R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29);
167 R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32);
168 R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
169 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38);
170 R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41);
171 R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44);
172 R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
173 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50);
174 R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53);
175 R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56);
176 R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
177 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62);
178 R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65);
179 R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68);
180 R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
181 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74);
182 R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77);
183 R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
184
185 /* Add the working vars back into context.state[] */
186 state[0] += a;
187 state[1] += b;
188 state[2] += c;
189 state[3] += d;
190 state[4] += e;
191 /* Wipe variables */
192 /* a = b = c = d = e = 0; Nice try, but the compiler
193 optimizes this out, anyway, and it produces an annoying
194 warning. */
195 }
196
197
198 /* SHA1Init - Initialize new context */
199
SHA1Init(SHA1_CTX * context)200 void SHA1Init(SHA1_CTX* context)
201 {
202 /* SHA1 initialization constants */
203 context->state[0] = 0x67452301;
204 context->state[1] = 0xEFCDAB89;
205 context->state[2] = 0x98BADCFE;
206 context->state[3] = 0x10325476;
207 context->state[4] = 0xC3D2E1F0;
208 context->count[0] = context->count[1] = 0;
209 }
210
211
212 /* Run your data through this. */
213
SHA1Update(SHA1_CTX * context,const unsigned char * data,unsigned long len)214 void SHA1Update(SHA1_CTX* context, const unsigned char* data,
215 unsigned long len) /* JHB */
216 {
217 unsigned long i, j; /* JHB */
218
219 j = (context->count[0] >> 3) & 63;
220 if ((context->count[0] += len << 3) < (len << 3))
221 context->count[1]++;
222 context->count[1] += (len >> 29);
223 if ((j + len) > 63)
224 {
225 memcpy(&context->buffer[j], data, (i = 64-j));
226 SHA1Transform(context->state, context->buffer);
227 for ( ; i + 63 < len; i += 64) {
228 SHA1Transform(context->state, &data[i]);
229 }
230 j = 0;
231 }
232 else
233 i = 0;
234 memcpy(&context->buffer[j], &data[i], len - i);
235 }
236
237
238 /* Add padding and return the message digest. */
239
SHA1Final(unsigned char digest[HASHSIZE],SHA1_CTX * context)240 void SHA1Final(unsigned char digest[HASHSIZE], SHA1_CTX*
241 context)
242 {
243 unsigned long i; /* JHB */
244 unsigned char finalcount[8];
245
246 for (i = 0; i < 8; i++)
247 {
248 finalcount[i] = (unsigned char)((context->count[(i>=4?
249 0:1)]>>((3-(i&3))*8))&255);
250 /* Endian independent */
251 }
252 SHA1Update(context, (unsigned char *)"\200", 1);
253 while ((context->count[0] & 504) != 448) {
254 SHA1Update(context, (unsigned char *)"\0", 1);
255 }
256 SHA1Update(context, finalcount, 8);
257 /* Should cause a SHA1Transform() */
258 for (i = 0; i < HASHSIZE; i++) {
259 digest[i] = (unsigned char)
260 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
261 }
262 /* Wipe variables */
263 memset(context->buffer, 0, 64);
264 memset(context->state, 0, HASHSIZE);
265 memset(context->count, 0, 8);
266 memset(&finalcount, 0, 8);
267 #ifdef SHA1HANDSOFF
268 /* make SHA1Transform overwrite it's own static vars */
269 SHA1Transform(context->state, context->buffer);
270 #endif
271 }
272
273
274
275 #ifdef CMDLINE
276
277 /* sha1file computes the SHA-1 hash of the named file and puts
278 it in the 20-byte array digest. If fname is NULL, stdin is
279 assumed.
280 */
sha1file(char * fname,unsigned char * digest)281 void sha1file(char *fname, unsigned char* digest)
282 {
283 int bytesread;
284 SHA1_CTX context;
285 unsigned char buffer[16384];
286 FILE* f;
287
288 if (fname)
289 {
290 f = fopen(fname, "rb");
291 if (!f)
292 {
293 fprintf(stderr, "Can't open %s\n", fname);
294 memset(digest, 0, HASHSIZE);
295 return;
296 }
297 }
298 else
299 {
300 f = stdin;
301 }
302 SHA1Init(&context);
303 while (!feof(f))
304 {
305 bytesread = fread(buffer, 1, 16384, f);
306 SHA1Update(&context, buffer, bytesread);
307 }
308 SHA1Final(digest, &context);
309 if (fname)
310 fclose(f);
311 }
312
313 /* Convert ASCII hexidecimal digit to 4-bit value. */
hexval(char c)314 unsigned char hexval(char c)
315 {
316 unsigned char h;
317
318 c = toupper(c);
319 if (c >= 'A')
320 h = c - 'A' + 10;
321 else
322 h = c - '0';
323 return h;
324 }
325
326 /* Verify a file created with sha1sum by redirecting output
327 to a file. */
verifyfile(char * fname)328 int verifyfile(char *fname)
329 {
330 int j, k;
331 int found = 0;
332 unsigned char digest[HASHSIZE];
333 unsigned char expected_digest[HASHSIZE];
334 FILE *checkfile;
335 char checkline[LINESIZE];
336 char *s;
337 unsigned char err;
338
339 checkfile = fopen(fname, "rt");
340 if (!checkfile)
341 {
342 fprintf(stderr, "Can't open %s\n", fname);
343 return(0);
344 }
345 do
346 {
347 s = fgets(checkline, LINESIZE, checkfile);
348 if (s)
349 {
350 if ((strlen(checkline)>26)&&
351 1 /*(!strncmp(checkline,"SHA1=", 5))*/)
352 {
353 /* Overwrite newline. */
354 checkline[strlen(checkline)-1]=0;
355 found = 1;
356
357 /* Read expected check value. */
358 for (k=0, j=5; k < HASHSIZE; k++)
359 {
360 expected_digest[k]=hexval(checkline[j++]);
361 expected_digest[k]=(expected_digest[k]<<4)
362 +hexval(checkline[j++]);
363 }
364
365 /* Compute fingerprints */
366 s = checkline+46;
367 sha1file(s, digest);
368
369 /* Compare fingerprints */
370 err = 0;
371 for (k=0; k<HASHSIZE; k++)
372 err |= digest[k]-
373 expected_digest[k];
374 if (err)
375 {
376 fprintf(stderr, "FAILED: %s\n"
377 " EXPECTED: ", s);
378 for (k=0; k<HASHSIZE; k++)
379 fprintf(stderr, "%02X",
380 expected_digest[k]);
381 fprintf(stderr,"\n FOUND: ");
382 for (k=0; k<HASHSIZE; k++)
383 fprintf(stderr, "%02X", digest[k]);
384 fprintf(stderr, "\n");
385 }
386 else
387 {
388 printf("OK: %s\n", s);
389 }
390 }
391 }
392 } while (s);
393 return found;
394 }
395
396
397
syntax(char * progname)398 void syntax(char *progname)
399 {
400 printf("\nsyntax:\n"
401 "%s [-c|-h][-q] file name[s]\n"
402 " -c = check files against previous check values\n"
403 " -g = generate SHA-1 check values (default action)\n"
404 " -h = display this help\n"
405 "For example,\n"
406 "sha1sum test.txt > check.txt\n"
407 "generates check value for test.txt in check.txt, and\n"
408 "sha1sum -c check.txt\n"
409 "checks test.txt against the check value in check.txt\n",
410 progname);
411 exit(1);
412 }
413
414
415 /**********************************************************/
416
main(int argc,char ** argv)417 int main(int argc, char** argv)
418 {
419 int i, j, k;
420 int check = 0;
421 int found = 0;
422 unsigned char digest[HASHSIZE];
423 unsigned char expected_digest[HASHSIZE];
424 FILE *checkfile;
425 char checkline[LINESIZE];
426 char *s;
427 #ifdef __BORLANDC__
428 struct ffblk f;
429 int done;
430 char path[MAXPATH];
431 char drive[MAXDRIVE];
432 char dir[MAXDIR];
433 char name[MAXFILE];
434 char ext[MAXEXT];
435 #endif
436 unsigned char err;
437 const char *binary_output_file = 0;
438
439 for (i = 1; i < argc; i++)
440 {
441 if (argv[i][0] == '-')
442 {
443 switch (argv[i][1])
444 {
445 case 'B':
446 ++i;
447 binary_output_file = argv[i];
448 break;
449 case 'c':
450 case 'C':
451 check = 1;
452 break;
453 case 'g':
454 case 'G':
455 check = 0;
456 break;
457 default:
458 syntax(argv[0]);
459 }
460 }
461 }
462
463 // Read from STDIN
464 sha1file(NULL, digest);
465 if (binary_output_file) {
466 FILE *fout = fopen(binary_output_file, "wb");
467 if (!fout) {
468 fprintf(stderr, "Error: Can not write to %s.\n", binary_output_file);
469 return 1;
470 }
471 fwrite(digest, 1, HASHSIZE, fout);
472 fclose(fout);
473 return 0;
474 }
475 for (j = 0; j < HASHSIZE; j++)
476 printf("%02x", digest[j]);
477 return 0;
478
479 for (i=1; i<argc; i++)
480 {
481 if (argv[i][0] != '-')
482 {
483 #ifdef __BORLANDC__
484 fnsplit(argv[i], drive, dir, name, ext);
485 done = findfirst(argv[i], &f, FA_RDONLY |
486 FA_HIDDEN|FA_SYSTEM|FA_ARCH);
487 while (!done)
488 {
489 sprintf(path, "%s%s%s", drive, dir, f.ff_name);
490 s = path;
491 #else
492 s = argv[i];
493 #endif
494
495 if (check)
496 { /* Check fingerprint file. */
497 found |= verifyfile(s);
498 }
499 else
500 { /* Generate fingerprints & write to
501 stdout. */
502 sha1file(s, digest);
503 //printf("SHA1=");
504 for (j=0; j<HASHSIZE; j++)
505 printf("%02x", digest[j]);
506 printf(" %s\n", s);
507 found = 1;
508 }
509
510 #ifdef __BORLANDC__
511 done = findnext(&f);
512 }
513 #endif
514
515 }
516 }
517 if (!found)
518 {
519 if (check)
520 {
521 fprintf(stderr,
522 "No SHA1 lines found in %s\n",
523 argv[i]);
524 }
525 else
526 {
527 fprintf(stderr, "No files checked.\n");
528 syntax(argv[0]);
529 }
530 }
531 return(0); /* JHB */
532 }
533
534 #endif /*CMDLINE*/
535