4
|
1 /* |
|
2 zip_source_pkware.c -- Traditional PKWARE de/encryption routines |
|
3 Copyright (C) 2009-2015 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 #include <stdlib.h> |
|
36 #include <string.h> |
|
37 |
|
38 #include "zipint.h" |
|
39 |
|
40 struct trad_pkware { |
|
41 zip_error_t error; |
|
42 zip_uint32_t key[3]; |
|
43 }; |
|
44 |
|
45 #define HEADERLEN 12 |
|
46 #define KEY0 305419896 |
|
47 #define KEY1 591751049 |
|
48 #define KEY2 878082192 |
|
49 |
|
50 |
|
51 static void decrypt(struct trad_pkware *, zip_uint8_t *, |
|
52 const zip_uint8_t *, zip_uint64_t, int); |
|
53 static int decrypt_header(zip_source_t *, struct trad_pkware *); |
|
54 static zip_int64_t pkware_decrypt(zip_source_t *, void *, void *, |
|
55 zip_uint64_t, zip_source_cmd_t); |
|
56 static void pkware_free(struct trad_pkware *); |
|
57 |
|
58 |
|
59 zip_source_t * |
|
60 zip_source_pkware(zip_t *za, zip_source_t *src, |
|
61 zip_uint16_t em, int flags, const char *password) |
|
62 { |
|
63 struct trad_pkware *ctx; |
|
64 zip_source_t *s2; |
|
65 |
|
66 if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { |
|
67 zip_error_set(&za->error, ZIP_ER_INVAL, 0); |
|
68 return NULL; |
|
69 } |
|
70 if (flags & ZIP_CODEC_ENCODE) { |
|
71 zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); |
|
72 return NULL; |
|
73 } |
|
74 |
|
75 if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { |
|
76 zip_error_set(&za->error, ZIP_ER_MEMORY, 0); |
|
77 return NULL; |
|
78 } |
|
79 |
|
80 zip_error_init(&ctx->error); |
|
81 |
|
82 ctx->key[0] = KEY0; |
|
83 ctx->key[1] = KEY1; |
|
84 ctx->key[2] = KEY2; |
|
85 decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1); |
|
86 |
|
87 if ((s2=zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) { |
|
88 pkware_free(ctx); |
|
89 return NULL; |
|
90 } |
|
91 |
|
92 return s2; |
|
93 } |
|
94 |
|
95 |
|
96 static void |
|
97 decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, |
|
98 zip_uint64_t len, int update_only) |
|
99 { |
|
100 zip_uint16_t tmp; |
|
101 zip_uint64_t i; |
|
102 Bytef b; |
|
103 |
|
104 for (i=0; i<len; i++) { |
|
105 b = in[i]; |
|
106 |
|
107 if (!update_only) { |
|
108 /* decrypt next byte */ |
|
109 tmp = (zip_uint16_t)(ctx->key[2] | 2); |
|
110 tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8); |
|
111 b ^= (Bytef)tmp; |
|
112 } |
|
113 |
|
114 /* store cleartext */ |
|
115 if (out) |
|
116 out[i] = b; |
|
117 |
|
118 /* update keys */ |
|
119 ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; |
|
120 ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1; |
|
121 b = (Bytef)(ctx->key[1] >> 24); |
|
122 ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; |
|
123 } |
|
124 } |
|
125 |
|
126 |
|
127 static int |
|
128 decrypt_header(zip_source_t *src, struct trad_pkware *ctx) |
|
129 { |
|
130 zip_uint8_t header[HEADERLEN]; |
|
131 struct zip_stat st; |
|
132 zip_int64_t n; |
|
133 unsigned short dostime, dosdate; |
|
134 |
|
135 if ((n=zip_source_read(src, header, HEADERLEN)) < 0) { |
|
136 _zip_error_set_from_source(&ctx->error, src); |
|
137 return -1; |
|
138 } |
|
139 |
|
140 if (n != HEADERLEN) { |
|
141 zip_error_set(&ctx->error, ZIP_ER_EOF, 0); |
|
142 return -1; |
|
143 } |
|
144 |
|
145 decrypt(ctx, header, header, HEADERLEN, 0); |
|
146 |
|
147 if (zip_source_stat(src, &st) < 0) { |
|
148 /* stat failed, skip password validation */ |
|
149 return 0; |
|
150 } |
|
151 |
|
152 _zip_u2d_time(st.mtime, &dostime, &dosdate); |
|
153 |
|
154 if (header[HEADERLEN-1] != st.crc>>24 && header[HEADERLEN-1] != dostime>>8) { |
|
155 zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); |
|
156 return -1; |
|
157 } |
|
158 |
|
159 return 0; |
|
160 } |
|
161 |
|
162 |
|
163 static zip_int64_t |
|
164 pkware_decrypt(zip_source_t *src, void *ud, void *data, |
|
165 zip_uint64_t len, zip_source_cmd_t cmd) |
|
166 { |
|
167 struct trad_pkware *ctx; |
|
168 zip_int64_t n; |
|
169 |
|
170 ctx = (struct trad_pkware *)ud; |
|
171 |
|
172 switch (cmd) { |
|
173 case ZIP_SOURCE_OPEN: |
|
174 if (decrypt_header(src, ctx) < 0) |
|
175 return -1; |
|
176 return 0; |
|
177 |
|
178 case ZIP_SOURCE_READ: |
|
179 if ((n=zip_source_read(src, data, len)) < 0) { |
|
180 _zip_error_set_from_source(&ctx->error, src); |
|
181 return -1; |
|
182 } |
|
183 |
|
184 decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, 0); |
|
185 return n; |
|
186 |
|
187 case ZIP_SOURCE_CLOSE: |
|
188 return 0; |
|
189 |
|
190 case ZIP_SOURCE_STAT: |
|
191 { |
|
192 zip_stat_t *st; |
|
193 |
|
194 st = (zip_stat_t *)data; |
|
195 |
|
196 st->encryption_method = ZIP_EM_NONE; |
|
197 st->valid |= ZIP_STAT_ENCRYPTION_METHOD; |
|
198 /* TODO: deduce HEADERLEN from size for uncompressed */ |
|
199 if (st->valid & ZIP_STAT_COMP_SIZE) |
|
200 st->comp_size -= HEADERLEN; |
|
201 |
|
202 return 0; |
|
203 } |
|
204 |
|
205 case ZIP_SOURCE_SUPPORTS: |
|
206 return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); |
|
207 |
|
208 case ZIP_SOURCE_ERROR: |
|
209 return zip_error_to_data(&ctx->error, data, len); |
|
210 |
|
211 case ZIP_SOURCE_FREE: |
|
212 pkware_free(ctx); |
|
213 return 0; |
|
214 |
|
215 default: |
|
216 zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); |
|
217 return -1; |
|
218 } |
|
219 } |
|
220 |
|
221 |
|
222 static void |
|
223 pkware_free(struct trad_pkware *ctx) |
|
224 { |
|
225 free(ctx); |
|
226 } |