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