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