Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / bin / unzip / cryptf.c
blobf84ea323907d4487a90c046d8644f8f4db046e9b
1 /*
2 Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
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!! ***
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.)
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.
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).
33 #define FUNZIP
34 #define ZCRYPT_INTERNAL
35 #include "zip.h"
36 #include "crypt.h"
37 #include "ttyio.h"
39 #if CRYPT
41 #ifndef FALSE
42 # define FALSE 0
43 #endif
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().
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.
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 */
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 */
101 #ifndef UNZIP /* moved to globals.h for UnZip */
102 local ulg keys[3]; /* keys defining the pseudo-random sequence */
103 #endif /* !UNZIP */
105 #ifndef Trace
106 # ifdef CRYPT_DEBUG
107 # define Trace(x) fprintf x
108 # else
109 # define Trace(x)
110 # endif
111 #endif
113 #ifndef CRC_32_TAB
114 # define CRC_32_TAB crc_32_tab
115 #endif
117 #define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
119 /***********************************************************************
120 * Return the next byte in the pseudo-random sequence
122 int decrypt_byte(__G)
123 __GDEF
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 */
129 temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2;
130 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
133 /***********************************************************************
134 * Update the encryption keys with the next byte of plain text
136 int update_keys(__G__ c)
137 __GDEF
138 int c; /* byte of plain text */
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;
144 register int keyshift = (int)(GLOBAL(keys[1]) >> 24);
145 GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift);
147 return c;
151 /***********************************************************************
152 * Initialize the encryption keys and the random header according to
153 * the given password.
155 void init_keys(__G__ passwd)
156 __GDEF
157 ZCONST char *passwd; /* password string with which to modify keys */
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++;
169 #ifdef ZIP
171 /***********************************************************************
172 * Write encryption header to file zfile using the password passwd
173 * and the cyclic redundancy check crc.
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 */
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 */
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.
191 if (++calls == 1) {
192 srand((unsigned)time(NULL) ^ ZCR_SEED2);
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);
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);
205 ztemp = zencode((int)(crc >> 16) & 0xff, t);
206 putc(ztemp, zfile);
207 ztemp = zencode((int)(crc >> 24) & 0xff, t);
208 putc(ztemp, zfile);
212 #ifdef UTIL
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.
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 */
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 */
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;
240 /* Initialize keys with password and write random header */
241 crypthead(passwd, z->crc, dest);
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;
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;
254 ztemp = zencode(c, t);
255 putc(ztemp, dest);
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;
261 if (fflush(dest) == EOF) return ZE_TEMP;
262 return ZE_OK;
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.
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 */
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 */
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;
287 /* Initialize keys with password */
288 init_keys(passwd);
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;
297 Trace((stdout, " (%02x)", c1));
298 zdecode(c1);
299 Trace((stdout, " %02x", c1));
301 Trace((stdout, "\n"));
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.
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;
317 if ((res = zipcopy(z, source, dest)) != ZE_OK) return res;
318 return ZE_MISS;
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;
331 /* Decrypt data */
332 for (size = z->siz; size; size--) {
333 if ((c1 = getc(source)) == EOF) {
334 return ferror(source) ? ZE_READ : ZE_EOF;
336 zdecode(c1);
337 putc(c1, dest);
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;
343 if (fflush(dest) == EOF) return ZE_TEMP;
345 return ZE_OK;
349 #else /* !UTIL */
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.
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 */
361 int t; /* temporary */
363 if (key != (char *)NULL) { /* key is the global password pointer */
364 ulg size; /* buffer size */
365 char *p = (char*)buf; /* steps through buffer */
367 /* Encrypt data in buffer */
368 for (size = item_size*(ulg)nb; size != 0; p++, size--) {
369 *p = (char)zencode(*p, t);
372 /* Write the buffer out */
373 return fwrite(buf, item_size, nb, f);
376 #endif /* ?UTIL */
377 #endif /* ZIP */
380 #if (defined(UNZIP) && !defined(FUNZIP))
382 /***********************************************************************
383 * Get the password and set up keys for current zipfile member.
384 * Return PK_ class error.
386 int decrypt(__G__ passwrd)
387 __GDEF
388 ZCONST char *passwrd;
390 ush b;
391 int n, r;
392 uch h[RAND_HEAD_LEN];
394 Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt)));
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]));
405 undefer_input(__G);
406 GLOBAL(pInfo->encrypted) = TRUE;
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! */
418 } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */
419 free(GLOBAL(key));
420 GLOBAL(key) = (char *)NULL;
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;
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;
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. */
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);
453 return PK_WARN;
455 } /* end function decrypt() */
459 /***********************************************************************
460 * Test the password. Return -1 if bad, 0 if OK.
462 local int testp(__G__ h)
463 __GDEF
464 ZCONST uch *h;
466 int r;
467 char *key_translated;
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. */
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 */
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
502 #endif /* STR_TO_CP2 */
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));
510 #endif /* STR_TO_CP1 */
512 return r;
514 } /* end function testp() */
517 local int testkey(__G__ h, key)
518 __GDEF
519 ZCONST uch *h; /* decrypted header */
520 ZCONST char *key; /* decryption password to test */
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 */
530 /* set keys and save the encrypted header */
531 init_keys(__G__ key);
532 memcpy(hh, h, RAND_HEAD_LEN);
534 /* check password */
535 for (n = 0; n < RAND_HEAD_LEN; n++) {
536 zdecode(hh[n]);
537 Trace((stdout, " %02x", hh[n]));
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))));
548 /* same test as in zipbare(): */
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 */
577 } /* end function testkey() */
579 #endif /* UNZIP && !FUNZIP */
581 #else /* !CRYPT */
583 /* something "externally visible" to shut up compiler/linker warnings */
584 int zcr_dummy;
586 #endif /* ?CRYPT */