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/* 14sha1sum: inspired by md5sum. 15 16SHA-1 in C 17By Steve Reid <steve@edmweb.com> 18100% Public Domain 19 20----------------- 21Modified 7/98 22By James H. Brown <jbrown@burgoyne.com> 23Still 100% Public Domain 24 25bit machines 26Routine SHA1Update changed from 27 void SHA1Update(SHA1_CTX* context, unsigned char* data, 28 unsigned int len) 29to 30 void SHA1Update(SHA1_CTX* context, unsigned char* data, 31 unsigned long len) 32 33The 'len' parameter was declared an int which works fine on 32 34bit machines. However, on 16 bit machines an int is too small 35for the shifts being done against it. This caused the hash 36function to generate incorrect values if len was greater than 378191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). 38 39Since the file IO in main() reads 16K at a time, any file 8K or 40larger would be guaranteed to generate the wrong hash (e.g. 41Test Vector #3, a million "a"s). 42 43I also changed the declaration of variables i & j in SHA1Update 44to unsigned long from unsigned int for the same reason. 45 46These changes should make no difference to any 32 bit 47implementations since an int and a long are the same size in 48those environments. 49 50-- 51I also corrected a few compiler warnings generated by Borland 52C. 531. Added #include <process.h> for exit() prototype 542. Removed unused variable 'j' in SHA1Final 553. Changed exit(0) to return(0) at end of main. 56 57ALL changes I made can be located by searching for comments 58containing 'JHB' 59 60----------------- 61Modified 13 August 2000 62By Michael Paul Johnson <mpj@cryptography.org> 63Still 100% Public Domain 64 65Changed command line syntax, added feature to automatically 66check files against their previous SHA-1 check values, kind of 67like md5sum does. Added functions hexval, verifyfile, 68and sha1file. Rewrote main(). 69----------------- 70 71Test Vectors (from FIPS PUB 180-1) 72"abc" 73 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 74"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 75 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 76A 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 106static 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 134static void SHA1Transform(unsigned long state[5], 135 const unsigned char buffer[64]) 136{ 137unsigned long a, b, c, d, e; 138typedef union { 139 unsigned char c[64]; 140 unsigned long l[16]; 141} CHAR64LONG16; 142CHAR64LONG16* block; 143#ifdef SHA1HANDSOFF 144static 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 193optimizes this out, anyway, and it produces an annoying 194warning. */ 195} 196 197 198/* SHA1Init - Initialize new context */ 199 200void 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 214void 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 240void SHA1Final(unsigned char digest[HASHSIZE], SHA1_CTX* 241context) 242{ 243unsigned long i; /* JHB */ 244unsigned 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*/ 281void 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. */ 314unsigned 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. */ 328int 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 398void 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 417int 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