1 /*
2 zip_source_pkware.c -- Traditional PKWARE de/encryption routines
3 Copyright (C) 2009 Dieter Baron and Thomas Klausner
4
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
16 distribution.
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
19 written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "zipint.h"
40
41 struct trad_pkware {
42 int e[2];
43
44 zip_uint32_t key[3];
45 };
46
47 #define HEADERLEN 12
48 #define KEY0 305419896
49 #define KEY1 591751049
50 #define KEY2 878082192
51
52 static const uLongf *crc = NULL;
53
54 #define CRC32(c, b) (crc[((c) ^ (b)) & 0xff] ^ ((c) >> 8))
55
56
57
58 static void decrypt(struct trad_pkware *, zip_uint8_t *,
59 const zip_uint8_t *, zip_uint64_t, int);
60 static int decrypt_header(struct zip_source *, struct trad_pkware *);
61 static zip_int64_t pkware_decrypt(struct zip_source *, void *, void *,
62 zip_uint64_t, enum zip_source_cmd);
63 static void pkware_free(struct trad_pkware *);
64
65
66
67 ZIP_EXTERN(struct zip_source *)
zip_source_pkware(struct zip * za,struct zip_source * src,zip_uint16_t em,int flags,const char * password)68 zip_source_pkware(struct zip *za, struct zip_source *src,
69 zip_uint16_t em, int flags, const char *password)
70 {
71 struct trad_pkware *ctx;
72 struct zip_source *s2;
73
74 if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) {
75 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
76 return NULL;
77 }
78 if (flags & ZIP_CODEC_ENCODE) {
79 _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
80 return NULL;
81 }
82
83 if (crc == NULL)
84 crc = get_crc_table();
85
86 if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
87 _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
88 return NULL;
89 }
90
91 ctx->e[0] = ctx->e[1] = 0;
92
93 ctx->key[0] = KEY0;
94 ctx->key[1] = KEY1;
95 ctx->key[2] = KEY2;
96 decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1);
97
98 if ((s2=zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) {
99 pkware_free(ctx);
100 return NULL;
101 }
102
103 return s2;
104 }
105
106
107
108 static void
decrypt(struct trad_pkware * ctx,zip_uint8_t * out,const zip_uint8_t * in,zip_uint64_t len,int update_only)109 decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
110 zip_uint64_t len, int update_only)
111 {
112 zip_uint16_t tmp;
113 zip_uint64_t i;
114 Bytef b;
115
116 for (i=0; i<len; i++) {
117 b = in[i];
118
119 if (!update_only) {
120 /* decrypt next byte */
121 tmp = ctx->key[2] | 2;
122 tmp = (tmp * (tmp ^ 1)) >> 8;
123 b ^= tmp;
124 }
125
126 /* store cleartext */
127 if (out)
128 out[i] = b;
129
130 /* update keys */
131 ctx->key[0] = CRC32(ctx->key[0], b);
132 ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1;
133 b = ctx->key[1] >> 24;
134 ctx->key[2] = CRC32(ctx->key[2], b);
135 }
136 }
137
138
139
140 static int
decrypt_header(struct zip_source * src,struct trad_pkware * ctx)141 decrypt_header(struct zip_source *src, struct trad_pkware *ctx)
142 {
143 zip_uint8_t header[HEADERLEN];
144 struct zip_stat st;
145 zip_int64_t n;
146 unsigned short dostime, dosdate;
147
148 if ((n=zip_source_read(src, header, HEADERLEN)) < 0) {
149 zip_source_error(src, ctx->e, ctx->e+1);
150 return -1;
151 }
152
153 if (n != HEADERLEN) {
154 ctx->e[0] = ZIP_ER_EOF;
155 ctx->e[1] = 0;
156 return -1;
157 }
158
159 decrypt(ctx, header, header, HEADERLEN, 0);
160
161 if (zip_source_stat(src, &st) < 0) {
162 /* stat failed, skip password validation */
163 return 0;
164 }
165
166 _zip_u2d_time(st.mtime, &dostime, &dosdate);
167
168 if (header[HEADERLEN-1] != st.crc>>24
169 && header[HEADERLEN-1] != dostime>>8) {
170 ctx->e[0] = ZIP_ER_WRONGPASSWD;
171 ctx->e[1] = 0;
172 return -1;
173 }
174
175 return 0;
176 }
177
178
179
180 static zip_int64_t
pkware_decrypt(struct zip_source * src,void * ud,void * data,zip_uint64_t len,enum zip_source_cmd cmd)181 pkware_decrypt(struct zip_source *src, void *ud, void *data,
182 zip_uint64_t len, enum zip_source_cmd cmd)
183 {
184 struct trad_pkware *ctx;
185 zip_int64_t n;
186
187 ctx = (struct trad_pkware *)ud;
188
189 switch (cmd) {
190 case ZIP_SOURCE_OPEN:
191 if (decrypt_header(src, ctx) < 0)
192 return -1;
193 return 0;
194
195 case ZIP_SOURCE_READ:
196 if ((n=zip_source_read(src, data, len)) < 0)
197 return ZIP_SOURCE_ERR_LOWER;
198
199 decrypt(ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n,
200 0);
201 return n;
202
203 case ZIP_SOURCE_CLOSE:
204 return 0;
205
206 case ZIP_SOURCE_STAT:
207 {
208 struct zip_stat *st;
209
210 st = (struct zip_stat *)data;
211
212 st->encryption_method = ZIP_EM_NONE;
213 st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
214 /* XXX: deduce HEADERLEN from size for uncompressed */
215 if (st->valid & ZIP_STAT_COMP_SIZE)
216 st->comp_size -= HEADERLEN;
217 }
218 return 0;
219
220 case ZIP_SOURCE_ERROR:
221 memcpy(data, ctx->e, sizeof(int)*2);
222 return sizeof(int)*2;
223
224 case ZIP_SOURCE_FREE:
225 pkware_free(ctx);
226 return 0;
227
228 default:
229 ctx->e[0] = ZIP_ER_INVAL;
230 ctx->e[1] = 0;
231 return -1;
232 }
233 }
234
235
236
237 static void
pkware_free(struct trad_pkware * ctx)238 pkware_free(struct trad_pkware *ctx)
239 {
240 free(ctx);
241 }
242