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