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