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 (at) edmweb.com> 18 100% Public Domain 19 20 ----------------- 21 Modified 7/98 22 By James H. Brown <jbrown (at) 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 (at) 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 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 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 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 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 */ 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. */ 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. */ 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 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 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