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