1 /* 2 Copyright (c) 1990-2000 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 or later 5 (the contents of which are also included in zip.h) for terms of use. 6 If, for some reason, all these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 8 */ 9 /* 10 crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] 11 12 This encryption/decryption source code for Info-Zip software was 13 originally written in Europe. The whole source package can be 14 freely distributed, including from the USA. (Prior to January 2000, 15 re-export from the US was a violation of US law.) 16 17 NOTE on copyright history: 18 Previous versions of this source package (up to version 2.8) were 19 not copyrighted and put in the public domain. If you cannot comply 20 with the Info-Zip LICENSE, you may want to look for one of those 21 public domain versions. 22 */ 23 24 /* 25 This encryption code is a direct transcription of the algorithm from 26 Roger Schlafly, described by Phil Katz in the file appnote.txt. This 27 file (appnote.txt) is distributed with the PKZIP program (even in the 28 version without encryption capabilities). 29 */ 30 31 #define ZCRYPT_INTERNAL 32 #include "zip.h" 33 #include "crypt.h" 34 #include "ttyio.h" 35 36 #if CRYPT 37 38 #ifndef FALSE 39 # define FALSE 0 40 #endif 41 42 #ifdef ZIP 43 /* For the encoding task used in Zip (and ZipCloak), we want to initialize 44 the crypt algorithm with some reasonably unpredictable bytes, see 45 the crypthead() function. The standard rand() library function is 46 used to supply these `random' bytes, which in turn is initialized by 47 a srand() call. The srand() function takes an "unsigned" (at least 16bit) 48 seed value as argument to determine the starting point of the rand() 49 pseudo-random number generator. 50 This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with 51 Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 52 as some (hopefully) nondeterministic bitmask. On many (most) systems, 53 we use some "process specific" number, as the PID or something similar, 54 but when nothing unpredictable is available, a fixed number may be 55 sufficient. 56 NOTE: 57 1.) This implementation requires the availability of the following 58 standard UNIX C runtime library functions: time(), rand(), srand(). 59 On systems where some of them are missing, the environment that 60 incorporates the crypt routines must supply suitable replacement 61 functions. 62 2.) It is a very bad idea to use a second call to time() to set the 63 "Seed2" number! In this case, both "Seed1" and "Seed2" would be 64 (almost) identical, resulting in a (mostly) "zero" constant seed 65 number passed to srand(). 66 67 The implementation environment defined in the "zip.h" header should 68 supply a reasonable definition for ZCR_SEED2 (an unsigned number; for 69 most implementations of rand() and srand(), only the lower 16 bits are 70 significant!). An example that works on many systems would be 71 "#define ZCR_SEED2 (unsigned)getpid()". 72 The default definition for ZCR_SEED2 supplied below should be regarded 73 as a fallback to allow successful compilation in "beta state" 74 environments. 75 */ 76 # include <time.h> /* time() function supplies first part of crypt seed */ 77 /* "last resort" source for second part of crypt seed pattern */ 78 # ifndef ZCR_SEED2 79 # define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ 80 # endif 81 # ifdef GLOBAL /* used in Amiga system headers, maybe others too */ 82 # undef GLOBAL 83 # endif 84 # define GLOBAL(g) g 85 #else /* !ZIP */ 86 # define GLOBAL(g) G.g 87 #endif /* ?ZIP */ 88 89 90 #ifdef UNZIP 91 /* char *key = (char *)NULL; moved to globals.h */ 92 # ifndef FUNZIP 93 local int testp OF((__GPRO__ ZCONST uch *h)); 94 local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); 95 # endif 96 #endif /* UNZIP */ 97 98 #ifndef UNZIP /* moved to globals.h for UnZip */ 99 local ulg keys[3]; /* keys defining the pseudo-random sequence */ 100 #endif /* !UNZIP */ 101 102 #ifndef Trace 103 # ifdef CRYPT_DEBUG 104 # define Trace(x) fprintf x 105 # else 106 # define Trace(x) 107 # endif 108 #endif 109 110 #ifndef CRC_32_TAB 111 # define CRC_32_TAB crc_32_tab 112 #endif 113 114 #define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) 115 116 /*********************************************************************** 117 * Return the next byte in the pseudo-random sequence 118 */ 119 int decrypt_byte(__G) 120 __GDEF 121 { 122 unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an 123 * unpredictable manner on 16-bit systems; not a problem 124 * with any known compiler so far, though */ 125 126 temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; 127 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); 128 } 129 130 /*********************************************************************** 131 * Update the encryption keys with the next byte of plain text 132 */ 133 int update_keys(__G__ c) 134 __GDEF 135 int c; /* byte of plain text */ 136 { 137 GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c); 138 GLOBAL(keys[1]) += GLOBAL(keys[0]) & 0xff; 139 GLOBAL(keys[1]) = GLOBAL(keys[1]) * 134775813L + 1; 140 { 141 register int keyshift = (int)(GLOBAL(keys[1]) >> 24); 142 GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift); 143 } 144 return c; 145 } 146 147 148 /*********************************************************************** 149 * Initialize the encryption keys and the random header according to 150 * the given password. 151 */ 152 void init_keys(__G__ passwd) 153 __GDEF 154 ZCONST char *passwd; /* password string with which to modify keys */ 155 { 156 GLOBAL(keys[0]) = 305419896L; 157 GLOBAL(keys[1]) = 591751049L; 158 GLOBAL(keys[2]) = 878082192L; 159 while (*passwd != '\0') { 160 update_keys(__G__ (int)*passwd); 161 passwd++; 162 } 163 } 164 165 166 #ifdef ZIP 167 168 /*********************************************************************** 169 * Write encryption header to file zfile using the password passwd 170 * and the cyclic redundancy check crc. 171 */ 172 void crypthead(passwd, crc, zfile) 173 ZCONST char *passwd; /* password string */ 174 ulg crc; /* crc of file being encrypted */ 175 FILE *zfile; /* where to write header */ 176 { 177 int n; /* index in random header */ 178 int t; /* temporary */ 179 int c; /* random byte */ 180 int ztemp; /* temporary for zencoded value */ 181 uch header[RAND_HEAD_LEN-2]; /* random header */ 182 static unsigned calls = 0; /* ensure different random header each time */ 183 184 /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the 185 * output of rand() to get less predictability, since rand() is 186 * often poorly implemented. 187 */ 188 if (++calls == 1) { 189 srand((unsigned)time(NULL) ^ ZCR_SEED2); 190 } 191 init_keys(passwd); 192 for (n = 0; n < RAND_HEAD_LEN-2; n++) { 193 c = (rand() >> 7) & 0xff; 194 header[n] = (uch)zencode(c, t); 195 } 196 /* Encrypt random header (last two bytes is high word of crc) */ 197 init_keys(passwd); 198 for (n = 0; n < RAND_HEAD_LEN-2; n++) { 199 ztemp = zencode(header[n], t); 200 putc(ztemp, zfile); 201 } 202 ztemp = zencode((int)(crc >> 16) & 0xff, t); 203 putc(ztemp, zfile); 204 ztemp = zencode((int)(crc >> 24) & 0xff, t); 205 putc(ztemp, zfile); 206 } 207 208 209 #ifdef UTIL 210 211 /*********************************************************************** 212 * Encrypt the zip entry described by z from file source to file dest 213 * using the password passwd. Return an error code in the ZE_ class. 214 */ 215 int zipcloak(z, source, dest, passwd) 216 struct zlist far *z; /* zip entry to encrypt */ 217 FILE *source, *dest; /* source and destination files */ 218 ZCONST char *passwd; /* password string */ 219 { 220 int c; /* input byte */ 221 int res; /* result code */ 222 ulg n; /* holds offset and counts size */ 223 ush flag; /* previous flags */ 224 int t; /* temporary */ 225 int ztemp; /* temporary storage for zencode value */ 226 227 /* Set encrypted bit, clear extended local header bit and write local 228 header to output file */ 229 if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; 230 z->off = n; 231 flag = z->flg; 232 z->flg |= 1, z->flg &= ~8; 233 z->lflg |= 1, z->lflg &= ~8; 234 z->siz += RAND_HEAD_LEN; 235 if ((res = putlocal(z, dest)) != ZE_OK) return res; 236 237 /* Initialize keys with password and write random header */ 238 crypthead(passwd, z->crc, dest); 239 240 /* Skip local header in input file */ 241 if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), 242 SEEK_CUR)) { 243 return ferror(source) ? ZE_READ : ZE_EOF; 244 } 245 246 /* Encrypt data */ 247 for (n = z->siz - RAND_HEAD_LEN; n; n--) { 248 if ((c = getc(source)) == EOF) { 249 return ferror(source) ? ZE_READ : ZE_EOF; 250 } 251 ztemp = zencode(c, t); 252 putc(ztemp, dest); 253 } 254 /* Skip extended local header in input file if there is one */ 255 if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { 256 return ferror(source) ? ZE_READ : ZE_EOF; 257 } 258 if (fflush(dest) == EOF) return ZE_TEMP; 259 return ZE_OK; 260 } 261 262 /*********************************************************************** 263 * Decrypt the zip entry described by z from file source to file dest 264 * using the password passwd. Return an error code in the ZE_ class. 265 */ 266 int zipbare(z, source, dest, passwd) 267 struct zlist far *z; /* zip entry to encrypt */ 268 FILE *source, *dest; /* source and destination files */ 269 ZCONST char *passwd; /* password string */ 270 { 271 int c0, c1; /* last two input bytes */ 272 ulg offset; /* used for file offsets */ 273 ulg size; /* size of input data */ 274 int r; /* size of encryption header */ 275 int res; /* return code */ 276 ush flag; /* previous flags */ 277 278 /* Save position and skip local header in input file */ 279 if ((offset = (ulg)ftell(source)) == (ulg)-1L || 280 fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), 281 SEEK_CUR)) { 282 return ferror(source) ? ZE_READ : ZE_EOF; 283 } 284 /* Initialize keys with password */ 285 init_keys(passwd); 286 287 /* Decrypt encryption header, save last two bytes */ 288 c1 = 0; 289 for (r = RAND_HEAD_LEN; r; r--) { 290 c0 = c1; 291 if ((c1 = getc(source)) == EOF) { 292 return ferror(source) ? ZE_READ : ZE_EOF; 293 } 294 Trace((stdout, " (%02x)", c1)); 295 zdecode(c1); 296 Trace((stdout, " %02x", c1)); 297 } 298 Trace((stdout, "\n")); 299 300 /* If last two bytes of header don't match crc (or file time in the 301 * case of an extended local header), back up and just copy. For 302 * pkzip 2.0, the check has been reduced to one byte only. 303 */ 304 #ifdef ZIP10 305 if ((ush)(c0 | (c1<<8)) != 306 (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { 307 #else 308 c0++; /* avoid warning on unused variable */ 309 if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { 310 #endif 311 if (fseek(source, offset, SEEK_SET)) { 312 return ferror(source) ? ZE_READ : ZE_EOF; 313 } 314 if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; 315 return ZE_MISS; 316 } 317 318 /* Clear encrypted bit and local header bit, and write local header to 319 output file */ 320 if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; 321 z->off = offset; 322 flag = z->flg; 323 z->flg &= ~9; 324 z->lflg &= ~9; 325 z->siz -= RAND_HEAD_LEN; 326 if ((res = putlocal(z, dest)) != ZE_OK) return res; 327 328 /* Decrypt data */ 329 for (size = z->siz; size; size--) { 330 if ((c1 = getc(source)) == EOF) { 331 return ferror(source) ? ZE_READ : ZE_EOF; 332 } 333 zdecode(c1); 334 putc(c1, dest); 335 } 336 /* Skip extended local header in input file if there is one */ 337 if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { 338 return ferror(source) ? ZE_READ : ZE_EOF; 339 } 340 if (fflush(dest) == EOF) return ZE_TEMP; 341 342 return ZE_OK; 343 } 344 345 346 #else /* !UTIL */ 347 348 /*********************************************************************** 349 * If requested, encrypt the data in buf, and in any case call fwrite() 350 * with the arguments to zfwrite(). Return what fwrite() returns. 351 */ 352 unsigned zfwrite(buf, item_size, nb, f) 353 zvoid *buf; /* data buffer */ 354 extent item_size; /* size of each item in bytes */ 355 extent nb; /* number of items */ 356 FILE *f; /* file to write to */ 357 { 358 int t; /* temporary */ 359 360 if (key != (char *)NULL) { /* key is the global password pointer */ 361 ulg size; /* buffer size */ 362 char *p = (char*)buf; /* steps through buffer */ 363 364 /* Encrypt data in buffer */ 365 for (size = item_size*(ulg)nb; size != 0; p++, size--) { 366 *p = (char)zencode(*p, t); 367 } 368 } 369 /* Write the buffer out */ 370 return fwrite(buf, item_size, nb, f); 371 } 372 373 #endif /* ?UTIL */ 374 #endif /* ZIP */ 375 376 377 #if (defined(UNZIP) && !defined(FUNZIP)) 378 379 /*********************************************************************** 380 * Get the password and set up keys for current zipfile member. 381 * Return PK_ class error. 382 */ 383 int decrypt(__G__ passwrd) 384 __GDEF 385 ZCONST char *passwrd; 386 { 387 ush b; 388 int n, r; 389 uch h[RAND_HEAD_LEN]; 390 391 Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); 392 393 /* get header once (turn off "encrypted" flag temporarily so we don't 394 * try to decrypt the same data twice) */ 395 GLOBAL(pInfo->encrypted) = FALSE; 396 defer_leftover_input(__G); 397 for (n = 0; n < RAND_HEAD_LEN; n++) { 398 b = NEXTBYTE; 399 h[n] = (uch)b; 400 Trace((stdout, " (%02x)", h[n])); 401 } 402 undefer_input(__G); 403 GLOBAL(pInfo->encrypted) = TRUE; 404 405 if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ 406 GLOBAL(newzip) = FALSE; 407 if (passwrd != (char *)NULL) { /* user gave password on command line */ 408 if (!GLOBAL(key)) { 409 if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == 410 (char *)NULL) 411 return PK_MEM2; 412 strcpy(GLOBAL(key), passwrd); 413 GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ 414 } 415 } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ 416 free(GLOBAL(key)); 417 GLOBAL(key) = (char *)NULL; 418 } 419 } 420 421 /* if have key already, test it; else allocate memory for it */ 422 if (GLOBAL(key)) { 423 if (!testp(__G__ h)) 424 return PK_COOL; /* existing password OK (else prompt for new) */ 425 else if (GLOBAL(nopwd)) 426 return PK_WARN; /* user indicated no more prompting */ 427 } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) 428 return PK_MEM2; 429 430 /* try a few keys */ 431 n = 0; 432 do { 433 r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, 434 GLOBAL(zipfn), GLOBAL(filename)); 435 if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ 436 free (GLOBAL(key)); 437 GLOBAL(key) = NULL; 438 return PK_MEM2; 439 } 440 if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ 441 *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ 442 n = 0; /* and cancel fetch for this item. */ 443 } 444 if (!testp(__G__ h)) 445 return PK_COOL; 446 if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ 447 GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ 448 } while (n > 0); 449 450 return PK_WARN; 451 452 } /* end function decrypt() */ 453 454 455 456 /*********************************************************************** 457 * Test the password. Return -1 if bad, 0 if OK. 458 */ 459 local int testp(__G__ h) 460 __GDEF 461 ZCONST uch *h; 462 { 463 int r; 464 char *key_translated; 465 466 /* On systems with "obscure" native character coding (e.g., EBCDIC), 467 * the first test translates the password to the "main standard" 468 * character coding. */ 469 470 #ifdef STR_TO_CP1 471 /* allocate buffer for translated password */ 472 if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) 473 return -1; 474 /* first try, test password translated "standard" charset */ 475 r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); 476 #else /* !STR_TO_CP1 */ 477 /* first try, test password as supplied on the extractor's host */ 478 r = testkey(__G__ h, GLOBAL(key)); 479 #endif /* ?STR_TO_CP1 */ 480 481 #ifdef STR_TO_CP2 482 if (r != 0) { 483 #ifndef STR_TO_CP1 484 /* now prepare for second (and maybe third) test with translated pwd */ 485 if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) 486 return -1; 487 #endif 488 /* second try, password translated to alternate ("standard") charset */ 489 r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); 490 #ifdef STR_TO_CP3 491 if (r != 0) 492 /* third try, password translated to another "standard" charset */ 493 r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); 494 #endif 495 #ifndef STR_TO_CP1 496 free(key_translated); 497 #endif 498 } 499 #endif /* STR_TO_CP2 */ 500 501 #ifdef STR_TO_CP1 502 free(key_translated); 503 if (r != 0) { 504 /* last resort, test password as supplied on the extractor's host */ 505 r = testkey(__G__ h, GLOBAL(key)); 506 } 507 #endif /* STR_TO_CP1 */ 508 509 return r; 510 511 } /* end function testp() */ 512 513 514 local int testkey(__G__ h, key) 515 __GDEF 516 ZCONST uch *h; /* decrypted header */ 517 ZCONST char *key; /* decryption password to test */ 518 { 519 ush b; 520 #ifdef ZIP10 521 ush c; 522 #endif 523 int n; 524 uch *p; 525 uch hh[RAND_HEAD_LEN]; /* decrypted header */ 526 527 /* set keys and save the encrypted header */ 528 init_keys(__G__ key); 529 memcpy(hh, h, RAND_HEAD_LEN); 530 531 /* check password */ 532 for (n = 0; n < RAND_HEAD_LEN; n++) { 533 zdecode(hh[n]); 534 Trace((stdout, " %02x", hh[n])); 535 } 536 537 Trace((stdout, 538 "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", 539 GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), 540 GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); 541 Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", 542 GLOBAL(incnt), 543 GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); 544 545 /* same test as in zipbare(): */ 546 547 #ifdef ZIP10 /* check two bytes */ 548 c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; 549 Trace((stdout, 550 " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", 551 (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), 552 ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); 553 if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? 554 ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : 555 (ush)(GLOBAL(lrec.crc32) >> 16))) 556 return -1; /* bad */ 557 #else 558 b = hh[RAND_HEAD_LEN-1]; 559 Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", 560 b, (ush)(GLOBAL(lrec.crc32) >> 24), 561 ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); 562 if (b != (GLOBAL(pInfo->ExtLocHdr) ? 563 ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : 564 (ush)(GLOBAL(lrec.crc32) >> 24))) 565 return -1; /* bad */ 566 #endif 567 /* password OK: decrypt current buffer contents before leaving */ 568 for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? 569 (int)GLOBAL(csize) : GLOBAL(incnt), 570 p = GLOBAL(inptr); n--; p++) 571 zdecode(*p); 572 return 0; /* OK */ 573 574 } /* end function testkey() */ 575 576 #endif /* UNZIP && !FUNZIP */ 577 578 #else /* !CRYPT */ 579 580 /* something "externally visible" to shut up compiler/linker warnings */ 581 int zcr_dummy; 582 583 #endif /* ?CRYPT */ 584