]>
Commit | Line | Data |
---|---|---|
8931b30d DSH |
1 | /* crypto/cms/cms_smime.c */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | |
3 | * project. | |
4 | */ | |
5 | /* ==================================================================== | |
6 | * Copyright (c) 2008 The OpenSSL Project. All rights reserved. | |
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 | * | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | |
14 | * | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in | |
17 | * the documentation and/or other materials provided with the | |
18 | * distribution. | |
19 | * | |
20 | * 3. All advertising materials mentioning features or use of this | |
21 | * software must display the following acknowledgment: | |
22 | * "This product includes software developed by the OpenSSL Project | |
23 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 | * | |
25 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 | * endorse or promote products derived from this software without | |
27 | * prior written permission. For written permission, please contact | |
28 | * licensing@OpenSSL.org. | |
29 | * | |
30 | * 5. Products derived from this software may not be called "OpenSSL" | |
31 | * nor may "OpenSSL" appear in their names without prior written | |
32 | * permission of the OpenSSL Project. | |
33 | * | |
34 | * 6. Redistributions of any form whatsoever must retain the following | |
35 | * acknowledgment: | |
36 | * "This product includes software developed by the OpenSSL Project | |
37 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 | * | |
39 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 | * ==================================================================== | |
52 | */ | |
53 | ||
54 | #include "cryptlib.h" | |
55 | #include <openssl/asn1t.h> | |
56 | #include <openssl/x509.h> | |
57 | #include <openssl/x509v3.h> | |
58 | #include <openssl/err.h> | |
59 | #include <openssl/cms.h> | |
60 | #include "cms_lcl.h" | |
61 | ||
62 | static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) | |
63 | { | |
64 | unsigned char buf[4096]; | |
65 | int r = 0, i; | |
66 | BIO *tmpout = NULL; | |
67 | ||
68 | if(flags & CMS_TEXT) | |
69 | { | |
70 | tmpout = BIO_new(BIO_s_mem()); | |
71 | if(!tmpout) | |
72 | { | |
73 | CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE); | |
74 | goto err; | |
75 | } | |
76 | } | |
77 | else | |
78 | tmpout = out; | |
79 | ||
e540d1cd | 80 | /* Read all content through chain to process digest, decrypt etc */ |
8931b30d DSH |
81 | for (;;) |
82 | { | |
83 | i=BIO_read(in,buf,sizeof(buf)); | |
84 | if (i <= 0) | |
e540d1cd DSH |
85 | { |
86 | if (BIO_method_type(in) == BIO_TYPE_CIPHER) | |
87 | { | |
88 | if (!BIO_get_cipher_status(in)) | |
89 | goto err; | |
90 | } | |
8931b30d | 91 | break; |
e540d1cd DSH |
92 | } |
93 | ||
8931b30d DSH |
94 | if (tmpout) |
95 | BIO_write(tmpout, buf, i); | |
96 | } | |
97 | ||
98 | if(flags & CMS_TEXT) | |
99 | { | |
100 | if(!SMIME_text(tmpout, out)) | |
101 | { | |
102 | CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR); | |
103 | goto err; | |
104 | } | |
105 | } | |
106 | ||
107 | r = 1; | |
108 | ||
109 | err: | |
110 | if (tmpout && (tmpout != out)) | |
111 | BIO_free(tmpout); | |
112 | return r; | |
113 | ||
114 | } | |
115 | ||
4f1aa191 DSH |
116 | static int check_content(CMS_ContentInfo *cms) |
117 | { | |
118 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms); | |
119 | if (!pos || !*pos) | |
120 | { | |
121 | CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT); | |
122 | return 0; | |
123 | } | |
124 | return 1; | |
125 | } | |
126 | ||
8931b30d DSH |
127 | int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags) |
128 | { | |
129 | BIO *cont; | |
130 | int r; | |
131 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) | |
132 | { | |
133 | CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA); | |
134 | return 0; | |
135 | } | |
136 | cont = CMS_dataInit(cms, NULL); | |
137 | if (!cont) | |
138 | return 0; | |
139 | r = cms_copy_content(out, cont, flags); | |
140 | BIO_free_all(cont); | |
141 | return r; | |
142 | } | |
143 | ||
144 | CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags) | |
145 | { | |
146 | CMS_ContentInfo *cms; | |
147 | cms = cms_Data_create(); | |
148 | if (!cms) | |
149 | return NULL; | |
150 | ||
151 | if ((flags & CMS_STREAM) || CMS_final(cms, in, flags)) | |
152 | return cms; | |
153 | ||
154 | CMS_ContentInfo_free(cms); | |
155 | ||
156 | return NULL; | |
157 | } | |
158 | ||
159 | int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, | |
160 | unsigned int flags) | |
161 | { | |
162 | BIO *cont; | |
163 | int r; | |
164 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) | |
165 | { | |
166 | CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA); | |
167 | return 0; | |
168 | } | |
169 | ||
4f1aa191 DSH |
170 | if (!dcont && !check_content(cms)) |
171 | return 0; | |
8931b30d DSH |
172 | |
173 | cont = CMS_dataInit(cms, dcont); | |
174 | if (!cont) | |
175 | return 0; | |
176 | r = cms_copy_content(out, cont, flags); | |
177 | if (r) | |
178 | r = cms_DigestedData_do_final(cms, cont, 1); | |
179 | BIO_free_all(cont); | |
180 | return r; | |
181 | } | |
182 | ||
183 | CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, | |
184 | unsigned int flags) | |
185 | { | |
186 | CMS_ContentInfo *cms; | |
187 | if (!md) | |
188 | md = EVP_sha1(); | |
189 | cms = cms_DigestedData_create(md); | |
190 | if (!cms) | |
191 | return NULL; | |
192 | ||
193 | if(!(flags & CMS_DETACHED)) | |
194 | CMS_set_detached(cms, 0); | |
195 | ||
196 | if ((flags & CMS_STREAM) || CMS_final(cms, in, flags)) | |
197 | return cms; | |
198 | ||
199 | CMS_ContentInfo_free(cms); | |
200 | return NULL; | |
201 | } | |
202 | ||
b820455c DSH |
203 | int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, |
204 | const unsigned char *key, size_t keylen, | |
205 | BIO *dcont, BIO *out, unsigned int flags) | |
206 | { | |
207 | BIO *cont; | |
208 | int r; | |
209 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) | |
210 | { | |
211 | CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT, | |
212 | CMS_R_TYPE_NOT_ENCRYPTED_DATA); | |
213 | return 0; | |
214 | } | |
215 | ||
4f1aa191 DSH |
216 | if (!dcont && !check_content(cms)) |
217 | return 0; | |
b820455c | 218 | |
320bfc1b DSH |
219 | if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0) |
220 | return 0; | |
b820455c DSH |
221 | cont = CMS_dataInit(cms, dcont); |
222 | if (!cont) | |
223 | return 0; | |
320bfc1b | 224 | r = cms_copy_content(out, cont, flags); |
b820455c DSH |
225 | BIO_free_all(cont); |
226 | return r; | |
227 | } | |
228 | ||
320bfc1b DSH |
229 | CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, |
230 | const unsigned char *key, size_t keylen, | |
231 | unsigned int flags) | |
232 | { | |
233 | CMS_ContentInfo *cms; | |
fd47c361 DSH |
234 | if (!cipher) |
235 | { | |
236 | CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER); | |
237 | return NULL; | |
238 | } | |
320bfc1b DSH |
239 | cms = CMS_ContentInfo_new(); |
240 | if (!cms) | |
241 | return NULL; | |
242 | if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen)) | |
243 | return NULL; | |
244 | ||
245 | if(!(flags & CMS_DETACHED)) | |
246 | CMS_set_detached(cms, 0); | |
247 | ||
248 | if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, in, flags)) | |
249 | return cms; | |
250 | ||
251 | CMS_ContentInfo_free(cms); | |
252 | return NULL; | |
253 | } | |
254 | ||
8931b30d DSH |
255 | static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, |
256 | X509_STORE *store, | |
257 | STACK_OF(X509) *certs, | |
258 | STACK_OF(X509_CRL) *crls, | |
259 | unsigned int flags) | |
260 | { | |
261 | X509_STORE_CTX ctx; | |
262 | X509 *signer; | |
263 | int i, j, r = 0; | |
264 | CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); | |
265 | if (!X509_STORE_CTX_init(&ctx, store, signer, certs)) | |
266 | { | |
267 | CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, | |
268 | CMS_R_STORE_INIT_ERROR); | |
269 | goto err; | |
270 | } | |
271 | X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_SMIME_SIGN); | |
272 | if (crls) | |
273 | X509_STORE_CTX_set0_crls(&ctx, crls); | |
274 | ||
275 | i = X509_verify_cert(&ctx); | |
276 | if (i <= 0) | |
277 | { | |
278 | j = X509_STORE_CTX_get_error(&ctx); | |
279 | CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, | |
280 | CMS_R_CERTIFICATE_VERIFY_ERROR); | |
281 | ERR_add_error_data(2, "Verify error:", | |
282 | X509_verify_cert_error_string(j)); | |
283 | goto err; | |
284 | } | |
285 | r = 1; | |
286 | err: | |
287 | X509_STORE_CTX_cleanup(&ctx); | |
288 | return r; | |
289 | ||
290 | } | |
291 | ||
292 | int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, | |
293 | X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags) | |
294 | { | |
295 | CMS_SignerInfo *si; | |
296 | STACK_OF(CMS_SignerInfo) *sinfos; | |
297 | STACK_OF(X509) *cms_certs = NULL; | |
298 | STACK_OF(X509_CRL) *crls = NULL; | |
299 | X509 *signer; | |
300 | int i, scount = 0, ret = 0; | |
301 | BIO *cmsbio = NULL, *tmpin = NULL; | |
302 | ||
4f1aa191 DSH |
303 | if (!dcont && !check_content(cms)) |
304 | return 0; | |
8931b30d DSH |
305 | |
306 | /* Attempt to find all signer certificates */ | |
307 | ||
308 | sinfos = CMS_get0_SignerInfos(cms); | |
309 | ||
310 | if (sk_CMS_SignerInfo_num(sinfos) <= 0) | |
311 | { | |
312 | CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS); | |
313 | goto err; | |
314 | } | |
315 | ||
316 | for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) | |
317 | { | |
318 | si = sk_CMS_SignerInfo_value(sinfos, i); | |
319 | CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); | |
320 | if (signer) | |
321 | scount++; | |
322 | } | |
323 | ||
324 | if (scount != sk_CMS_SignerInfo_num(sinfos)) | |
325 | scount += CMS_set1_signers_certs(cms, certs, flags); | |
326 | ||
327 | if (scount != sk_CMS_SignerInfo_num(sinfos)) | |
328 | { | |
329 | CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND); | |
330 | goto err; | |
331 | } | |
332 | ||
333 | /* Attempt to verify all signers certs */ | |
334 | ||
335 | if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) | |
336 | { | |
337 | cms_certs = CMS_get1_certs(cms); | |
338 | crls = CMS_get1_crls(cms); | |
339 | for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) | |
340 | { | |
341 | si = sk_CMS_SignerInfo_value(sinfos, i); | |
342 | if (!cms_signerinfo_verify_cert(si, store, | |
343 | cms_certs, crls, flags)) | |
344 | goto err; | |
345 | } | |
346 | } | |
347 | ||
348 | /* Attempt to verify all SignerInfo signed attribute signatures */ | |
349 | ||
350 | if (!(flags & CMS_NO_ATTR_VERIFY)) | |
351 | { | |
352 | for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) | |
353 | { | |
354 | si = sk_CMS_SignerInfo_value(sinfos, i); | |
355 | if (CMS_signed_get_attr_count(si) < 0) | |
356 | continue; | |
357 | if (CMS_SignerInfo_verify(si) <= 0) | |
358 | goto err; | |
359 | } | |
360 | } | |
361 | ||
362 | /* Performance optimization: if the content is a memory BIO then | |
363 | * store its contents in a temporary read only memory BIO. This | |
364 | * avoids potentially large numbers of slow copies of data which will | |
365 | * occur when reading from a read write memory BIO when signatures | |
366 | * are calculated. | |
367 | */ | |
368 | ||
369 | if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) | |
370 | { | |
371 | char *ptr; | |
372 | long len; | |
373 | len = BIO_get_mem_data(dcont, &ptr); | |
374 | tmpin = BIO_new_mem_buf(ptr, len); | |
375 | if (tmpin == NULL) | |
376 | { | |
377 | CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE); | |
378 | return 0; | |
379 | } | |
380 | } | |
381 | else | |
382 | tmpin = dcont; | |
383 | ||
384 | ||
385 | cmsbio=CMS_dataInit(cms, tmpin); | |
386 | if (!cmsbio) | |
387 | goto err; | |
388 | ||
389 | if (!cms_copy_content(out, cmsbio, flags)) | |
390 | goto err; | |
391 | ||
392 | if (!(flags & CMS_NO_CONTENT_VERIFY)) | |
393 | { | |
394 | for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) | |
395 | { | |
396 | si = sk_CMS_SignerInfo_value(sinfos, i); | |
397 | if (!CMS_SignerInfo_verify_content(si, cmsbio)) | |
398 | { | |
399 | CMSerr(CMS_F_CMS_VERIFY, | |
400 | CMS_R_CONTENT_VERIFY_ERROR); | |
401 | goto err; | |
402 | } | |
403 | } | |
404 | } | |
405 | ||
406 | ret = 1; | |
407 | ||
408 | err: | |
409 | ||
410 | if (dcont && (tmpin == dcont)) | |
411 | BIO_pop(cmsbio); | |
412 | BIO_free_all(cmsbio); | |
413 | ||
414 | if (cms_certs) | |
415 | sk_X509_pop_free(cms_certs, X509_free); | |
416 | if (crls) | |
417 | sk_X509_CRL_pop_free(crls, X509_CRL_free); | |
418 | ||
419 | return ret; | |
420 | } | |
421 | ||
422 | CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, | |
423 | BIO *data, unsigned int flags) | |
424 | { | |
425 | CMS_ContentInfo *cms; | |
426 | int i; | |
427 | cms = CMS_ContentInfo_new(); | |
428 | if (!cms) | |
429 | goto merr; | |
430 | if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) | |
431 | { | |
432 | CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR); | |
433 | goto err; | |
434 | } | |
435 | for (i = 0; i < sk_X509_num(certs); i++) | |
436 | { | |
437 | X509 *x = sk_X509_value(certs, i); | |
438 | if (!CMS_add1_cert(cms, x)) | |
439 | goto merr; | |
440 | } | |
441 | /* If no signer or certs initialize signedData */ | |
442 | if (!pkey && !i && !CMS_SignedData_init(cms)) | |
443 | goto merr; | |
444 | ||
445 | if(!(flags & CMS_DETACHED)) | |
446 | CMS_set_detached(cms, 0); | |
447 | ||
448 | if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, data, flags)) | |
449 | return cms; | |
e4f0e40e DSH |
450 | else |
451 | goto err; | |
8931b30d DSH |
452 | |
453 | merr: | |
454 | CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE); | |
455 | ||
456 | err: | |
457 | if (cms) | |
458 | CMS_ContentInfo_free(cms); | |
459 | return NULL; | |
460 | } | |
461 | ||
761ffa72 | 462 | CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data, |
8931b30d DSH |
463 | const EVP_CIPHER *cipher, unsigned int flags) |
464 | { | |
761ffa72 DSH |
465 | CMS_ContentInfo *cms; |
466 | int i; | |
467 | X509 *recip; | |
468 | cms = CMS_EnvelopedData_create(cipher); | |
469 | if (!cms) | |
470 | goto merr; | |
471 | for (i = 0; i < sk_X509_num(certs); i++) | |
472 | { | |
473 | recip = sk_X509_value(certs, i); | |
474 | if (!CMS_add1_recipient_cert(cms, recip, flags)) | |
475 | { | |
476 | CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR); | |
477 | goto err; | |
478 | } | |
479 | } | |
480 | ||
481 | if(!(flags & CMS_DETACHED)) | |
482 | CMS_set_detached(cms, 0); | |
483 | ||
484 | if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, data, flags)) | |
485 | return cms; | |
e4f0e40e DSH |
486 | else |
487 | goto err; | |
761ffa72 DSH |
488 | |
489 | merr: | |
490 | CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE); | |
491 | err: | |
492 | if (cms) | |
493 | CMS_ContentInfo_free(cms); | |
8931b30d DSH |
494 | return NULL; |
495 | } | |
eeb9cdfc DSH |
496 | |
497 | int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) | |
498 | { | |
499 | STACK_OF(CMS_RecipientInfo) *ris; | |
500 | CMS_RecipientInfo *ri; | |
501 | int i, r; | |
502 | ris = CMS_get0_RecipientInfos(cms); | |
503 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) | |
504 | { | |
505 | ri = sk_CMS_RecipientInfo_value(ris, i); | |
506 | if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS) | |
507 | continue; | |
508 | /* If we have a cert try matching RecipientInfo | |
509 | * otherwise try them all. | |
510 | */ | |
511 | if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0)) | |
512 | { | |
513 | CMS_RecipientInfo_set0_pkey(ri, pk); | |
514 | r = CMS_RecipientInfo_decrypt(cms, ri); | |
515 | CMS_RecipientInfo_set0_pkey(ri, NULL); | |
516 | if (r > 0) | |
517 | return 1; | |
518 | if (cert) | |
519 | { | |
520 | CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, | |
521 | CMS_R_DECRYPT_ERROR); | |
522 | return 0; | |
523 | } | |
524 | ERR_clear_error(); | |
525 | } | |
526 | } | |
527 | ||
528 | CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT); | |
529 | return 0; | |
530 | ||
531 | } | |
532 | ||
533 | int CMS_decrypt_set1_key(CMS_ContentInfo *cms, | |
534 | unsigned char *key, size_t keylen, | |
535 | unsigned char *id, size_t idlen) | |
536 | { | |
537 | STACK_OF(CMS_RecipientInfo) *ris; | |
538 | CMS_RecipientInfo *ri; | |
539 | int i, r; | |
540 | ris = CMS_get0_RecipientInfos(cms); | |
541 | for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) | |
542 | { | |
543 | ri = sk_CMS_RecipientInfo_value(ris, i); | |
544 | if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK) | |
545 | continue; | |
546 | ||
547 | /* If we have an id try matching RecipientInfo | |
548 | * otherwise try them all. | |
549 | */ | |
550 | if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) | |
551 | { | |
552 | CMS_RecipientInfo_set0_key(ri, key, keylen); | |
553 | r = CMS_RecipientInfo_decrypt(cms, ri); | |
554 | CMS_RecipientInfo_set0_key(ri, NULL, 0); | |
555 | if (r > 0) | |
556 | return 1; | |
557 | if (id) | |
558 | { | |
559 | CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, | |
560 | CMS_R_DECRYPT_ERROR); | |
561 | return 0; | |
562 | } | |
563 | ERR_clear_error(); | |
564 | } | |
565 | } | |
566 | ||
567 | CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT); | |
568 | return 0; | |
569 | ||
570 | } | |
8931b30d | 571 | |
4f1aa191 DSH |
572 | int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, |
573 | BIO *dcont, BIO *out, | |
8931b30d DSH |
574 | unsigned int flags) |
575 | { | |
eeb9cdfc | 576 | int r; |
4f1aa191 DSH |
577 | BIO *cont; |
578 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) | |
579 | { | |
580 | CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA); | |
581 | return 0; | |
582 | } | |
583 | if (!dcont && !check_content(cms)) | |
584 | return 0; | |
eeb9cdfc DSH |
585 | if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) |
586 | return 0; | |
4f1aa191 | 587 | |
4f1aa191 DSH |
588 | cont = CMS_dataInit(cms, dcont); |
589 | if (!cont) | |
590 | return 0; | |
591 | r = cms_copy_content(out, cont, flags); | |
592 | BIO_free_all(cont); | |
593 | return r; | |
8931b30d DSH |
594 | } |
595 | ||
596 | int CMS_final(CMS_ContentInfo *cms, BIO *data, int flags) | |
597 | { | |
598 | BIO *cmsbio; | |
599 | int ret = 0; | |
600 | if (!(cmsbio = CMS_dataInit(cms, NULL))) | |
601 | { | |
602 | CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE); | |
603 | return 0; | |
604 | } | |
605 | ||
606 | SMIME_crlf_copy(data, cmsbio, flags); | |
607 | ||
608 | (void)BIO_flush(cmsbio); | |
609 | ||
610 | ||
611 | if (!CMS_dataFinal(cms, cmsbio)) | |
612 | { | |
613 | CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR); | |
614 | goto err; | |
615 | } | |
616 | ||
617 | ret = 1; | |
618 | ||
619 | err: | |
620 | BIO_free_all(cmsbio); | |
621 | ||
622 | return ret; | |
623 | ||
624 | } | |
625 | ||
626 | #ifdef ZLIB | |
627 | ||
628 | int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, | |
629 | unsigned int flags) | |
630 | { | |
631 | BIO *cont; | |
632 | int r; | |
633 | if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) | |
634 | { | |
635 | CMSerr(CMS_F_CMS_UNCOMPRESS, | |
636 | CMS_R_TYPE_NOT_COMPRESSED_DATA); | |
637 | return 0; | |
638 | } | |
639 | ||
4f1aa191 DSH |
640 | if (!dcont && !check_content(cms)) |
641 | return 0; | |
8931b30d DSH |
642 | |
643 | cont = CMS_dataInit(cms, dcont); | |
644 | if (!cont) | |
645 | return 0; | |
646 | r = cms_copy_content(out, cont, flags); | |
647 | BIO_free_all(cont); | |
648 | return r; | |
649 | } | |
650 | ||
651 | CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) | |
652 | { | |
653 | CMS_ContentInfo *cms; | |
654 | if (comp_nid <= 0) | |
655 | comp_nid = NID_zlib_compression; | |
656 | cms = cms_CompressedData_create(comp_nid); | |
657 | if (!cms) | |
658 | return NULL; | |
659 | ||
660 | if(!(flags & CMS_DETACHED)) | |
661 | CMS_set_detached(cms, 0); | |
662 | ||
663 | if ((flags & CMS_STREAM) || CMS_final(cms, in, flags)) | |
664 | return cms; | |
665 | ||
666 | CMS_ContentInfo_free(cms); | |
667 | return NULL; | |
668 | } | |
669 | ||
670 | #else | |
671 | ||
672 | int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, | |
673 | unsigned int flags) | |
674 | { | |
675 | CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); | |
676 | return 0; | |
677 | } | |
678 | ||
679 | CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags) | |
680 | { | |
681 | CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); | |
682 | return NULL; | |
683 | } | |
684 | ||
685 | #endif |