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; 139typedef union { 140 unsigned char c[64]; 141 unsigned long l[16]; 142} CHAR64LONG16; 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