xref: /haiku/src/bin/unzip/crypt.c (revision f2b4344867e97c3f4e742a1b4a15e6879644601a)
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