libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / bin / unzip / crypt.c
blob8590e5af22ec59bdee175a1afa80f52d45bfc9e5
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 crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
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.)
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.
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).
31 #define ZCRYPT_INTERNAL
32 #include "zip.h"
33 #include "crypt.h"
34 #include "ttyio.h"
36 #if CRYPT
38 #ifndef FALSE
39 # define FALSE 0
40 #endif
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().
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.
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 */
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 */
98 #ifndef UNZIP /* moved to globals.h for UnZip */
99 local ulg keys[3]; /* keys defining the pseudo-random sequence */
100 #endif /* !UNZIP */
102 #ifndef Trace
103 # ifdef CRYPT_DEBUG
104 # define Trace(x) fprintf x
105 # else
106 # define Trace(x)
107 # endif
108 #endif
110 #ifndef CRC_32_TAB
111 # define CRC_32_TAB crc_32_tab
112 #endif
114 #define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
116 /***********************************************************************
117 * Return the next byte in the pseudo-random sequence
119 int decrypt_byte(__G)
120 __GDEF
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 */
126 temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2;
127 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
130 /***********************************************************************
131 * Update the encryption keys with the next byte of plain text
133 int update_keys(__G__ c)
134 __GDEF
135 int c; /* byte of plain text */
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;
141 register int keyshift = (int)(GLOBAL(keys[1]) >> 24);
142 GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift);
144 return c;
148 /***********************************************************************
149 * Initialize the encryption keys and the random header according to
150 * the given password.
152 void init_keys(__G__ passwd)
153 __GDEF
154 ZCONST char *passwd; /* password string with which to modify keys */
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++;
166 #ifdef ZIP
168 /***********************************************************************
169 * Write encryption header to file zfile using the password passwd
170 * and the cyclic redundancy check crc.
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 */
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 */
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.
188 if (++calls == 1) {
189 srand((unsigned)time(NULL) ^ ZCR_SEED2);
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);
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);
202 ztemp = zencode((int)(crc >> 16) & 0xff, t);
203 putc(ztemp, zfile);
204 ztemp = zencode((int)(crc >> 24) & 0xff, t);
205 putc(ztemp, zfile);
209 #ifdef UTIL
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.
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 */
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 */
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;
237 /* Initialize keys with password and write random header */
238 crypthead(passwd, z->crc, dest);
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;
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;
251 ztemp = zencode(c, t);
252 putc(ztemp, dest);
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;
258 if (fflush(dest) == EOF) return ZE_TEMP;
259 return ZE_OK;
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.
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 */
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 */
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;
284 /* Initialize keys with password */
285 init_keys(passwd);
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;
294 Trace((stdout, " (%02x)", c1));
295 zdecode(c1);
296 Trace((stdout, " %02x", c1));
298 Trace((stdout, "\n"));
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.
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;
314 if ((res = zipcopy(z, source, dest)) != ZE_OK) return res;
315 return ZE_MISS;
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;
328 /* Decrypt data */
329 for (size = z->siz; size; size--) {
330 if ((c1 = getc(source)) == EOF) {
331 return ferror(source) ? ZE_READ : ZE_EOF;
333 zdecode(c1);
334 putc(c1, dest);
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;
340 if (fflush(dest) == EOF) return ZE_TEMP;
342 return ZE_OK;
346 #else /* !UTIL */
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.
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 */
358 int t; /* temporary */
360 if (key != (char *)NULL) { /* key is the global password pointer */
361 ulg size; /* buffer size */
362 char *p = (char*)buf; /* steps through buffer */
364 /* Encrypt data in buffer */
365 for (size = item_size*(ulg)nb; size != 0; p++, size--) {
366 *p = (char)zencode(*p, t);
369 /* Write the buffer out */
370 return fwrite(buf, item_size, nb, f);
373 #endif /* ?UTIL */
374 #endif /* ZIP */
377 #if (defined(UNZIP) && !defined(FUNZIP))
379 /***********************************************************************
380 * Get the password and set up keys for current zipfile member.
381 * Return PK_ class error.
383 int decrypt(__G__ passwrd)
384 __GDEF
385 ZCONST char *passwrd;
387 ush b;
388 int n, r;
389 uch h[RAND_HEAD_LEN];
391 Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt)));
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]));
402 undefer_input(__G);
403 GLOBAL(pInfo->encrypted) = TRUE;
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! */
415 } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */
416 free(GLOBAL(key));
417 GLOBAL(key) = (char *)NULL;
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;
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;
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. */
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);
450 return PK_WARN;
452 } /* end function decrypt() */
456 /***********************************************************************
457 * Test the password. Return -1 if bad, 0 if OK.
459 local int testp(__G__ h)
460 __GDEF
461 ZCONST uch *h;
463 int r;
464 char *key_translated;
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. */
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 */
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
499 #endif /* STR_TO_CP2 */
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));
507 #endif /* STR_TO_CP1 */
509 return r;
511 } /* end function testp() */
514 local int testkey(__G__ h, key)
515 __GDEF
516 ZCONST uch *h; /* decrypted header */
517 ZCONST char *key; /* decryption password to test */
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 */
527 /* set keys and save the encrypted header */
528 init_keys(__G__ key);
529 memcpy(hh, h, RAND_HEAD_LEN);
531 /* check password */
532 for (n = 0; n < RAND_HEAD_LEN; n++) {
533 zdecode(hh[n]);
534 Trace((stdout, " %02x", hh[n]));
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))));
545 /* same test as in zipbare(): */
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 */
574 } /* end function testkey() */
576 #endif /* UNZIP && !FUNZIP */
578 #else /* !CRYPT */
580 /* something "externally visible" to shut up compiler/linker warnings */
581 int zcr_dummy;
583 #endif /* ?CRYPT */