/src/minizip-ng/mz_crypt_openssl.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* mz_crypt_openssl.c -- Crypto/hash functions for OpenSSL |
2 | | part of the minizip-ng project |
3 | | |
4 | | Copyright (C) Nathan Moinvaziri |
5 | | https://github.com/zlib-ng/minizip-ng |
6 | | |
7 | | This program is distributed under the terms of the same license as zlib. |
8 | | See the accompanying LICENSE file for the full text of the license. |
9 | | */ |
10 | | |
11 | | #include "mz.h" |
12 | | |
13 | | #include <openssl/err.h> |
14 | | #include <openssl/engine.h> |
15 | | #include <openssl/rand.h> |
16 | | #include <openssl/sha.h> |
17 | | #include <openssl/aes.h> |
18 | | #include <openssl/crypto.h> |
19 | | #include <openssl/evp.h> |
20 | | #include <openssl/hmac.h> |
21 | | |
22 | | #if defined(MZ_ZIP_SIGNING) |
23 | | /* Note: https://www.imperialviolet.org/2015/10/17/boringssl.html says that |
24 | | BoringSSL does not support CMS. "#include <etc/cms.h>" will fail. See |
25 | | https://bugs.chromium.org/p/boringssl/issues/detail?id=421 |
26 | | */ |
27 | | #include <openssl/cms.h> |
28 | | #include <openssl/pkcs12.h> |
29 | | #include <openssl/x509.h> |
30 | | #endif |
31 | | |
32 | | /***************************************************************************/ |
33 | | |
34 | 5.75M | static void mz_crypt_init(void) { |
35 | 5.75M | static int32_t openssl_initialized = 0; |
36 | 5.75M | if (!openssl_initialized) { |
37 | 1 | OpenSSL_add_all_algorithms(); |
38 | | |
39 | 1 | ERR_load_BIO_strings(); |
40 | 1 | ERR_load_crypto_strings(); |
41 | | |
42 | 1 | ENGINE_load_builtin_engines(); |
43 | 1 | ENGINE_register_all_complete(); |
44 | | |
45 | 1 | openssl_initialized = 1; |
46 | 1 | } |
47 | 5.75M | } |
48 | | |
49 | 0 | int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { |
50 | 0 | int32_t result = 0; |
51 | |
|
52 | 0 | result = RAND_bytes(buf, size); |
53 | |
|
54 | 0 | if (!result) |
55 | 0 | return MZ_CRYPT_ERROR; |
56 | | |
57 | 0 | return size; |
58 | 0 | } |
59 | | |
60 | | /***************************************************************************/ |
61 | | |
62 | | typedef struct mz_crypt_sha_s { |
63 | | union { |
64 | | SHA512_CTX ctx512; |
65 | | SHA256_CTX ctx256; |
66 | | SHA_CTX ctx1; |
67 | | }; |
68 | | int32_t initialized; |
69 | | int32_t error; |
70 | | uint16_t algorithm; |
71 | | } mz_crypt_sha; |
72 | | |
73 | | /***************************************************************************/ |
74 | | |
75 | | static const uint8_t mz_crypt_sha_digest_size[] = { |
76 | | MZ_HASH_SHA1_SIZE, 0, MZ_HASH_SHA224_SIZE, |
77 | | MZ_HASH_SHA256_SIZE, MZ_HASH_SHA384_SIZE, MZ_HASH_SHA512_SIZE |
78 | | }; |
79 | | |
80 | | /***************************************************************************/ |
81 | | |
82 | 0 | void mz_crypt_sha_reset(void *handle) { |
83 | 0 | mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
84 | |
|
85 | 0 | sha->error = 0; |
86 | 0 | sha->initialized = 0; |
87 | |
|
88 | 0 | mz_crypt_init(); |
89 | 0 | } |
90 | | |
91 | 0 | int32_t mz_crypt_sha_begin(void *handle) { |
92 | 0 | mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
93 | 0 | int32_t result = 0; |
94 | |
|
95 | 0 | if (!sha) |
96 | 0 | return MZ_PARAM_ERROR; |
97 | | |
98 | 0 | mz_crypt_sha_reset(handle); |
99 | |
|
100 | 0 | switch (sha->algorithm) { |
101 | 0 | case MZ_HASH_SHA1: |
102 | 0 | result = SHA1_Init(&sha->ctx1); |
103 | 0 | break; |
104 | 0 | case MZ_HASH_SHA224: |
105 | 0 | result = SHA224_Init(&sha->ctx256); |
106 | 0 | break; |
107 | 0 | case MZ_HASH_SHA256: |
108 | 0 | result = SHA256_Init(&sha->ctx256); |
109 | 0 | break; |
110 | 0 | case MZ_HASH_SHA384: |
111 | 0 | result = SHA384_Init(&sha->ctx512); |
112 | 0 | break; |
113 | 0 | case MZ_HASH_SHA512: |
114 | 0 | result = SHA512_Init(&sha->ctx512); |
115 | 0 | break; |
116 | 0 | } |
117 | | |
118 | 0 | if (!result) { |
119 | 0 | sha->error = ERR_get_error(); |
120 | 0 | return MZ_HASH_ERROR; |
121 | 0 | } |
122 | | |
123 | 0 | sha->initialized = 1; |
124 | 0 | return MZ_OK; |
125 | 0 | } |
126 | | |
127 | 0 | int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) { |
128 | 0 | mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
129 | 0 | int32_t result = 0; |
130 | |
|
131 | 0 | if (!sha || !buf || !sha->initialized) |
132 | 0 | return MZ_PARAM_ERROR; |
133 | | |
134 | 0 | switch (sha->algorithm) { |
135 | 0 | case MZ_HASH_SHA1: |
136 | 0 | result = SHA1_Update(&sha->ctx1, buf, size); |
137 | 0 | break; |
138 | 0 | case MZ_HASH_SHA224: |
139 | 0 | result = SHA224_Update(&sha->ctx256, buf, size); |
140 | 0 | break; |
141 | 0 | case MZ_HASH_SHA256: |
142 | 0 | result = SHA256_Update(&sha->ctx256, buf, size); |
143 | 0 | break; |
144 | 0 | case MZ_HASH_SHA384: |
145 | 0 | result = SHA384_Update(&sha->ctx512, buf, size); |
146 | 0 | break; |
147 | 0 | case MZ_HASH_SHA512: |
148 | 0 | result = SHA512_Update(&sha->ctx512, buf, size); |
149 | 0 | break; |
150 | 0 | } |
151 | | |
152 | 0 | if (!result) { |
153 | 0 | sha->error = ERR_get_error(); |
154 | 0 | return MZ_HASH_ERROR; |
155 | 0 | } |
156 | | |
157 | 0 | return size; |
158 | 0 | } |
159 | | |
160 | 0 | int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) { |
161 | 0 | mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
162 | 0 | int32_t result = 0; |
163 | |
|
164 | 0 | if (!sha || !digest || !sha->initialized) |
165 | 0 | return MZ_PARAM_ERROR; |
166 | 0 | if (digest_size < mz_crypt_sha_digest_size[sha->algorithm - MZ_HASH_SHA1]) |
167 | 0 | return MZ_PARAM_ERROR; |
168 | | |
169 | 0 | switch (sha->algorithm) { |
170 | 0 | case MZ_HASH_SHA1: |
171 | 0 | result = SHA1_Final(digest, &sha->ctx1); |
172 | 0 | break; |
173 | 0 | case MZ_HASH_SHA224: |
174 | 0 | result = SHA224_Final(digest, &sha->ctx256); |
175 | 0 | break; |
176 | 0 | case MZ_HASH_SHA256: |
177 | 0 | result = SHA256_Final(digest, &sha->ctx256); |
178 | 0 | break; |
179 | 0 | case MZ_HASH_SHA384: |
180 | 0 | result = SHA384_Final(digest, &sha->ctx512); |
181 | 0 | break; |
182 | 0 | case MZ_HASH_SHA512: |
183 | 0 | result = SHA512_Final(digest, &sha->ctx512); |
184 | 0 | break; |
185 | 0 | } |
186 | | |
187 | 0 | if (!result) { |
188 | 0 | sha->error = ERR_get_error(); |
189 | 0 | return MZ_HASH_ERROR; |
190 | 0 | } |
191 | | |
192 | 0 | return MZ_OK; |
193 | 0 | } |
194 | | |
195 | 0 | void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { |
196 | 0 | mz_crypt_sha *sha = (mz_crypt_sha *)handle; |
197 | 0 | if (MZ_HASH_SHA1 <= algorithm && algorithm <= MZ_HASH_SHA512) |
198 | 0 | sha->algorithm = algorithm; |
199 | 0 | } |
200 | | |
201 | 0 | void *mz_crypt_sha_create(void **handle) { |
202 | 0 | mz_crypt_sha *sha = NULL; |
203 | |
|
204 | 0 | sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); |
205 | 0 | if (sha) |
206 | 0 | sha->algorithm = MZ_HASH_SHA256; |
207 | 0 | if (handle) |
208 | 0 | *handle = sha; |
209 | |
|
210 | 0 | return sha; |
211 | 0 | } |
212 | | |
213 | 0 | void mz_crypt_sha_delete(void **handle) { |
214 | 0 | mz_crypt_sha *sha = NULL; |
215 | 0 | if (!handle) |
216 | 0 | return; |
217 | 0 | sha = (mz_crypt_sha *)*handle; |
218 | 0 | if (sha) { |
219 | 0 | mz_crypt_sha_reset(*handle); |
220 | 0 | free(sha); |
221 | 0 | } |
222 | 0 | *handle = NULL; |
223 | 0 | } |
224 | | |
225 | | /***************************************************************************/ |
226 | | |
227 | | typedef struct mz_crypt_aes_s { |
228 | | AES_KEY key; |
229 | | int32_t mode; |
230 | | int32_t error; |
231 | | uint8_t *key_copy; |
232 | | int32_t key_length; |
233 | | } mz_crypt_aes; |
234 | | |
235 | | /***************************************************************************/ |
236 | | |
237 | 3.42k | void mz_crypt_aes_reset(void *handle) { |
238 | 3.42k | MZ_UNUSED(handle); |
239 | | |
240 | 3.42k | mz_crypt_init(); |
241 | 3.42k | } |
242 | | |
243 | 63.8k | int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size) { |
244 | 63.8k | mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
245 | | |
246 | 63.8k | if (!aes || !buf) |
247 | 0 | return MZ_PARAM_ERROR; |
248 | 63.8k | if (size != MZ_AES_BLOCK_SIZE) |
249 | 0 | return MZ_PARAM_ERROR; |
250 | | |
251 | 63.8k | AES_encrypt(buf, buf, &aes->key); |
252 | | /* Equivalent to AES_ecb_encrypt with AES_ENCRYPT */ |
253 | 63.8k | return size; |
254 | 63.8k | } |
255 | | |
256 | 0 | int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size) { |
257 | 0 | mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
258 | 0 | if (!aes || !buf) |
259 | 0 | return MZ_PARAM_ERROR; |
260 | 0 | if (size != MZ_AES_BLOCK_SIZE) |
261 | 0 | return MZ_PARAM_ERROR; |
262 | | |
263 | 0 | AES_decrypt(buf, buf, &aes->key); |
264 | | /* Equivalent to AES_ecb_encrypt with AES_DECRYPT */ |
265 | 0 | return size; |
266 | 0 | } |
267 | | |
268 | 1.71k | int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length) { |
269 | 1.71k | mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
270 | 1.71k | int32_t result = 0; |
271 | 1.71k | int32_t key_bits = 0; |
272 | | |
273 | 1.71k | if (!aes || !key || !key_length) |
274 | 0 | return MZ_PARAM_ERROR; |
275 | | |
276 | 1.71k | mz_crypt_aes_reset(handle); |
277 | | |
278 | 1.71k | key_bits = key_length * 8; |
279 | 1.71k | result = AES_set_encrypt_key(key, key_bits, &aes->key); |
280 | 1.71k | if (result) { |
281 | 0 | aes->error = ERR_get_error(); |
282 | 0 | return MZ_HASH_ERROR; |
283 | 0 | } |
284 | | |
285 | 1.71k | return MZ_OK; |
286 | 1.71k | } |
287 | | |
288 | 0 | int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length) { |
289 | 0 | mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
290 | 0 | int32_t result = 0; |
291 | 0 | int32_t key_bits = 0; |
292 | |
|
293 | 0 | if (!aes || !key || !key_length) |
294 | 0 | return MZ_PARAM_ERROR; |
295 | | |
296 | 0 | mz_crypt_aes_reset(handle); |
297 | |
|
298 | 0 | key_bits = key_length * 8; |
299 | 0 | result = AES_set_decrypt_key(key, key_bits, &aes->key); |
300 | 0 | if (result) { |
301 | 0 | aes->error = ERR_get_error(); |
302 | 0 | return MZ_HASH_ERROR; |
303 | 0 | } |
304 | | |
305 | 0 | return MZ_OK; |
306 | 0 | } |
307 | | |
308 | 1.71k | void mz_crypt_aes_set_mode(void *handle, int32_t mode) { |
309 | 1.71k | mz_crypt_aes *aes = (mz_crypt_aes *)handle; |
310 | 1.71k | aes->mode = mode; |
311 | 1.71k | } |
312 | | |
313 | 1.72k | void *mz_crypt_aes_create(void **handle) { |
314 | 1.72k | mz_crypt_aes *aes = NULL; |
315 | | |
316 | 1.72k | aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); |
317 | 1.72k | if (handle) |
318 | 1.72k | *handle = aes; |
319 | | |
320 | 1.72k | return aes; |
321 | 1.72k | } |
322 | | |
323 | 1.72k | void mz_crypt_aes_delete(void **handle) { |
324 | 1.72k | mz_crypt_aes *aes = NULL; |
325 | 1.72k | if (!handle) |
326 | 0 | return; |
327 | 1.72k | aes = (mz_crypt_aes *)*handle; |
328 | 1.72k | if (aes) |
329 | 1.72k | free(aes); |
330 | 1.72k | *handle = NULL; |
331 | 1.72k | } |
332 | | |
333 | | /***************************************************************************/ |
334 | | |
335 | | typedef struct mz_crypt_hmac_s { |
336 | | HMAC_CTX *ctx; |
337 | | int32_t initialized; |
338 | | int32_t error; |
339 | | uint16_t algorithm; |
340 | | } mz_crypt_hmac; |
341 | | |
342 | | /***************************************************************************/ |
343 | | |
344 | | #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2070000fL)) |
345 | | static HMAC_CTX *HMAC_CTX_new(void) { |
346 | | HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX)); |
347 | | if (ctx) |
348 | | HMAC_CTX_init(ctx); |
349 | | return ctx; |
350 | | } |
351 | | |
352 | | static void HMAC_CTX_free(HMAC_CTX *ctx) { |
353 | | if (ctx) { |
354 | | HMAC_CTX_cleanup(ctx); |
355 | | OPENSSL_free(ctx); |
356 | | } |
357 | | } |
358 | | #endif |
359 | | |
360 | | /***************************************************************************/ |
361 | | |
362 | 5.75M | void mz_crypt_hmac_reset(void *handle) { |
363 | 5.75M | mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
364 | | |
365 | 5.75M | HMAC_CTX_free(hmac->ctx); |
366 | | |
367 | 5.75M | hmac->ctx = NULL; |
368 | 5.75M | hmac->error = 0; |
369 | | |
370 | 5.75M | mz_crypt_init(); |
371 | 5.75M | } |
372 | | |
373 | 5.13k | int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) { |
374 | 5.13k | mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
375 | 5.13k | int32_t result = 0; |
376 | 5.13k | const EVP_MD *evp_md = NULL; |
377 | | |
378 | 5.13k | if (!hmac || !key) |
379 | 0 | return MZ_PARAM_ERROR; |
380 | | |
381 | 5.13k | mz_crypt_hmac_reset(handle); |
382 | | |
383 | 5.13k | hmac->ctx = HMAC_CTX_new(); |
384 | | |
385 | 5.13k | if (hmac->algorithm == MZ_HASH_SHA1) |
386 | 5.13k | evp_md = EVP_sha1(); |
387 | 0 | else |
388 | 0 | evp_md = EVP_sha256(); |
389 | | |
390 | 5.13k | result = HMAC_Init_ex(hmac->ctx, key, key_length, evp_md, NULL); |
391 | 5.13k | if (!result) { |
392 | 0 | hmac->error = ERR_get_error(); |
393 | 0 | return MZ_HASH_ERROR; |
394 | 0 | } |
395 | | |
396 | 5.13k | return MZ_OK; |
397 | 5.13k | } |
398 | | |
399 | 5.73M | int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) { |
400 | 5.73M | mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
401 | 5.73M | int32_t result = 0; |
402 | | |
403 | 5.73M | if (!hmac || !buf) |
404 | 0 | return MZ_PARAM_ERROR; |
405 | | |
406 | 5.73M | result = HMAC_Update(hmac->ctx, buf, size); |
407 | 5.73M | if (!result) { |
408 | 0 | hmac->error = ERR_get_error(); |
409 | 0 | return MZ_HASH_ERROR; |
410 | 0 | } |
411 | | |
412 | 5.73M | return MZ_OK; |
413 | 5.73M | } |
414 | | |
415 | 5.73M | int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) { |
416 | 5.73M | mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
417 | 5.73M | int32_t result = 0; |
418 | | |
419 | 5.73M | if (!hmac || !digest) |
420 | 0 | return MZ_PARAM_ERROR; |
421 | | |
422 | 5.73M | if (hmac->algorithm == MZ_HASH_SHA1) { |
423 | 5.73M | if (digest_size < MZ_HASH_SHA1_SIZE) |
424 | 0 | return MZ_BUF_ERROR; |
425 | | |
426 | 5.73M | result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size); |
427 | 5.73M | } else { |
428 | 0 | if (digest_size < MZ_HASH_SHA256_SIZE) |
429 | 0 | return MZ_BUF_ERROR; |
430 | 0 | result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size); |
431 | 0 | } |
432 | | |
433 | 5.73M | if (!result) { |
434 | 0 | hmac->error = ERR_get_error(); |
435 | 0 | return MZ_HASH_ERROR; |
436 | 0 | } |
437 | | |
438 | 5.73M | return MZ_OK; |
439 | 5.73M | } |
440 | | |
441 | 6.84k | void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) { |
442 | 6.84k | mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; |
443 | 6.84k | hmac->algorithm = algorithm; |
444 | 6.84k | } |
445 | | |
446 | 5.73M | int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) { |
447 | 5.73M | mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle; |
448 | 5.73M | mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle; |
449 | 5.73M | int32_t result = 0; |
450 | | |
451 | 5.73M | if (!source || !target) |
452 | 0 | return MZ_PARAM_ERROR; |
453 | | |
454 | 5.73M | mz_crypt_hmac_reset(target_handle); |
455 | | |
456 | 5.73M | if (!target->ctx) |
457 | 5.73M | target->ctx = HMAC_CTX_new(); |
458 | | |
459 | 5.73M | result = HMAC_CTX_copy(target->ctx, source->ctx); |
460 | 5.73M | if (!result) { |
461 | 0 | target->error = ERR_get_error(); |
462 | 0 | return MZ_HASH_ERROR; |
463 | 0 | } |
464 | | |
465 | 5.73M | return MZ_OK; |
466 | 5.73M | } |
467 | | |
468 | 6.86k | void *mz_crypt_hmac_create(void **handle) { |
469 | 6.86k | mz_crypt_hmac *hmac = NULL; |
470 | | |
471 | 6.86k | hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); |
472 | 6.86k | if (hmac) |
473 | 6.86k | hmac->algorithm = MZ_HASH_SHA256; |
474 | 6.86k | if (handle) |
475 | 6.86k | *handle = hmac; |
476 | | |
477 | 6.86k | return hmac; |
478 | 6.86k | } |
479 | | |
480 | 6.86k | void mz_crypt_hmac_delete(void **handle) { |
481 | 6.86k | mz_crypt_hmac *hmac = NULL; |
482 | 6.86k | if (!handle) |
483 | 0 | return; |
484 | 6.86k | hmac = (mz_crypt_hmac *)*handle; |
485 | 6.86k | if (hmac) { |
486 | 6.86k | mz_crypt_hmac_reset(*handle); |
487 | 6.86k | free(hmac); |
488 | 6.86k | } |
489 | 6.86k | *handle = NULL; |
490 | 6.86k | } |
491 | | |
492 | | /***************************************************************************/ |
493 | | |
494 | | #if defined(MZ_ZIP_SIGNING) |
495 | | int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size, |
496 | | const char *cert_pwd, uint8_t **signature, int32_t *signature_size) { |
497 | | PKCS12 *p12 = NULL; |
498 | | EVP_PKEY *evp_pkey = NULL; |
499 | | BUF_MEM *buf_mem = NULL; |
500 | | BIO *cert_bio = NULL; |
501 | | BIO *message_bio = NULL; |
502 | | BIO *signature_bio = NULL; |
503 | | CMS_ContentInfo *cms = NULL; |
504 | | CMS_SignerInfo *signer_info = NULL; |
505 | | STACK_OF(X509) *ca_stack = NULL; |
506 | | X509 *cert = NULL; |
507 | | int32_t result = 0; |
508 | | int32_t err = MZ_OK; |
509 | | |
510 | | if (!message || !cert_data || !signature || !signature_size) |
511 | | return MZ_PARAM_ERROR; |
512 | | |
513 | | mz_crypt_init(); |
514 | | |
515 | | *signature = NULL; |
516 | | *signature_size = 0; |
517 | | |
518 | | cert_bio = BIO_new_mem_buf(cert_data, cert_data_size); |
519 | | |
520 | | if (!d2i_PKCS12_bio(cert_bio, &p12)) |
521 | | err = MZ_SIGN_ERROR; |
522 | | if (err == MZ_OK) |
523 | | result = PKCS12_parse(p12, cert_pwd, &evp_pkey, &cert, &ca_stack); |
524 | | if (result) { |
525 | | cms = CMS_sign(NULL, NULL, ca_stack, NULL, CMS_BINARY | CMS_PARTIAL); |
526 | | if (cms) |
527 | | signer_info = CMS_add1_signer(cms, cert, evp_pkey, EVP_sha256(), 0); |
528 | | if (!signer_info) { |
529 | | err = MZ_SIGN_ERROR; |
530 | | } else { |
531 | | message_bio = BIO_new_mem_buf(message, message_size); |
532 | | signature_bio = BIO_new(BIO_s_mem()); |
533 | | |
534 | | result = CMS_final(cms, message_bio, NULL, CMS_BINARY); |
535 | | if (result) |
536 | | result = i2d_CMS_bio(signature_bio, cms); |
537 | | if (result) { |
538 | | BIO_flush(signature_bio); |
539 | | BIO_get_mem_ptr(signature_bio, &buf_mem); |
540 | | |
541 | | *signature_size = buf_mem->length; |
542 | | *signature = malloc(buf_mem->length); |
543 | | |
544 | | memcpy(*signature, buf_mem->data, buf_mem->length); |
545 | | } |
546 | | #if 0 |
547 | | BIO *yy = BIO_new_file("xyz", "wb"); |
548 | | BIO_write(yy, *signature, *signature_size); |
549 | | BIO_flush(yy); |
550 | | BIO_free(yy); |
551 | | #endif |
552 | | } |
553 | | } |
554 | | |
555 | | if (!result) |
556 | | err = MZ_SIGN_ERROR; |
557 | | |
558 | | if (cms) |
559 | | CMS_ContentInfo_free(cms); |
560 | | if (signature_bio) |
561 | | BIO_free(signature_bio); |
562 | | if (cert_bio) |
563 | | BIO_free(cert_bio); |
564 | | if (message_bio) |
565 | | BIO_free(message_bio); |
566 | | if (p12) |
567 | | PKCS12_free(p12); |
568 | | |
569 | | if (err != MZ_OK && *signature) { |
570 | | free(*signature); |
571 | | *signature = NULL; |
572 | | *signature_size = 0; |
573 | | } |
574 | | |
575 | | return err; |
576 | | } |
577 | | |
578 | | int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) { |
579 | | CMS_ContentInfo *cms = NULL; |
580 | | STACK_OF(X509) *signers = NULL; |
581 | | STACK_OF(X509) *intercerts = NULL; |
582 | | X509_STORE *cert_store = NULL; |
583 | | X509_LOOKUP *lookup = NULL; |
584 | | X509_STORE_CTX *store_ctx = NULL; |
585 | | BIO *message_bio = NULL; |
586 | | BIO *signature_bio = NULL; |
587 | | BUF_MEM *buf_mem = NULL; |
588 | | int32_t signer_count = 0; |
589 | | int32_t result = 0; |
590 | | int32_t i = 0; |
591 | | int32_t err = MZ_SIGN_ERROR; |
592 | | |
593 | | if (!message || !message_size || !signature || !signature_size) |
594 | | return MZ_PARAM_ERROR; |
595 | | |
596 | | mz_crypt_init(); |
597 | | |
598 | | cert_store = X509_STORE_new(); |
599 | | |
600 | | X509_STORE_load_locations(cert_store, "cacert.pem", NULL); |
601 | | X509_STORE_set_default_paths(cert_store); |
602 | | |
603 | | #if 0 |
604 | | BIO *yy = BIO_new_file("xyz", "wb"); |
605 | | BIO_write(yy, signature, signature_size); |
606 | | BIO_flush(yy); |
607 | | BIO_free(yy); |
608 | | #endif |
609 | | |
610 | | lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_file()); |
611 | | if (lookup) |
612 | | X509_LOOKUP_load_file(lookup, "cacert.pem", X509_FILETYPE_PEM); |
613 | | lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_hash_dir()); |
614 | | if (lookup) |
615 | | X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); |
616 | | |
617 | | signature_bio = BIO_new_mem_buf(signature, signature_size); |
618 | | message_bio = BIO_new(BIO_s_mem()); |
619 | | |
620 | | cms = d2i_CMS_bio(signature_bio, NULL); |
621 | | if (cms) { |
622 | | result = CMS_verify(cms, NULL, cert_store, NULL, message_bio, CMS_NO_SIGNER_CERT_VERIFY | CMS_BINARY); |
623 | | if (result) |
624 | | signers = CMS_get0_signers(cms); |
625 | | if (signers) |
626 | | intercerts = CMS_get1_certs(cms); |
627 | | if (intercerts) { |
628 | | /* Verify signer certificates */ |
629 | | signer_count = sk_X509_num(signers); |
630 | | if (signer_count > 0) |
631 | | err = MZ_OK; |
632 | | |
633 | | for (i = 0; i < signer_count; i++) { |
634 | | store_ctx = X509_STORE_CTX_new(); |
635 | | X509_STORE_CTX_init(store_ctx, cert_store, sk_X509_value(signers, i), intercerts); |
636 | | result = X509_verify_cert(store_ctx); |
637 | | if (store_ctx) |
638 | | X509_STORE_CTX_free(store_ctx); |
639 | | |
640 | | if (!result) { |
641 | | err = MZ_SIGN_ERROR; |
642 | | break; |
643 | | } |
644 | | } |
645 | | } |
646 | | |
647 | | BIO_get_mem_ptr(message_bio, &buf_mem); |
648 | | |
649 | | if (err == MZ_OK) { |
650 | | /* Verify the message */ |
651 | | if (((int32_t)buf_mem->length != message_size) || |
652 | | (memcmp(buf_mem->data, message, message_size) != 0)) |
653 | | err = MZ_SIGN_ERROR; |
654 | | } |
655 | | } |
656 | | |
657 | | #if 0 |
658 | | if (!result) |
659 | | printf(ERR_error_string(ERR_get_error(), NULL)); |
660 | | #endif |
661 | | |
662 | | if (cms) |
663 | | CMS_ContentInfo_free(cms); |
664 | | if (message_bio) |
665 | | BIO_free(message_bio); |
666 | | if (signature_bio) |
667 | | BIO_free(signature_bio); |
668 | | if (cert_store) |
669 | | X509_STORE_free(cert_store); |
670 | | |
671 | | return err; |
672 | | } |
673 | | #endif |