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 */
122int 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 */
136int 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 */
155void 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 */
175void 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 */
218int 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 */
269int 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 */
355unsigned 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 */
386int 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 */
462local 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
517local 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 */
584int zcr_dummy;
585
586#endif /* ?CRYPT */
587