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