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  */
decrypt_byte(__G)149 int 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  */
163 int 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  */
183 void 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
crytab_init(__G)212 local 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  */
crypthead(passwd,crc,zfile)231 void 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  */
zipcloak(z,source,dest,passwd)271 int 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  */
zipbare(z,source,dest,passwd)326 int 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  */
zfwrite(buf,item_size,nb,f)422 unsigned 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  */
453 int 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         /* 2012-11-23 SMS.  (OUSPG report.)
469          * Quit early if compressed size < HEAD_LEN.  The resulting
470          * error message ("unable to get password") could be improved,
471          * but it's better than trying to read nonexistent data, and
472          * then continuing with a negative G.csize.  (See
473          * fileio.c:readbyte()).
474          */
475         if ((b = NEXTBYTE) == (ush)EOF)
476         {
477             return PK_ERR;
478         }
479         h[n] = (uch)b;
480         Trace((stdout, " (%02x)", h[n]));
481     }
482     undefer_input(__G);
483     GLOBAL(pInfo->encrypted) = TRUE;
484 
485     if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */
486         GLOBAL(newzip) = FALSE;
487         if (passwrd != (char *)NULL) { /* user gave password on command line */
488             if (!GLOBAL(key)) {
489                 if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) ==
490                     (char *)NULL)
491                     return PK_MEM2;
492                 strcpy(GLOBAL(key), passwrd);
493                 GLOBAL(nopwd) = TRUE;  /* inhibit password prompting! */
494             }
495         } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */
496             free(GLOBAL(key));
497             GLOBAL(key) = (char *)NULL;
498         }
499     }
500 
501     /* if have key already, test it; else allocate memory for it */
502     if (GLOBAL(key)) {
503         if (!testp(__G__ h))
504             return PK_COOL;   /* existing password OK (else prompt for new) */
505         else if (GLOBAL(nopwd))
506             return PK_WARN;   /* user indicated no more prompting */
507     } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)
508         return PK_MEM2;
509 
510     /* try a few keys */
511     n = 0;
512     do {
513         r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1,
514                              GLOBAL(zipfn), GLOBAL(filename));
515         if (r == IZ_PW_ERROR) {         /* internal error in fetch of PW */
516             free (GLOBAL(key));
517             GLOBAL(key) = NULL;
518             return PK_MEM2;
519         }
520         if (r != IZ_PW_ENTERED) {       /* user replied "skip" or "skip all" */
521             *GLOBAL(key) = '\0';        /*   We try the NIL password, ... */
522             n = 0;                      /*   and cancel fetch for this item. */
523         }
524         if (!testp(__G__ h))
525             return PK_COOL;
526         if (r == IZ_PW_CANCELALL)       /* User replied "Skip all" */
527             GLOBAL(nopwd) = TRUE;       /*   inhibit any further PW prompt! */
528     } while (n > 0);
529 
530     return PK_WARN;
531 
532 } /* end function decrypt() */
533 
534 
535 
536 /***********************************************************************
537  * Test the password.  Return -1 if bad, 0 if OK.
538  */
539 local int testp(__G__ h)
540     __GDEF
541     ZCONST uch *h;
542 {
543     int r;
544     char *key_translated;
545 
546     /* On systems with "obscure" native character coding (e.g., EBCDIC),
547      * the first test translates the password to the "main standard"
548      * character coding. */
549 
550 #ifdef STR_TO_CP1
551     /* allocate buffer for translated password */
552     if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)
553         return -1;
554     /* first try, test password translated "standard" charset */
555     r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key)));
556 #else /* !STR_TO_CP1 */
557     /* first try, test password as supplied on the extractor's host */
558     r = testkey(__G__ h, GLOBAL(key));
559 #endif /* ?STR_TO_CP1 */
560 
561 #ifdef STR_TO_CP2
562     if (r != 0) {
563 #ifndef STR_TO_CP1
564         /* now prepare for second (and maybe third) test with translated pwd */
565         if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)
566             return -1;
567 #endif
568         /* second try, password translated to alternate ("standard") charset */
569         r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key)));
570 #ifdef STR_TO_CP3
571         if (r != 0)
572             /* third try, password translated to another "standard" charset */
573             r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key)));
574 #endif
575 #ifndef STR_TO_CP1
576         free(key_translated);
577 #endif
578     }
579 #endif /* STR_TO_CP2 */
580 
581 #ifdef STR_TO_CP1
582     free(key_translated);
583     if (r != 0) {
584         /* last resort, test password as supplied on the extractor's host */
585         r = testkey(__G__ h, GLOBAL(key));
586     }
587 #endif /* STR_TO_CP1 */
588 
589     return r;
590 
591 } /* end function testp() */
592 
593 
594 local int testkey(__G__ h, key)
595     __GDEF
596     ZCONST uch *h;      /* decrypted header */
597     ZCONST char *key;   /* decryption password to test */
598 {
599     ush b;
600 #ifdef ZIP10
601     ush c;
602 #endif
603     int n;
604     uch *p;
605     uch hh[RAND_HEAD_LEN]; /* decrypted header */
606 
607     /* set keys and save the encrypted header */
608     init_keys(__G__ key);
609     memcpy(hh, h, RAND_HEAD_LEN);
610 
611     /* check password */
612     for (n = 0; n < RAND_HEAD_LEN; n++) {
613         zdecode(hh[n]);
614         Trace((stdout, " %02x", hh[n]));
615     }
616 
617     Trace((stdout,
618       "\n  lrec.crc= %08lx  crec.crc= %08lx  pInfo->ExtLocHdr= %s\n",
619       GLOBAL(lrec.crc32), GLOBAL(pInfo->crc),
620       GLOBAL(pInfo->ExtLocHdr) ? "true":"false"));
621     Trace((stdout, "  incnt = %d  unzip offset into zipfile = %ld\n",
622       GLOBAL(incnt),
623       GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf))));
624 
625     /* same test as in zipbare(): */
626 
627 #ifdef ZIP10 /* check two bytes */
628     c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1];
629     Trace((stdout,
630       "  (c | (b<<8)) = %04x  (crc >> 16) = %04x  lrec.time = %04x\n",
631       (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16),
632       ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff))));
633     if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ?
634                            ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) :
635                            (ush)(GLOBAL(lrec.crc32) >> 16)))
636         return -1;  /* bad */
637 #else
638     b = hh[RAND_HEAD_LEN-1];
639     Trace((stdout, "  b = %02x  (crc >> 24) = %02x  (lrec.time >> 8) = %02x\n",
640       b, (ush)(GLOBAL(lrec.crc32) >> 24),
641       ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff));
642     if (b != (GLOBAL(pInfo->ExtLocHdr) ?
643         ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff :
644         (ush)(GLOBAL(lrec.crc32) >> 24)))
645         return -1;  /* bad */
646 #endif
647     /* password OK:  decrypt current buffer contents before leaving */
648     for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ?
649              (int)GLOBAL(csize) : GLOBAL(incnt),
650          p = GLOBAL(inptr); n--; p++)
651         zdecode(*p);
652     return 0;       /* OK */
653 
654 } /* end function testkey() */
655 
656 #endif /* UNZIP && !FUNZIP */
657 
658 #else /* !CRYPT */
659 
660 /* something "externally visible" to shut up compiler/linker warnings */
661 int zcr_dummy;
662 
663 #endif /* ?CRYPT */
664