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