xref: /openbsd-src/lib/libcrypto/cms/cms_lib.c (revision 1ad61ae0a79a724d2d3ec69e69c8e1d1ff6b53a0)
1 /* $OpenBSD: cms_lib.c,v 1.24 2023/08/24 04:56:36 tb 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 <openssl/asn1t.h>
56 #include <openssl/x509v3.h>
57 #include <openssl/err.h>
58 #include <openssl/pem.h>
59 #include <openssl/bio.h>
60 #include <openssl/asn1.h>
61 #include <openssl/cms.h>
62 
63 #include "cms_local.h"
64 #include "x509_local.h"
65 
66 CMS_ContentInfo *
67 d2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len)
68 {
69 	return (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
70 	    &CMS_ContentInfo_it);
71 }
72 LCRYPTO_ALIAS(d2i_CMS_ContentInfo);
73 
74 int
75 i2d_CMS_ContentInfo(CMS_ContentInfo *a, unsigned char **out)
76 {
77 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ContentInfo_it);
78 }
79 LCRYPTO_ALIAS(i2d_CMS_ContentInfo);
80 
81 CMS_ContentInfo *
82 CMS_ContentInfo_new(void)
83 {
84 	return (CMS_ContentInfo *)ASN1_item_new(&CMS_ContentInfo_it);
85 }
86 LCRYPTO_ALIAS(CMS_ContentInfo_new);
87 
88 void
89 CMS_ContentInfo_free(CMS_ContentInfo *a)
90 {
91 	ASN1_item_free((ASN1_VALUE *)a, &CMS_ContentInfo_it);
92 }
93 LCRYPTO_ALIAS(CMS_ContentInfo_free);
94 
95 int
96 CMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const ASN1_PCTX *pctx)
97 {
98 	return ASN1_item_print(out, (ASN1_VALUE *)x, indent,
99 	    &CMS_ContentInfo_it, pctx);
100 }
101 LCRYPTO_ALIAS(CMS_ContentInfo_print_ctx);
102 
103 const ASN1_OBJECT *
104 CMS_get0_type(const CMS_ContentInfo *cms)
105 {
106 	return cms->contentType;
107 }
108 LCRYPTO_ALIAS(CMS_get0_type);
109 
110 CMS_ContentInfo *
111 cms_Data_create(void)
112 {
113 	CMS_ContentInfo *cms;
114 
115 	cms = CMS_ContentInfo_new();
116 	if (cms != NULL) {
117 		cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
118 		/* Never detached */
119 		CMS_set_detached(cms, 0);
120 	}
121 	return cms;
122 }
123 
124 static BIO *
125 cms_content_bio(CMS_ContentInfo *cms)
126 {
127 	ASN1_OCTET_STRING **pos;
128 
129 	if ((pos = CMS_get0_content(cms)) == NULL)
130 		return NULL;
131 
132 	/* If content is detached, data goes nowhere: create null BIO. */
133 	if (*pos == NULL)
134 		return BIO_new(BIO_s_null());
135 
136 	/* If content is not detached and was created, return memory BIO. */
137 	if ((*pos)->flags == ASN1_STRING_FLAG_CONT)
138 		return BIO_new(BIO_s_mem());
139 
140 	/* Else content was read in: return read-only BIO for it. */
141 	return BIO_new_mem_buf((*pos)->data, (*pos)->length);
142 }
143 
144 BIO *
145 CMS_dataInit(CMS_ContentInfo *cms, BIO *in_content_bio)
146 {
147 	BIO *cms_bio = NULL, *content_bio = NULL;
148 
149 	if ((content_bio = in_content_bio) == NULL)
150 		content_bio = cms_content_bio(cms);
151 	if (content_bio == NULL) {
152 		CMSerror(CMS_R_NO_CONTENT);
153 		goto err;
154 	}
155 
156 	switch (OBJ_obj2nid(cms->contentType)) {
157 	case NID_pkcs7_data:
158 		return content_bio;
159 	case NID_pkcs7_signed:
160 		if ((cms_bio = cms_SignedData_init_bio(cms)) == NULL)
161 			goto err;
162 		break;
163 	case NID_pkcs7_digest:
164 		if ((cms_bio = cms_DigestedData_init_bio(cms)) == NULL)
165 			goto err;
166 		break;
167 	case NID_pkcs7_encrypted:
168 		if ((cms_bio = cms_EncryptedData_init_bio(cms)) == NULL)
169 			goto err;
170 		break;
171 	case NID_pkcs7_enveloped:
172 		if ((cms_bio = cms_EnvelopedData_init_bio(cms)) == NULL)
173 			goto err;
174 		break;
175 	default:
176 		CMSerror(CMS_R_UNSUPPORTED_TYPE);
177 		goto err;
178 	}
179 
180 	return BIO_push(cms_bio, content_bio);
181 
182  err:
183 	if (content_bio != in_content_bio)
184 		BIO_free(content_bio);
185 
186 	return NULL;
187 }
188 LCRYPTO_ALIAS(CMS_dataInit);
189 
190 int
191 CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
192 {
193 	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
194 
195 	if (!pos)
196 		return 0;
197 	/* If embedded content find memory BIO and set content */
198 	if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
199 		BIO *mbio;
200 		unsigned char *cont;
201 		long contlen;
202 		mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
203 		if (!mbio) {
204 			CMSerror(CMS_R_CONTENT_NOT_FOUND);
205 			return 0;
206 		}
207 		contlen = BIO_get_mem_data(mbio, &cont);
208 		/* Set bio as read only so its content can't be clobbered */
209 		BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
210 		BIO_set_mem_eof_return(mbio, 0);
211 		ASN1_STRING_set0(*pos, cont, contlen);
212 		(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
213 	}
214 
215 	switch (OBJ_obj2nid(cms->contentType)) {
216 
217 	case NID_pkcs7_data:
218 	case NID_pkcs7_enveloped:
219 	case NID_pkcs7_encrypted:
220 	case NID_id_smime_ct_compressedData:
221 		/* Nothing to do */
222 		return 1;
223 
224 	case NID_pkcs7_signed:
225 		return cms_SignedData_final(cms, cmsbio);
226 
227 	case NID_pkcs7_digest:
228 		return cms_DigestedData_do_final(cms, cmsbio, 0);
229 
230 	default:
231 		CMSerror(CMS_R_UNSUPPORTED_TYPE);
232 		return 0;
233 	}
234 }
235 LCRYPTO_ALIAS(CMS_dataFinal);
236 
237 int
238 CMS_get_version(const CMS_ContentInfo *cms, long *version)
239 {
240 	switch (OBJ_obj2nid(cms->contentType)) {
241 	case NID_pkcs7_signed:
242 		*version = cms->d.signedData->version;
243 		return 1;
244 
245 	case NID_pkcs7_enveloped:
246 		*version = cms->d.envelopedData->version;
247 		return 1;
248 
249 	case NID_pkcs7_digest:
250 		*version = cms->d.digestedData->version;
251 		return 1;
252 
253 	case NID_pkcs7_encrypted:
254 		*version = cms->d.encryptedData->version;
255 		return 1;
256 
257 	case NID_id_smime_ct_authData:
258 		*version = cms->d.authenticatedData->version;
259 		return 1;
260 
261 	case NID_id_smime_ct_compressedData:
262 		*version = cms->d.compressedData->version;
263 		return 1;
264 
265 	default:
266 		CMSerror(CMS_R_UNSUPPORTED_TYPE);
267 		return 0;
268 	}
269 }
270 LCRYPTO_ALIAS(CMS_get_version);
271 
272 int
273 CMS_SignerInfo_get_version(const CMS_SignerInfo *si, long *version)
274 {
275 	*version = si->version;
276 	return 1;
277 }
278 LCRYPTO_ALIAS(CMS_SignerInfo_get_version);
279 
280 /*
281  * Return an OCTET STRING pointer to content. This allows it to be accessed
282  * or set later.
283  */
284 
285 ASN1_OCTET_STRING **
286 CMS_get0_content(CMS_ContentInfo *cms)
287 {
288 	switch (OBJ_obj2nid(cms->contentType)) {
289 	case NID_pkcs7_data:
290 		return &cms->d.data;
291 
292 	case NID_pkcs7_signed:
293 		return &cms->d.signedData->encapContentInfo->eContent;
294 
295 	case NID_pkcs7_enveloped:
296 		return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
297 
298 	case NID_pkcs7_digest:
299 		return &cms->d.digestedData->encapContentInfo->eContent;
300 
301 	case NID_pkcs7_encrypted:
302 		return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
303 
304 	case NID_id_smime_ct_authData:
305 		return &cms->d.authenticatedData->encapContentInfo->eContent;
306 
307 	case NID_id_smime_ct_compressedData:
308 		return &cms->d.compressedData->encapContentInfo->eContent;
309 
310 	default:
311 		if (cms->d.other->type == V_ASN1_OCTET_STRING)
312 			return &cms->d.other->value.octet_string;
313 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
314 		return NULL;
315 	}
316 }
317 
318 /*
319  * Return an ASN1_OBJECT pointer to content type. This allows it to be
320  * accessed or set later.
321  */
322 
323 static ASN1_OBJECT **
324 cms_get0_econtent_type(CMS_ContentInfo *cms)
325 {
326 	switch (OBJ_obj2nid(cms->contentType)) {
327 	case NID_pkcs7_signed:
328 		return &cms->d.signedData->encapContentInfo->eContentType;
329 
330 	case NID_pkcs7_enveloped:
331 		return &cms->d.envelopedData->encryptedContentInfo->contentType;
332 
333 	case NID_pkcs7_digest:
334 		return &cms->d.digestedData->encapContentInfo->eContentType;
335 
336 	case NID_pkcs7_encrypted:
337 		return &cms->d.encryptedData->encryptedContentInfo->contentType;
338 
339 	case NID_id_smime_ct_authData:
340 		return &cms->d.authenticatedData->encapContentInfo->eContentType;
341 
342 	case NID_id_smime_ct_compressedData:
343 		return &cms->d.compressedData->encapContentInfo->eContentType;
344 
345 	default:
346 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
347 		return NULL;
348 	}
349 }
350 
351 const ASN1_OBJECT *
352 CMS_get0_eContentType(CMS_ContentInfo *cms)
353 {
354 	ASN1_OBJECT **petype;
355 
356 	petype = cms_get0_econtent_type(cms);
357 	if (petype)
358 		return *petype;
359 
360 	return NULL;
361 }
362 LCRYPTO_ALIAS(CMS_get0_eContentType);
363 
364 int
365 CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
366 {
367 	ASN1_OBJECT **petype, *etype;
368 
369 	petype = cms_get0_econtent_type(cms);
370 	if (!petype)
371 		return 0;
372 	if (!oid)
373 		return 1;
374 	etype = OBJ_dup(oid);
375 	if (!etype)
376 		return 0;
377 	ASN1_OBJECT_free(*petype);
378 	*petype = etype;
379 
380 	return 1;
381 }
382 LCRYPTO_ALIAS(CMS_set1_eContentType);
383 
384 int
385 CMS_is_detached(CMS_ContentInfo *cms)
386 {
387 	ASN1_OCTET_STRING **pos;
388 
389 	pos = CMS_get0_content(cms);
390 	if (!pos)
391 		return -1;
392 	if (*pos)
393 		return 0;
394 
395 	return 1;
396 }
397 LCRYPTO_ALIAS(CMS_is_detached);
398 
399 int
400 CMS_set_detached(CMS_ContentInfo *cms, int detached)
401 {
402 	ASN1_OCTET_STRING **pos;
403 
404 	pos = CMS_get0_content(cms);
405 	if (!pos)
406 		return 0;
407 	if (detached) {
408 		ASN1_OCTET_STRING_free(*pos);
409 		*pos = NULL;
410 		return 1;
411 	}
412 	if (*pos == NULL)
413 		*pos = ASN1_OCTET_STRING_new();
414 	if (*pos != NULL) {
415 		/*
416 		 * NB: special flag to show content is created and not read in.
417 		 */
418 		(*pos)->flags |= ASN1_STRING_FLAG_CONT;
419 		return 1;
420 	}
421 	CMSerror(ERR_R_MALLOC_FAILURE);
422 
423 	return 0;
424 }
425 LCRYPTO_ALIAS(CMS_set_detached);
426 
427 /* Create a digest BIO from an X509_ALGOR structure */
428 
429 BIO *
430 cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
431 {
432 	BIO *mdbio = NULL;
433 	const ASN1_OBJECT *digestoid;
434 	const EVP_MD *digest;
435 
436 	X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
437 	digest = EVP_get_digestbyobj(digestoid);
438 	if (!digest) {
439 		CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM);
440 		goto err;
441 	}
442 	mdbio = BIO_new(BIO_f_md());
443 	if (mdbio == NULL || !BIO_set_md(mdbio, digest)) {
444 		CMSerror(CMS_R_MD_BIO_INIT_ERROR);
445 		goto err;
446 	}
447 	return mdbio;
448 
449  err:
450 	BIO_free(mdbio);
451 
452 	return NULL;
453 }
454 
455 /* Locate a message digest content from a BIO chain based on SignerInfo */
456 
457 int
458 cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg)
459 {
460 	int nid;
461 	const ASN1_OBJECT *mdoid;
462 
463 	X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
464 	nid = OBJ_obj2nid(mdoid);
465 	/* Look for digest type to match signature */
466 	for (;;) {
467 		EVP_MD_CTX *mtmp;
468 		chain = BIO_find_type(chain, BIO_TYPE_MD);
469 		if (chain == NULL) {
470 			CMSerror(CMS_R_NO_MATCHING_DIGEST);
471 			return 0;
472 		}
473 		BIO_get_md_ctx(chain, &mtmp);
474 		if (EVP_MD_CTX_type(mtmp) == nid
475 			/*
476 			 * Workaround for broken implementations that use signature
477 			 * algorithm OID instead of digest.
478 			 */
479 			|| EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
480 			return EVP_MD_CTX_copy_ex(mctx, mtmp);
481 		chain = BIO_next(chain);
482 	}
483 }
484 
485 static STACK_OF(CMS_CertificateChoices) **
486 cms_get0_certificate_choices(CMS_ContentInfo *cms)
487 {
488 	switch (OBJ_obj2nid(cms->contentType)) {
489 	case NID_pkcs7_signed:
490 		return &cms->d.signedData->certificates;
491 
492 	case NID_pkcs7_enveloped:
493 		if (cms->d.envelopedData->originatorInfo == NULL)
494 			return NULL;
495 		return &cms->d.envelopedData->originatorInfo->certificates;
496 
497 	default:
498 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
499 		return NULL;
500 	}
501 }
502 
503 CMS_CertificateChoices *
504 CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
505 {
506 	STACK_OF(CMS_CertificateChoices) **pcerts;
507 	CMS_CertificateChoices *cch;
508 
509 	pcerts = cms_get0_certificate_choices(cms);
510 	if (!pcerts)
511 		return NULL;
512 	if (!*pcerts)
513 		*pcerts = sk_CMS_CertificateChoices_new_null();
514 	if (!*pcerts)
515 		return NULL;
516 	cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it);
517 	if (!cch)
518 		return NULL;
519 	if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
520 		ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it);
521 		return NULL;
522 	}
523 
524 	return cch;
525 }
526 LCRYPTO_ALIAS(CMS_add0_CertificateChoices);
527 
528 int
529 CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
530 {
531 	CMS_CertificateChoices *cch;
532 	STACK_OF(CMS_CertificateChoices) **pcerts;
533 	int i;
534 
535 	pcerts = cms_get0_certificate_choices(cms);
536 	if (!pcerts)
537 		return 0;
538 	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
539 		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
540 		if (cch->type == CMS_CERTCHOICE_CERT) {
541 			if (!X509_cmp(cch->d.certificate, cert)) {
542 			    CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT);
543 			    return 0;
544 			}
545 		}
546 	}
547 	cch = CMS_add0_CertificateChoices(cms);
548 	if (!cch)
549 		return 0;
550 	cch->type = CMS_CERTCHOICE_CERT;
551 	cch->d.certificate = cert;
552 
553 	return 1;
554 }
555 LCRYPTO_ALIAS(CMS_add0_cert);
556 
557 int
558 CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
559 {
560 	int r;
561 
562 	r = CMS_add0_cert(cms, cert);
563 	if (r > 0)
564 		X509_up_ref(cert);
565 
566 	return r;
567 }
568 LCRYPTO_ALIAS(CMS_add1_cert);
569 
570 static STACK_OF(CMS_RevocationInfoChoice) **
571 cms_get0_revocation_choices(CMS_ContentInfo *cms)
572 {
573 	switch (OBJ_obj2nid(cms->contentType)) {
574 	case NID_pkcs7_signed:
575 		return &cms->d.signedData->crls;
576 
577 	case NID_pkcs7_enveloped:
578 		if (cms->d.envelopedData->originatorInfo == NULL)
579 			return NULL;
580 		return &cms->d.envelopedData->originatorInfo->crls;
581 
582 	default:
583 		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
584 		return NULL;
585 	}
586 }
587 
588 CMS_RevocationInfoChoice *
589 CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
590 {
591 	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
592 	CMS_RevocationInfoChoice *rch;
593 
594 	pcrls = cms_get0_revocation_choices(cms);
595 	if (!pcrls)
596 		return NULL;
597 	if (!*pcrls)
598 		*pcrls = sk_CMS_RevocationInfoChoice_new_null();
599 	if (!*pcrls)
600 		return NULL;
601 	rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it);
602 	if (!rch)
603 		return NULL;
604 	if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
605 		ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it);
606 		return NULL;
607 	}
608 
609 	return rch;
610 }
611 LCRYPTO_ALIAS(CMS_add0_RevocationInfoChoice);
612 
613 int
614 CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
615 {
616 	CMS_RevocationInfoChoice *rch;
617 
618 	rch = CMS_add0_RevocationInfoChoice(cms);
619 	if (!rch)
620 		return 0;
621 	rch->type = CMS_REVCHOICE_CRL;
622 	rch->d.crl = crl;
623 
624 	return 1;
625 }
626 LCRYPTO_ALIAS(CMS_add0_crl);
627 
628 int
629 CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
630 {
631 	int r;
632 
633 	r = CMS_add0_crl(cms, crl);
634 	if (r > 0)
635 		X509_CRL_up_ref(crl);
636 
637 	return r;
638 }
639 LCRYPTO_ALIAS(CMS_add1_crl);
640 
641 STACK_OF(X509) *
642 CMS_get1_certs(CMS_ContentInfo *cms)
643 {
644 	STACK_OF(X509) *certs = NULL;
645 	CMS_CertificateChoices *cch;
646 	STACK_OF(CMS_CertificateChoices) **pcerts;
647 	int i;
648 
649 	pcerts = cms_get0_certificate_choices(cms);
650 	if (!pcerts)
651 		return NULL;
652 	for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
653 		cch = sk_CMS_CertificateChoices_value(*pcerts, i);
654 		if (cch->type == 0) {
655 			if (!certs) {
656 			    certs = sk_X509_new_null();
657 			    if (!certs)
658 			        return NULL;
659 			}
660 			if (!sk_X509_push(certs, cch->d.certificate)) {
661 			    sk_X509_pop_free(certs, X509_free);
662 			    return NULL;
663 			}
664 			X509_up_ref(cch->d.certificate);
665 		}
666 	}
667 	return certs;
668 }
669 LCRYPTO_ALIAS(CMS_get1_certs);
670 
671 STACK_OF(X509_CRL) *
672 CMS_get1_crls(CMS_ContentInfo *cms)
673 {
674 	STACK_OF(X509_CRL) *crls = NULL;
675 	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
676 	CMS_RevocationInfoChoice *rch;
677 	int i;
678 
679 	pcrls = cms_get0_revocation_choices(cms);
680 	if (!pcrls)
681 		return NULL;
682 	for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
683 		rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
684 		if (rch->type == 0) {
685 			if (!crls) {
686 			    crls = sk_X509_CRL_new_null();
687 			    if (!crls)
688 			        return NULL;
689 			}
690 			if (!sk_X509_CRL_push(crls, rch->d.crl)) {
691 			    sk_X509_CRL_pop_free(crls, X509_CRL_free);
692 			    return NULL;
693 			}
694 			X509_CRL_up_ref(rch->d.crl);
695 		}
696 	}
697 	return crls;
698 }
699 LCRYPTO_ALIAS(CMS_get1_crls);
700 
701 static const ASN1_OCTET_STRING *
702 cms_X509_get0_subject_key_id(X509 *x)
703 {
704 	/* Call for side-effect of computing hash and caching extensions */
705 	X509_check_purpose(x, -1, -1);
706 	return x->skid;
707 }
708 
709 int
710 cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
711 {
712 	int ret;
713 
714 	ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
715 	if (ret)
716 		return ret;
717 
718 	return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert));
719 }
720 
721 int
722 cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
723 {
724 	const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert);
725 
726 	if (cert_keyid == NULL)
727 		return -1;
728 
729 	return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
730 }
731 
732 int
733 cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
734 {
735 	CMS_IssuerAndSerialNumber *ias;
736 
737 	ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it);
738 	if (!ias)
739 		goto err;
740 	if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
741 		goto err;
742 	if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert)))
743 		goto err;
744 	ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it);
745 	*pias = ias;
746 
747 	return 1;
748 
749  err:
750 	ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it);
751 	CMSerror(ERR_R_MALLOC_FAILURE);
752 
753 	return 0;
754 }
755 
756 int
757 cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
758 {
759 	ASN1_OCTET_STRING *keyid = NULL;
760 	const ASN1_OCTET_STRING *cert_keyid;
761 
762 	cert_keyid = cms_X509_get0_subject_key_id(cert);
763 	if (cert_keyid == NULL) {
764 		CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID);
765 		return 0;
766 	}
767 	keyid = ASN1_STRING_dup(cert_keyid);
768 	if (!keyid) {
769 		CMSerror(ERR_R_MALLOC_FAILURE);
770 		return 0;
771 	}
772 	ASN1_OCTET_STRING_free(*pkeyid);
773 	*pkeyid = keyid;
774 
775 	return 1;
776 }
777