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