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