ddee1c8dd6b3e978902c8632661a2c055944c6ae
[platform/upstream/libzip.git] / lib / zip_source_winzip_aes_decode.c
1 /*
2   zip_source_winzip_aes.c -- Winzip AES de/encryption routines
3   Copyright (C) 2009-2017 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 #include "gladman-fcrypt.h"
41
42 #define MAX_HEADER_LENGTH (16+PWD_VER_LENGTH)
43 #define HMAC_LENGTH 10
44
45 static unsigned int salt_length[] = { 0, 8, 12, 16 };
46
47 struct winzip_aes {
48     char *password;
49     unsigned int mode;
50
51     zip_uint64_t data_length;
52     zip_uint64_t current_position;
53
54     fcrypt_ctx fcrypt_ctx;
55     zip_error_t error;
56 };
57
58
59 static int decrypt_header(zip_source_t *src, struct winzip_aes *ctx);
60 static void winzip_aes_free(struct winzip_aes *);
61 static zip_int64_t winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
62 static struct winzip_aes * winzip_aes_new(unsigned int mode, const char *password);
63
64
65 zip_source_t *
66 zip_source_winzip_aes_decode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password)
67 {
68     zip_source_t *s2;
69     unsigned int mode = 0;
70     zip_stat_t st;
71     zip_uint64_t aux_length;
72     struct winzip_aes *ctx;
73
74     switch (em) {
75     case ZIP_EM_AES_128:
76         mode = 1;
77         break;
78     case ZIP_EM_AES_192:
79         mode = 2;
80         break;
81     case ZIP_EM_AES_256:
82         mode = 3;
83         break;
84     }
85         
86     if (password == NULL || src == NULL || mode == 0) {
87         zip_error_set(&za->error, ZIP_ER_INVAL, 0);
88         return NULL;
89     }
90     if (flags & ZIP_CODEC_ENCODE) {
91         zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
92         return NULL;
93     }
94
95     if (strlen(password) > UINT_MAX) {
96         zip_error_set(&za->error, ZIP_ER_INVAL, 0); /* TODO: better error code? (password too long) */
97         return NULL;
98     }
99
100     if (zip_source_stat(src, &st) != 0) {
101         _zip_error_set_from_source(&za->error, src);
102         return NULL;
103     }
104
105     aux_length = PWD_VER_LENGTH + salt_length[mode] + HMAC_LENGTH;
106     
107     if ((st.valid & ZIP_STAT_COMP_SIZE) == 0 || st.comp_size < aux_length) {
108         zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
109         return NULL;
110     }
111
112     if ((ctx = winzip_aes_new(mode, password)) == NULL) {
113         zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
114         return NULL;
115     }
116
117     ctx->data_length = st.comp_size - aux_length;
118
119     if ((s2 = zip_source_layered(za, src, winzip_aes_decrypt, ctx)) == NULL) {
120         winzip_aes_free(ctx);
121         return NULL;
122     }
123
124     return s2;
125 }
126
127
128 static int
129 decrypt_header(zip_source_t *src, struct winzip_aes *ctx)
130 {
131     zip_uint8_t header[MAX_HEADER_LENGTH];
132     zip_uint8_t password_verification[PWD_VER_LENGTH];
133     unsigned int headerlen;
134     zip_int64_t n;
135
136     headerlen = PWD_VER_LENGTH + salt_length[ctx->mode];
137     if ((n=zip_source_read(src, header, headerlen)) < 0) {
138         _zip_error_set_from_source(&ctx->error, src);
139         return -1;
140     }
141     
142     if (n != headerlen) {
143         zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
144         return -1;
145     }
146
147     if (_zip_fcrypt_init(ctx->mode, (unsigned char *)ctx->password, (unsigned int)strlen(ctx->password), header, password_verification, &ctx->fcrypt_ctx) != 0) {
148         zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
149         return -1;
150     }
151     if (memcmp(password_verification, header + salt_length[ctx->mode], PWD_VER_LENGTH) != 0) {
152         zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0);
153         return -1;
154     }
155     return 0;
156 }
157
158
159 static bool
160 verify_hmac(zip_source_t *src, struct winzip_aes *ctx)
161 {
162     unsigned char computed[HMAC_LENGTH], from_file[HMAC_LENGTH];
163     if (zip_source_read(src, from_file, HMAC_LENGTH) < HMAC_LENGTH) {
164         _zip_error_set_from_source(&ctx->error, src);
165         return false;
166     }
167
168     _zip_fcrypt_end(computed, &ctx->fcrypt_ctx);
169     
170     if (memcmp(from_file, computed, HMAC_LENGTH) != 0) {
171         zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
172         return false;
173     }
174
175     return true;
176 }
177
178
179 static zip_int64_t
180 winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
181 {
182     struct winzip_aes *ctx;
183     zip_int64_t n;
184     zip_uint64_t total, offset;
185
186     ctx = (struct winzip_aes *)ud;
187
188     switch (cmd) {
189     case ZIP_SOURCE_OPEN:
190         if (decrypt_header(src, ctx) < 0) {
191             return -1;
192         }
193         ctx->current_position = 0;
194         return 0;
195
196     case ZIP_SOURCE_READ:
197         if (len > ctx->data_length - ctx->current_position) {
198             len = ctx->data_length - ctx->current_position;
199         }
200
201         if (len == 0) {
202             if (!verify_hmac(src, ctx)) {
203                 return -1;
204             }
205             return 0;
206         }
207         
208         if ((n=zip_source_read(src, data, len)) < 0) {
209             _zip_error_set_from_source(&ctx->error, src);
210             return -1;
211         }
212         ctx->current_position += (zip_uint64_t)n;
213
214         total = (zip_uint64_t)n;
215         for (offset = 0; offset < total; offset += ZIP_MIN(total - offset, UINT_MAX)) {
216             _zip_fcrypt_decrypt((zip_uint8_t *)data + offset, (unsigned int)ZIP_MIN(total - offset, UINT_MAX), &ctx->fcrypt_ctx);
217         }
218
219         return n;
220
221     case ZIP_SOURCE_CLOSE:
222         return 0;
223
224     case ZIP_SOURCE_STAT:
225     {
226         zip_stat_t *st;
227
228         st = (zip_stat_t *)data;
229
230         st->encryption_method = ZIP_EM_NONE;
231         st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
232         if (st->valid & ZIP_STAT_COMP_SIZE) {
233             st->comp_size -= 12 + salt_length[ctx->mode];
234         }
235         
236         return 0;
237     }
238             
239     case ZIP_SOURCE_SUPPORTS:
240         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);
241
242     case ZIP_SOURCE_ERROR:
243         return zip_error_to_data(&ctx->error, data, len);
244
245     case ZIP_SOURCE_FREE:
246         winzip_aes_free(ctx);
247         return 0;
248
249     default:
250         zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
251         return -1;
252     }
253 }
254
255
256 static void
257 winzip_aes_free(struct winzip_aes *ctx)
258 {
259     if (ctx == NULL) {
260         return;
261     }
262
263     _zip_crypto_clear(&ctx->fcrypt_ctx, sizeof(ctx->fcrypt_ctx));
264     _zip_crypto_clear(ctx->password, strlen(ctx->password));
265     free(ctx->password);
266     zip_error_fini(&ctx->error);
267     free(ctx);
268 }
269
270
271 static struct winzip_aes *
272 winzip_aes_new(unsigned int mode, const char *password) {
273     struct winzip_aes *ctx;
274     
275     if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) {
276         return NULL;
277     }
278     
279     if ((ctx->password = strdup(password)) == NULL) {
280         free(ctx);
281         return NULL;
282     }
283
284     ctx->mode = mode;
285
286     zip_error_init(&ctx->error);
287
288     return ctx;
289 }