1 /* $OpenBSD: cms_lib.c,v 1.25 2024/03/30 01:53:05 joshua 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 *
d2i_CMS_ContentInfo(CMS_ContentInfo ** a,const unsigned char ** in,long len)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
i2d_CMS_ContentInfo(CMS_ContentInfo * a,unsigned char ** out)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 *
CMS_ContentInfo_new(void)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
CMS_ContentInfo_free(CMS_ContentInfo * a)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
CMS_ContentInfo_print_ctx(BIO * out,CMS_ContentInfo * x,int indent,const ASN1_PCTX * pctx)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 *
CMS_get0_type(const CMS_ContentInfo * cms)104 CMS_get0_type(const CMS_ContentInfo *cms)
105 {
106 return cms->contentType;
107 }
108 LCRYPTO_ALIAS(CMS_get0_type);
109
110 CMS_ContentInfo *
cms_Data_create(void)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 *
cms_content_bio(CMS_ContentInfo * cms)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 *
CMS_dataInit(CMS_ContentInfo * cms,BIO * in_content_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
CMS_dataFinal(CMS_ContentInfo * cms,BIO * cmsbio)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
CMS_get_version(const CMS_ContentInfo * cms,long * version)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
CMS_SignerInfo_get_version(const CMS_SignerInfo * si,long * version)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 **
CMS_get0_content(CMS_ContentInfo * cms)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 LCRYPTO_ALIAS(CMS_get0_content);
318
319 /*
320 * Return an ASN1_OBJECT pointer to content type. This allows it to be
321 * accessed or set later.
322 */
323
324 static ASN1_OBJECT **
cms_get0_econtent_type(CMS_ContentInfo * cms)325 cms_get0_econtent_type(CMS_ContentInfo *cms)
326 {
327 switch (OBJ_obj2nid(cms->contentType)) {
328 case NID_pkcs7_signed:
329 return &cms->d.signedData->encapContentInfo->eContentType;
330
331 case NID_pkcs7_enveloped:
332 return &cms->d.envelopedData->encryptedContentInfo->contentType;
333
334 case NID_pkcs7_digest:
335 return &cms->d.digestedData->encapContentInfo->eContentType;
336
337 case NID_pkcs7_encrypted:
338 return &cms->d.encryptedData->encryptedContentInfo->contentType;
339
340 case NID_id_smime_ct_authData:
341 return &cms->d.authenticatedData->encapContentInfo->eContentType;
342
343 case NID_id_smime_ct_compressedData:
344 return &cms->d.compressedData->encapContentInfo->eContentType;
345
346 default:
347 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
348 return NULL;
349 }
350 }
351
352 const ASN1_OBJECT *
CMS_get0_eContentType(CMS_ContentInfo * cms)353 CMS_get0_eContentType(CMS_ContentInfo *cms)
354 {
355 ASN1_OBJECT **petype;
356
357 petype = cms_get0_econtent_type(cms);
358 if (petype)
359 return *petype;
360
361 return NULL;
362 }
363 LCRYPTO_ALIAS(CMS_get0_eContentType);
364
365 int
CMS_set1_eContentType(CMS_ContentInfo * cms,const ASN1_OBJECT * oid)366 CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
367 {
368 ASN1_OBJECT **petype, *etype;
369
370 petype = cms_get0_econtent_type(cms);
371 if (!petype)
372 return 0;
373 if (!oid)
374 return 1;
375 etype = OBJ_dup(oid);
376 if (!etype)
377 return 0;
378 ASN1_OBJECT_free(*petype);
379 *petype = etype;
380
381 return 1;
382 }
383 LCRYPTO_ALIAS(CMS_set1_eContentType);
384
385 int
CMS_is_detached(CMS_ContentInfo * cms)386 CMS_is_detached(CMS_ContentInfo *cms)
387 {
388 ASN1_OCTET_STRING **pos;
389
390 pos = CMS_get0_content(cms);
391 if (!pos)
392 return -1;
393 if (*pos)
394 return 0;
395
396 return 1;
397 }
398 LCRYPTO_ALIAS(CMS_is_detached);
399
400 int
CMS_set_detached(CMS_ContentInfo * cms,int detached)401 CMS_set_detached(CMS_ContentInfo *cms, int detached)
402 {
403 ASN1_OCTET_STRING **pos;
404
405 pos = CMS_get0_content(cms);
406 if (!pos)
407 return 0;
408 if (detached) {
409 ASN1_OCTET_STRING_free(*pos);
410 *pos = NULL;
411 return 1;
412 }
413 if (*pos == NULL)
414 *pos = ASN1_OCTET_STRING_new();
415 if (*pos != NULL) {
416 /*
417 * NB: special flag to show content is created and not read in.
418 */
419 (*pos)->flags |= ASN1_STRING_FLAG_CONT;
420 return 1;
421 }
422 CMSerror(ERR_R_MALLOC_FAILURE);
423
424 return 0;
425 }
426 LCRYPTO_ALIAS(CMS_set_detached);
427
428 /* Create a digest BIO from an X509_ALGOR structure */
429
430 BIO *
cms_DigestAlgorithm_init_bio(X509_ALGOR * digestAlgorithm)431 cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
432 {
433 BIO *mdbio = NULL;
434 const ASN1_OBJECT *digestoid;
435 const EVP_MD *digest;
436
437 X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
438 digest = EVP_get_digestbyobj(digestoid);
439 if (!digest) {
440 CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM);
441 goto err;
442 }
443 mdbio = BIO_new(BIO_f_md());
444 if (mdbio == NULL || !BIO_set_md(mdbio, digest)) {
445 CMSerror(CMS_R_MD_BIO_INIT_ERROR);
446 goto err;
447 }
448 return mdbio;
449
450 err:
451 BIO_free(mdbio);
452
453 return NULL;
454 }
455
456 /* Locate a message digest content from a BIO chain based on SignerInfo */
457
458 int
cms_DigestAlgorithm_find_ctx(EVP_MD_CTX * mctx,BIO * chain,X509_ALGOR * mdalg)459 cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg)
460 {
461 int nid;
462 const ASN1_OBJECT *mdoid;
463
464 X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
465 nid = OBJ_obj2nid(mdoid);
466 /* Look for digest type to match signature */
467 for (;;) {
468 EVP_MD_CTX *mtmp;
469 chain = BIO_find_type(chain, BIO_TYPE_MD);
470 if (chain == NULL) {
471 CMSerror(CMS_R_NO_MATCHING_DIGEST);
472 return 0;
473 }
474 BIO_get_md_ctx(chain, &mtmp);
475 if (EVP_MD_CTX_type(mtmp) == nid
476 /*
477 * Workaround for broken implementations that use signature
478 * algorithm OID instead of digest.
479 */
480 || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
481 return EVP_MD_CTX_copy_ex(mctx, mtmp);
482 chain = BIO_next(chain);
483 }
484 }
485
STACK_OF(CMS_CertificateChoices)486 static STACK_OF(CMS_CertificateChoices) **
487 cms_get0_certificate_choices(CMS_ContentInfo *cms)
488 {
489 switch (OBJ_obj2nid(cms->contentType)) {
490 case NID_pkcs7_signed:
491 return &cms->d.signedData->certificates;
492
493 case NID_pkcs7_enveloped:
494 if (cms->d.envelopedData->originatorInfo == NULL)
495 return NULL;
496 return &cms->d.envelopedData->originatorInfo->certificates;
497
498 default:
499 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
500 return NULL;
501 }
502 }
503
504 CMS_CertificateChoices *
CMS_add0_CertificateChoices(CMS_ContentInfo * cms)505 CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
506 {
507 STACK_OF(CMS_CertificateChoices) **pcerts;
508 CMS_CertificateChoices *cch;
509
510 pcerts = cms_get0_certificate_choices(cms);
511 if (!pcerts)
512 return NULL;
513 if (!*pcerts)
514 *pcerts = sk_CMS_CertificateChoices_new_null();
515 if (!*pcerts)
516 return NULL;
517 cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it);
518 if (!cch)
519 return NULL;
520 if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
521 ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it);
522 return NULL;
523 }
524
525 return cch;
526 }
527 LCRYPTO_ALIAS(CMS_add0_CertificateChoices);
528
529 int
CMS_add0_cert(CMS_ContentInfo * cms,X509 * cert)530 CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
531 {
532 CMS_CertificateChoices *cch;
533 STACK_OF(CMS_CertificateChoices) **pcerts;
534 int i;
535
536 pcerts = cms_get0_certificate_choices(cms);
537 if (!pcerts)
538 return 0;
539 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
540 cch = sk_CMS_CertificateChoices_value(*pcerts, i);
541 if (cch->type == CMS_CERTCHOICE_CERT) {
542 if (!X509_cmp(cch->d.certificate, cert)) {
543 CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT);
544 return 0;
545 }
546 }
547 }
548 cch = CMS_add0_CertificateChoices(cms);
549 if (!cch)
550 return 0;
551 cch->type = CMS_CERTCHOICE_CERT;
552 cch->d.certificate = cert;
553
554 return 1;
555 }
556 LCRYPTO_ALIAS(CMS_add0_cert);
557
558 int
CMS_add1_cert(CMS_ContentInfo * cms,X509 * cert)559 CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
560 {
561 int r;
562
563 r = CMS_add0_cert(cms, cert);
564 if (r > 0)
565 X509_up_ref(cert);
566
567 return r;
568 }
569 LCRYPTO_ALIAS(CMS_add1_cert);
570
STACK_OF(CMS_RevocationInfoChoice)571 static STACK_OF(CMS_RevocationInfoChoice) **
572 cms_get0_revocation_choices(CMS_ContentInfo *cms)
573 {
574 switch (OBJ_obj2nid(cms->contentType)) {
575 case NID_pkcs7_signed:
576 return &cms->d.signedData->crls;
577
578 case NID_pkcs7_enveloped:
579 if (cms->d.envelopedData->originatorInfo == NULL)
580 return NULL;
581 return &cms->d.envelopedData->originatorInfo->crls;
582
583 default:
584 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
585 return NULL;
586 }
587 }
588
589 CMS_RevocationInfoChoice *
CMS_add0_RevocationInfoChoice(CMS_ContentInfo * cms)590 CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
591 {
592 STACK_OF(CMS_RevocationInfoChoice) **pcrls;
593 CMS_RevocationInfoChoice *rch;
594
595 pcrls = cms_get0_revocation_choices(cms);
596 if (!pcrls)
597 return NULL;
598 if (!*pcrls)
599 *pcrls = sk_CMS_RevocationInfoChoice_new_null();
600 if (!*pcrls)
601 return NULL;
602 rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it);
603 if (!rch)
604 return NULL;
605 if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
606 ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it);
607 return NULL;
608 }
609
610 return rch;
611 }
612 LCRYPTO_ALIAS(CMS_add0_RevocationInfoChoice);
613
614 int
CMS_add0_crl(CMS_ContentInfo * cms,X509_CRL * crl)615 CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
616 {
617 CMS_RevocationInfoChoice *rch;
618
619 rch = CMS_add0_RevocationInfoChoice(cms);
620 if (!rch)
621 return 0;
622 rch->type = CMS_REVCHOICE_CRL;
623 rch->d.crl = crl;
624
625 return 1;
626 }
627 LCRYPTO_ALIAS(CMS_add0_crl);
628
629 int
CMS_add1_crl(CMS_ContentInfo * cms,X509_CRL * crl)630 CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
631 {
632 int r;
633
634 r = CMS_add0_crl(cms, crl);
635 if (r > 0)
636 X509_CRL_up_ref(crl);
637
638 return r;
639 }
640 LCRYPTO_ALIAS(CMS_add1_crl);
641
STACK_OF(X509)642 STACK_OF(X509) *
643 CMS_get1_certs(CMS_ContentInfo *cms)
644 {
645 STACK_OF(X509) *certs = NULL;
646 CMS_CertificateChoices *cch;
647 STACK_OF(CMS_CertificateChoices) **pcerts;
648 int i;
649
650 pcerts = cms_get0_certificate_choices(cms);
651 if (!pcerts)
652 return NULL;
653 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
654 cch = sk_CMS_CertificateChoices_value(*pcerts, i);
655 if (cch->type == 0) {
656 if (!certs) {
657 certs = sk_X509_new_null();
658 if (!certs)
659 return NULL;
660 }
661 if (!sk_X509_push(certs, cch->d.certificate)) {
662 sk_X509_pop_free(certs, X509_free);
663 return NULL;
664 }
665 X509_up_ref(cch->d.certificate);
666 }
667 }
668 return certs;
669 }
670 LCRYPTO_ALIAS(CMS_get1_certs);
671
STACK_OF(X509_CRL)672 STACK_OF(X509_CRL) *
673 CMS_get1_crls(CMS_ContentInfo *cms)
674 {
675 STACK_OF(X509_CRL) *crls = NULL;
676 STACK_OF(CMS_RevocationInfoChoice) **pcrls;
677 CMS_RevocationInfoChoice *rch;
678 int i;
679
680 pcrls = cms_get0_revocation_choices(cms);
681 if (!pcrls)
682 return NULL;
683 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
684 rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
685 if (rch->type == 0) {
686 if (!crls) {
687 crls = sk_X509_CRL_new_null();
688 if (!crls)
689 return NULL;
690 }
691 if (!sk_X509_CRL_push(crls, rch->d.crl)) {
692 sk_X509_CRL_pop_free(crls, X509_CRL_free);
693 return NULL;
694 }
695 X509_CRL_up_ref(rch->d.crl);
696 }
697 }
698 return crls;
699 }
700 LCRYPTO_ALIAS(CMS_get1_crls);
701
702 static const ASN1_OCTET_STRING *
cms_X509_get0_subject_key_id(X509 * x)703 cms_X509_get0_subject_key_id(X509 *x)
704 {
705 /* Call for side-effect of computing hash and caching extensions */
706 X509_check_purpose(x, -1, -1);
707 return x->skid;
708 }
709
710 int
cms_ias_cert_cmp(CMS_IssuerAndSerialNumber * ias,X509 * cert)711 cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
712 {
713 int ret;
714
715 ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
716 if (ret)
717 return ret;
718
719 return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert));
720 }
721
722 int
cms_keyid_cert_cmp(ASN1_OCTET_STRING * keyid,X509 * cert)723 cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
724 {
725 const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert);
726
727 if (cert_keyid == NULL)
728 return -1;
729
730 return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
731 }
732
733 int
cms_set1_ias(CMS_IssuerAndSerialNumber ** pias,X509 * cert)734 cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
735 {
736 CMS_IssuerAndSerialNumber *ias;
737
738 ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it);
739 if (!ias)
740 goto err;
741 if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
742 goto err;
743 if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert)))
744 goto err;
745 ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it);
746 *pias = ias;
747
748 return 1;
749
750 err:
751 ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it);
752 CMSerror(ERR_R_MALLOC_FAILURE);
753
754 return 0;
755 }
756
757 int
cms_set1_keyid(ASN1_OCTET_STRING ** pkeyid,X509 * cert)758 cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
759 {
760 ASN1_OCTET_STRING *keyid = NULL;
761 const ASN1_OCTET_STRING *cert_keyid;
762
763 cert_keyid = cms_X509_get0_subject_key_id(cert);
764 if (cert_keyid == NULL) {
765 CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID);
766 return 0;
767 }
768 keyid = ASN1_STRING_dup(cert_keyid);
769 if (!keyid) {
770 CMSerror(ERR_R_MALLOC_FAILURE);
771 return 0;
772 }
773 ASN1_OCTET_STRING_free(*pkeyid);
774 *pkeyid = keyid;
775
776 return 1;
777 }
778