xref: /openbsd-src/lib/libcrypto/cms/cms_smime.c (revision 1ad61ae0a79a724d2d3ec69e69c8e1d1ff6b53a0)
1 /* $OpenBSD: cms_smime.c,v 1.27 2023/07/08 08:26:26 beck Exp $ */
2 /*
3  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4  * project.
5  */
6 /* ====================================================================
7  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  */
54 
55 #include "cryptlib.h"
56 #include <openssl/asn1t.h>
57 #include <openssl/x509.h>
58 #include <openssl/x509v3.h>
59 #include <openssl/err.h>
60 #include <openssl/cms.h>
61 #include "cms_local.h"
62 #include "asn1/asn1_local.h"
63 
64 static BIO *
65 cms_get_text_bio(BIO *out, unsigned int flags)
66 {
67 	BIO *rbio;
68 
69 	if (out == NULL)
70 		rbio = BIO_new(BIO_s_null());
71 	else if (flags & CMS_TEXT) {
72 		rbio = BIO_new(BIO_s_mem());
73 		BIO_set_mem_eof_return(rbio, 0);
74 	} else
75 		rbio = out;
76 
77 	return rbio;
78 }
79 
80 static int
81 cms_copy_content(BIO *out, BIO *in, unsigned int flags)
82 {
83 	unsigned char buf[4096];
84 	int r = 0, i;
85 	BIO *tmpout;
86 
87 	tmpout = cms_get_text_bio(out, flags);
88 
89 	if (tmpout == NULL) {
90 		CMSerror(ERR_R_MALLOC_FAILURE);
91 		goto err;
92 	}
93 
94 	/* Read all content through chain to process digest, decrypt etc */
95 	for (;;) {
96 		i = BIO_read(in, buf, sizeof(buf));
97 		if (i <= 0) {
98 			if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
99 				if (!BIO_get_cipher_status(in))
100 					goto err;
101 			}
102 			if (i < 0)
103 				goto err;
104 			break;
105 		}
106 
107 		if (tmpout && (BIO_write(tmpout, buf, i) != i))
108 			goto err;
109 	}
110 
111 	if (flags & CMS_TEXT) {
112 		if (!SMIME_text(tmpout, out)) {
113 			CMSerror(CMS_R_SMIME_TEXT_ERROR);
114 			goto err;
115 		}
116 	}
117 
118 	r = 1;
119 
120  err:
121 	if (tmpout != out)
122 		BIO_free(tmpout);
123 
124 	return r;
125 }
126 
127 static int
128 check_content(CMS_ContentInfo *cms)
129 {
130 	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
131 
132 	if (!pos || !*pos) {
133 		CMSerror(CMS_R_NO_CONTENT);
134 		return 0;
135 	}
136 
137 	return 1;
138 }
139 
140 static void
141 do_free_upto(BIO *f, BIO *upto)
142 {
143 	if (upto) {
144 		BIO *tbio;
145 		do {
146 			tbio = BIO_pop(f);
147 			BIO_free(f);
148 			f = tbio;
149 		}
150 		while (f && f != upto);
151 	} else
152 		BIO_free_all(f);
153 }
154 
155 int
156 CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
157 {
158 	BIO *cont;
159 	int r;
160 
161 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
162 		CMSerror(CMS_R_TYPE_NOT_DATA);
163 		return 0;
164 	}
165 	cont = CMS_dataInit(cms, NULL);
166 	if (!cont)
167 		return 0;
168 	r = cms_copy_content(out, cont, flags);
169 	BIO_free_all(cont);
170 
171 	return r;
172 }
173 LCRYPTO_ALIAS(CMS_data);
174 
175 CMS_ContentInfo *
176 CMS_data_create(BIO *in, unsigned int flags)
177 {
178 	CMS_ContentInfo *cms;
179 
180 	cms = cms_Data_create();
181 	if (!cms)
182 		return NULL;
183 
184 	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
185 		return cms;
186 
187 	CMS_ContentInfo_free(cms);
188 
189 	return NULL;
190 }
191 LCRYPTO_ALIAS(CMS_data_create);
192 
193 int
194 CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, unsigned int flags)
195 {
196 	BIO *cont;
197 	int r;
198 
199 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
200 		CMSerror(CMS_R_TYPE_NOT_DIGESTED_DATA);
201 		return 0;
202 	}
203 
204 	if (!dcont && !check_content(cms))
205 		return 0;
206 
207 	cont = CMS_dataInit(cms, dcont);
208 	if (!cont)
209 		return 0;
210 	r = cms_copy_content(out, cont, flags);
211 	if (r)
212 		r = cms_DigestedData_do_final(cms, cont, 1);
213 	do_free_upto(cont, dcont);
214 
215 	return r;
216 }
217 LCRYPTO_ALIAS(CMS_digest_verify);
218 
219 CMS_ContentInfo *
220 CMS_digest_create(BIO *in, const EVP_MD *md, unsigned int flags)
221 {
222 	CMS_ContentInfo *cms;
223 
224 	if (!md)
225 		md = EVP_sha1();
226 	cms = cms_DigestedData_create(md);
227 	if (!cms)
228 		return NULL;
229 
230 	if (!(flags & CMS_DETACHED))
231 		CMS_set_detached(cms, 0);
232 
233 	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
234 		return cms;
235 
236 	CMS_ContentInfo_free(cms);
237 
238 	return NULL;
239 }
240 LCRYPTO_ALIAS(CMS_digest_create);
241 
242 int
243 CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, const unsigned char *key,
244     size_t keylen, BIO *dcont, BIO *out, unsigned int flags)
245 {
246 	BIO *cont;
247 	int r;
248 
249 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
250 		CMSerror(CMS_R_TYPE_NOT_ENCRYPTED_DATA);
251 		return 0;
252 	}
253 
254 	if (!dcont && !check_content(cms))
255 		return 0;
256 
257 	if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
258 		return 0;
259 	cont = CMS_dataInit(cms, dcont);
260 	if (!cont)
261 		return 0;
262 	r = cms_copy_content(out, cont, flags);
263 	do_free_upto(cont, dcont);
264 
265 	return r;
266 }
267 LCRYPTO_ALIAS(CMS_EncryptedData_decrypt);
268 
269 CMS_ContentInfo *
270 CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
271     const unsigned char *key, size_t keylen, unsigned int flags)
272 {
273 	CMS_ContentInfo *cms;
274 
275 	if (!cipher) {
276 		CMSerror(CMS_R_NO_CIPHER);
277 		return NULL;
278 	}
279 	cms = CMS_ContentInfo_new();
280 	if (cms == NULL)
281 		return NULL;
282 	if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
283 		return NULL;
284 
285 	if (!(flags & CMS_DETACHED))
286 		CMS_set_detached(cms, 0);
287 
288 	if ((flags & (CMS_STREAM | CMS_PARTIAL)) ||
289 	    CMS_final(cms, in, NULL, flags))
290 		return cms;
291 
292 	CMS_ContentInfo_free(cms);
293 
294 	return NULL;
295 }
296 LCRYPTO_ALIAS(CMS_EncryptedData_encrypt);
297 
298 static int
299 cms_signerinfo_verify_cert(CMS_SignerInfo *si, X509_STORE *store,
300     STACK_OF(X509) *certs, STACK_OF(X509_CRL) *crls)
301 {
302 	X509_STORE_CTX *ctx = X509_STORE_CTX_new();
303 	X509 *signer;
304 	int i, j, r = 0;
305 
306 	if (ctx == NULL) {
307 		CMSerror(ERR_R_MALLOC_FAILURE);
308 		goto err;
309 	}
310 	CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
311 	if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
312 		CMSerror(CMS_R_STORE_INIT_ERROR);
313 		goto err;
314 	}
315 	X509_STORE_CTX_set_default(ctx, "smime_sign");
316 	if (crls)
317 		X509_STORE_CTX_set0_crls(ctx, crls);
318 
319 	i = X509_verify_cert(ctx);
320 	if (i <= 0) {
321 		j = X509_STORE_CTX_get_error(ctx);
322 		CMSerror(CMS_R_CERTIFICATE_VERIFY_ERROR);
323 		ERR_asprintf_error_data("Verify error: %s",
324 		    X509_verify_cert_error_string(j));
325 		goto err;
326 	}
327 	r = 1;
328 
329  err:
330 	X509_STORE_CTX_free(ctx);
331 
332 	return r;
333 }
334 
335 int
336 CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, X509_STORE *store,
337     BIO *dcont, BIO *out, unsigned int flags)
338 {
339 	CMS_SignerInfo *si;
340 	STACK_OF(CMS_SignerInfo) *sinfos;
341 	STACK_OF(X509) *cms_certs = NULL;
342 	STACK_OF(X509_CRL) *crls = NULL;
343 	X509 *signer;
344 	int i, scount = 0, ret = 0;
345 	BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
346 
347 	if (!dcont && !check_content(cms))
348 		return 0;
349 	if (dcont && !(flags & CMS_BINARY)) {
350 		const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
351 		if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
352 			flags |= CMS_ASCIICRLF;
353 	}
354 
355 	/* Attempt to find all signer certificates */
356 
357 	sinfos = CMS_get0_SignerInfos(cms);
358 	if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
359 		CMSerror(CMS_R_NO_SIGNERS);
360 		goto err;
361 	}
362 
363 	for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
364 		si = sk_CMS_SignerInfo_value(sinfos, i);
365 		CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
366 		if (signer)
367 			scount++;
368 	}
369 
370 	if (scount != sk_CMS_SignerInfo_num(sinfos))
371 		scount += CMS_set1_signers_certs(cms, certs, flags);
372 
373 	if (scount != sk_CMS_SignerInfo_num(sinfos)) {
374 		CMSerror(CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
375 		goto err;
376 	}
377 
378 	/* Attempt to verify all signers certs */
379 
380 	if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
381 		cms_certs = CMS_get1_certs(cms);
382 		if (!(flags & CMS_NOCRL))
383 			crls = CMS_get1_crls(cms);
384 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
385 			si = sk_CMS_SignerInfo_value(sinfos, i);
386 			if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls))
387 				goto err;
388 		}
389 	}
390 
391 	/* Attempt to verify all SignerInfo signed attribute signatures */
392 
393 	if (!(flags & CMS_NO_ATTR_VERIFY)) {
394 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
395 			si = sk_CMS_SignerInfo_value(sinfos, i);
396 			if (CMS_signed_get_attr_count(si) < 0)
397 				continue;
398 			if (CMS_SignerInfo_verify(si) <= 0)
399 				goto err;
400 		}
401 	}
402 
403 	/*
404 	 * Performance optimization: if the content is a memory BIO then store
405 	 * its contents in a temporary read only memory BIO. This avoids
406 	 * potentially large numbers of slow copies of data which will occur when
407 	 * reading from a read write memory BIO when signatures are calculated.
408 	 */
409 
410 	if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
411 		char *ptr;
412 		long len;
413 
414 		len = BIO_get_mem_data(dcont, &ptr);
415 		tmpin = BIO_new_mem_buf(ptr, len);
416 		if (tmpin == NULL) {
417 			CMSerror(ERR_R_MALLOC_FAILURE);
418 			goto err2;
419 		}
420 	} else
421 		tmpin = dcont;
422 
423 	/*
424 	 * If not binary mode and detached generate digests by *writing* through
425 	 * the BIO. That makes it possible to canonicalise the input.
426 	 */
427 	if (!(flags & SMIME_BINARY) && dcont) {
428 		/*
429 		 * Create output BIO so we can either handle text or to ensure
430 		 * included content doesn't override detached content.
431 		 */
432 		tmpout = cms_get_text_bio(out, flags);
433 		if (!tmpout) {
434 			CMSerror(ERR_R_MALLOC_FAILURE);
435 			goto err;
436 		}
437 		cmsbio = CMS_dataInit(cms, tmpout);
438 		if (!cmsbio)
439 			goto err;
440 		/*
441 		 * Don't use SMIME_TEXT for verify: it adds headers and we want to
442 		 * remove them.
443 		 */
444 		SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT);
445 
446 		if (flags & CMS_TEXT) {
447 			if (!SMIME_text(tmpout, out)) {
448 				CMSerror(CMS_R_SMIME_TEXT_ERROR);
449 				goto err;
450 			}
451 		}
452 	} else {
453 		cmsbio = CMS_dataInit(cms, tmpin);
454 		if (!cmsbio)
455 			goto err;
456 
457 		if (!cms_copy_content(out, cmsbio, flags))
458 			goto err;
459 
460 	}
461 	if (!(flags & CMS_NO_CONTENT_VERIFY)) {
462 		for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
463 			si = sk_CMS_SignerInfo_value(sinfos, i);
464 			if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
465 				CMSerror(CMS_R_CONTENT_VERIFY_ERROR);
466 				goto err;
467 			}
468 		}
469 	}
470 
471 	ret = 1;
472 
473  err:
474 	if (!(flags & SMIME_BINARY) && dcont) {
475 		do_free_upto(cmsbio, tmpout);
476 		if (tmpin != dcont)
477 			BIO_free(tmpin);
478 	} else {
479 		if (dcont && (tmpin == dcont))
480 			do_free_upto(cmsbio, dcont);
481 		else
482 			BIO_free_all(cmsbio);
483 	}
484 
485 	if (out != tmpout)
486 		BIO_free_all(tmpout);
487 
488  err2:
489 	sk_X509_pop_free(cms_certs, X509_free);
490 	sk_X509_CRL_pop_free(crls, X509_CRL_free);
491 
492 	return ret;
493 }
494 LCRYPTO_ALIAS(CMS_verify);
495 
496 int
497 CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
498     STACK_OF(X509) *certs, X509_STORE *store, unsigned int flags)
499 {
500 	int r;
501 
502 	flags &= ~(CMS_DETACHED | CMS_TEXT);
503 	r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
504 	if (r <= 0)
505 		return r;
506 
507 	return cms_Receipt_verify(rcms, ocms);
508 }
509 LCRYPTO_ALIAS(CMS_verify_receipt);
510 
511 CMS_ContentInfo *
512 CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data,
513     unsigned int flags)
514 {
515 	CMS_ContentInfo *cms;
516 	int i;
517 
518 	cms = CMS_ContentInfo_new();
519 	if (cms == NULL || !CMS_SignedData_init(cms))
520 		goto merr;
521 	if (flags & CMS_ASCIICRLF &&
522 	    !CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
523 		goto err;
524 
525 	if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
526 		CMSerror(CMS_R_ADD_SIGNER_ERROR);
527 		goto err;
528 	}
529 
530 	for (i = 0; i < sk_X509_num(certs); i++) {
531 		X509 *x = sk_X509_value(certs, i);
532 		if (!CMS_add1_cert(cms, x))
533 			goto merr;
534 	}
535 
536 	if (!(flags & CMS_DETACHED))
537 		CMS_set_detached(cms, 0);
538 
539 	if ((flags & (CMS_STREAM | CMS_PARTIAL)) ||
540 	    CMS_final(cms, data, NULL, flags))
541 		return cms;
542 	else
543 		goto err;
544 
545  merr:
546 	CMSerror(ERR_R_MALLOC_FAILURE);
547 
548  err:
549 	CMS_ContentInfo_free(cms);
550 
551 	return NULL;
552 }
553 LCRYPTO_ALIAS(CMS_sign);
554 
555 CMS_ContentInfo *
556 CMS_sign_receipt(CMS_SignerInfo *si, X509 *signcert, EVP_PKEY *pkey,
557     STACK_OF(X509) *certs, unsigned int flags)
558 {
559 	CMS_SignerInfo *rct_si;
560 	CMS_ContentInfo *cms = NULL;
561 	ASN1_OCTET_STRING **pos, *os;
562 	BIO *rct_cont = NULL;
563 	int r = 0;
564 
565 	flags &= ~(CMS_STREAM | CMS_TEXT);
566 	/* Not really detached but avoids content being allocated */
567 	flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
568 	if (!pkey || !signcert) {
569 		CMSerror(CMS_R_NO_KEY_OR_CERT);
570 		return NULL;
571 	}
572 
573 	/* Initialize signed data */
574 
575 	cms = CMS_sign(NULL, NULL, certs, NULL, flags);
576 	if (!cms)
577 		goto err;
578 
579 	/* Set inner content type to signed receipt */
580 	if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
581 		goto err;
582 
583 	rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
584 	if (!rct_si) {
585 		CMSerror(CMS_R_ADD_SIGNER_ERROR);
586 		goto err;
587 	}
588 
589 	os = cms_encode_Receipt(si);
590 	if (!os)
591 		goto err;
592 
593 	/* Set content to digest */
594 	rct_cont = BIO_new_mem_buf(os->data, os->length);
595 	if (!rct_cont)
596 		goto err;
597 
598 	/* Add msgSigDigest attribute */
599 
600 	if (!cms_msgSigDigest_add1(rct_si, si))
601 		goto err;
602 
603 	/* Finalize structure */
604 	if (!CMS_final(cms, rct_cont, NULL, flags))
605 		goto err;
606 
607 	/* Set embedded content */
608 	pos = CMS_get0_content(cms);
609 	*pos = os;
610 
611 	r = 1;
612 
613  err:
614 	BIO_free(rct_cont);
615 	if (r)
616 		return cms;
617 	CMS_ContentInfo_free(cms);
618 
619 	return NULL;
620 }
621 LCRYPTO_ALIAS(CMS_sign_receipt);
622 
623 CMS_ContentInfo *
624 CMS_encrypt(STACK_OF(X509) *certs, BIO *data, const EVP_CIPHER *cipher,
625     unsigned int flags)
626 {
627 	CMS_ContentInfo *cms;
628 	int i;
629 	X509 *recip;
630 
631 	cms = CMS_EnvelopedData_create(cipher);
632 	if (!cms)
633 		goto merr;
634 	for (i = 0; i < sk_X509_num(certs); i++) {
635 		recip = sk_X509_value(certs, i);
636 		if (!CMS_add1_recipient_cert(cms, recip, flags)) {
637 			CMSerror(CMS_R_RECIPIENT_ERROR);
638 			goto err;
639 		}
640 	}
641 
642 	if (!(flags & CMS_DETACHED))
643 		CMS_set_detached(cms, 0);
644 
645 	if ((flags & (CMS_STREAM | CMS_PARTIAL)) ||
646 	    CMS_final(cms, data, NULL, flags))
647 		return cms;
648 	else
649 		goto err;
650 
651  merr:
652 	CMSerror(ERR_R_MALLOC_FAILURE);
653  err:
654 	CMS_ContentInfo_free(cms);
655 
656 	return NULL;
657 }
658 LCRYPTO_ALIAS(CMS_encrypt);
659 
660 static int
661 cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, EVP_PKEY *pk,
662     X509 *cert)
663 {
664 	int i;
665 	STACK_OF(CMS_RecipientEncryptedKey) *reks;
666 	CMS_RecipientEncryptedKey *rek;
667 
668 	reks = CMS_RecipientInfo_kari_get0_reks(ri);
669 	for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
670 		int rv;
671 
672 		rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
673 		if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
674 			continue;
675 		CMS_RecipientInfo_kari_set0_pkey(ri, pk);
676 		rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
677 		CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
678 		if (rv > 0)
679 			return 1;
680 		return cert == NULL ? 0 : -1;
681 	}
682 
683 	return 0;
684 }
685 
686 int
687 CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
688 {
689 	STACK_OF(CMS_RecipientInfo) *ris;
690 	CMS_RecipientInfo *ri;
691 	int i, r, ri_type;
692 	int debug = 0, match_ri = 0;
693 
694 	ris = CMS_get0_RecipientInfos(cms);
695 	if (ris)
696 		debug = cms->d.envelopedData->encryptedContentInfo->debug;
697 	ri_type = cms_pkey_get_ri_type(pk);
698 	if (ri_type == CMS_RECIPINFO_NONE) {
699 		CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
700 		return 0;
701 	}
702 
703 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
704 		ri = sk_CMS_RecipientInfo_value(ris, i);
705 		if (CMS_RecipientInfo_type(ri) != ri_type)
706 			continue;
707 		match_ri = 1;
708 		if (ri_type == CMS_RECIPINFO_AGREE) {
709 			r = cms_kari_set1_pkey(cms, ri, pk, cert);
710 			if (r > 0)
711 				return 1;
712 			if (r < 0)
713 				return 0;
714 		}
715 		/*
716 		 * If we have a cert try matching RecipientInfo otherwise try them
717 		 * all.
718 		 */
719 		else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
720 			EVP_PKEY_up_ref(pk);
721 			CMS_RecipientInfo_set0_pkey(ri, pk);
722 			r = CMS_RecipientInfo_decrypt(cms, ri);
723 			CMS_RecipientInfo_set0_pkey(ri, NULL);
724 			if (cert) {
725 				/*
726 				 * If not debugging clear any error and return success to
727 				 * avoid leaking of information useful to MMA
728 				 */
729 				if (!debug) {
730 					ERR_clear_error();
731 					return 1;
732 				}
733 				if (r > 0)
734 					return 1;
735 				CMSerror(CMS_R_DECRYPT_ERROR);
736 				return 0;
737 			}
738 			/*
739 			 * If no cert and not debugging don't leave loop after first
740 			 * successful decrypt. Always attempt to decrypt all recipients
741 			 * to avoid leaking timing of a successful decrypt.
742 			 */
743 			else if (r > 0 && debug)
744 				return 1;
745 		}
746 	}
747 	/* If no cert, key transport and not debugging always return success */
748 	if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) {
749 		ERR_clear_error();
750 		return 1;
751 	}
752 
753 	CMSerror(CMS_R_NO_MATCHING_RECIPIENT);
754 
755 	return 0;
756 }
757 LCRYPTO_ALIAS(CMS_decrypt_set1_pkey);
758 
759 int
760 CMS_decrypt_set1_key(CMS_ContentInfo *cms, unsigned char *key, size_t keylen,
761     const unsigned char *id, size_t idlen)
762 {
763 	STACK_OF(CMS_RecipientInfo) *ris;
764 	CMS_RecipientInfo *ri;
765 	int i, r;
766 
767 	ris = CMS_get0_RecipientInfos(cms);
768 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
769 		ri = sk_CMS_RecipientInfo_value(ris, i);
770 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
771 			continue;
772 
773 		/*
774 		 * If we have an id try matching RecipientInfo otherwise try them
775 		 * all.
776 		 */
777 		if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
778 			CMS_RecipientInfo_set0_key(ri, key, keylen);
779 			r = CMS_RecipientInfo_decrypt(cms, ri);
780 			CMS_RecipientInfo_set0_key(ri, NULL, 0);
781 			if (r > 0)
782 				return 1;
783 			if (id) {
784 				CMSerror(CMS_R_DECRYPT_ERROR);
785 				return 0;
786 			}
787 			ERR_clear_error();
788 		}
789 	}
790 
791 	CMSerror(CMS_R_NO_MATCHING_RECIPIENT);
792 
793 	return 0;
794 }
795 LCRYPTO_ALIAS(CMS_decrypt_set1_key);
796 
797 int
798 CMS_decrypt_set1_password(CMS_ContentInfo *cms, unsigned char *pass,
799     ssize_t passlen)
800 {
801 	STACK_OF(CMS_RecipientInfo) *ris;
802 	CMS_RecipientInfo *ri;
803 	int i, r;
804 
805 	ris = CMS_get0_RecipientInfos(cms);
806 	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
807 		ri = sk_CMS_RecipientInfo_value(ris, i);
808 		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
809 			continue;
810 		CMS_RecipientInfo_set0_password(ri, pass, passlen);
811 		r = CMS_RecipientInfo_decrypt(cms, ri);
812 		CMS_RecipientInfo_set0_password(ri, NULL, 0);
813 		if (r > 0)
814 			return 1;
815 	}
816 
817 	CMSerror(CMS_R_NO_MATCHING_RECIPIENT);
818 
819 	return 0;
820 }
821 LCRYPTO_ALIAS(CMS_decrypt_set1_password);
822 
823 int
824 CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, BIO *dcont,
825     BIO *out, unsigned int flags)
826 {
827 	int r;
828 	BIO *cont;
829 
830 	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) {
831 		CMSerror(CMS_R_TYPE_NOT_ENVELOPED_DATA);
832 		return 0;
833 	}
834 	if (!dcont && !check_content(cms))
835 		return 0;
836 	if (flags & CMS_DEBUG_DECRYPT)
837 		cms->d.envelopedData->encryptedContentInfo->debug = 1;
838 	else
839 		cms->d.envelopedData->encryptedContentInfo->debug = 0;
840 	if (!cert)
841 		cms->d.envelopedData->encryptedContentInfo->havenocert = 1;
842 	else
843 		cms->d.envelopedData->encryptedContentInfo->havenocert = 0;
844 	if (!pk && !cert && !dcont && !out)
845 		return 1;
846 	if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
847 		return 0;
848 	cont = CMS_dataInit(cms, dcont);
849 	if (!cont)
850 		return 0;
851 	r = cms_copy_content(out, cont, flags);
852 	do_free_upto(cont, dcont);
853 
854 	return r;
855 }
856 LCRYPTO_ALIAS(CMS_decrypt);
857 
858 int
859 CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
860 {
861 	BIO *cmsbio;
862 	int ret = 0;
863 
864 	if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
865 		CMSerror(CMS_R_CMS_LIB);
866 		return 0;
867 	}
868 
869 	SMIME_crlf_copy(data, cmsbio, flags);
870 
871 	(void)BIO_flush(cmsbio);
872 
873 	if (!CMS_dataFinal(cms, cmsbio)) {
874 		CMSerror(CMS_R_CMS_DATAFINAL_ERROR);
875 		goto err;
876 	}
877 
878 	ret = 1;
879 
880  err:
881 	do_free_upto(cmsbio, dcont);
882 
883 	return ret;
884 }
885 LCRYPTO_ALIAS(CMS_final);
886 
887 int
888 CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, unsigned int flags)
889 {
890 	CMSerror(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
891 	return 0;
892 }
893 LCRYPTO_ALIAS(CMS_uncompress);
894 
895 CMS_ContentInfo *
896 CMS_compress(BIO *in, int comp_nid, unsigned int flags)
897 {
898 	CMSerror(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
899 	return NULL;
900 }
901 LCRYPTO_ALIAS(CMS_compress);
902