xref: /openssl/crypto/cms/cms_lib.c (revision 7ed6de99)
1 /*
2  * Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <openssl/asn1t.h>
11 #include <openssl/x509v3.h>
12 #include <openssl/err.h>
13 #include <openssl/pem.h>
14 #include <openssl/bio.h>
15 #include <openssl/asn1.h>
16 #include <openssl/cms.h>
17 #include "internal/sizes.h"
18 #include "crypto/x509.h"
19 #include "cms_local.h"
20 
21 static STACK_OF(CMS_CertificateChoices)
22 **cms_get0_certificate_choices(CMS_ContentInfo *cms);
23 
24 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_ContentInfo)
IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)25 IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
26 
27 CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
28                                      const unsigned char **in, long len)
29 {
30     CMS_ContentInfo *ci;
31     const CMS_CTX *ctx = ossl_cms_get0_cmsctx(a == NULL ? NULL : *a);
32 
33     ci = (CMS_ContentInfo *)ASN1_item_d2i_ex((ASN1_VALUE **)a, in, len,
34                                           (CMS_ContentInfo_it()),
35                                           ossl_cms_ctx_get0_libctx(ctx),
36                                           ossl_cms_ctx_get0_propq(ctx));
37     if (ci != NULL) {
38         ERR_set_mark();
39         ossl_cms_resolve_libctx(ci);
40         ERR_pop_to_mark();
41     }
42     return ci;
43 }
44 
i2d_CMS_ContentInfo(const CMS_ContentInfo * a,unsigned char ** out)45 int i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out)
46 {
47     return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it()));
48 }
49 
CMS_ContentInfo_new_ex(OSSL_LIB_CTX * libctx,const char * propq)50 CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
51 {
52     CMS_ContentInfo *ci;
53 
54     ci = (CMS_ContentInfo *)ASN1_item_new_ex(ASN1_ITEM_rptr(CMS_ContentInfo),
55                                              libctx, propq);
56     if (ci != NULL) {
57         ci->ctx.libctx = libctx;
58         ci->ctx.propq = NULL;
59         if (propq != NULL) {
60             ci->ctx.propq = OPENSSL_strdup(propq);
61             if (ci->ctx.propq == NULL) {
62                 CMS_ContentInfo_free(ci);
63                 ci = NULL;
64             }
65         }
66     }
67     return ci;
68 }
69 
ossl_cms_get0_cmsctx(const CMS_ContentInfo * cms)70 const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms)
71 {
72     return cms != NULL ? &cms->ctx : NULL;
73 }
74 
ossl_cms_ctx_get0_libctx(const CMS_CTX * ctx)75 OSSL_LIB_CTX *ossl_cms_ctx_get0_libctx(const CMS_CTX *ctx)
76 {
77     return ctx != NULL ? ctx->libctx : NULL;
78 }
79 
ossl_cms_ctx_get0_propq(const CMS_CTX * ctx)80 const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx)
81 {
82     return ctx != NULL ? ctx->propq : NULL;
83 }
84 
ossl_cms_resolve_libctx(CMS_ContentInfo * ci)85 void ossl_cms_resolve_libctx(CMS_ContentInfo *ci)
86 {
87     int i;
88     CMS_CertificateChoices *cch;
89     STACK_OF(CMS_CertificateChoices) **pcerts;
90     const CMS_CTX *ctx = ossl_cms_get0_cmsctx(ci);
91     OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
92     const char *propq = ossl_cms_ctx_get0_propq(ctx);
93 
94     ossl_cms_SignerInfos_set_cmsctx(ci);
95     ossl_cms_RecipientInfos_set_cmsctx(ci);
96 
97     pcerts = cms_get0_certificate_choices(ci);
98     if (pcerts != NULL) {
99         for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
100             cch = sk_CMS_CertificateChoices_value(*pcerts, i);
101             if (cch->type == CMS_CERTCHOICE_CERT)
102                 ossl_x509_set0_libctx(cch->d.certificate, libctx, propq);
103         }
104     }
105 }
106 
CMS_get0_type(const CMS_ContentInfo * cms)107 const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms)
108 {
109     return cms->contentType;
110 }
111 
ossl_cms_Data_create(OSSL_LIB_CTX * libctx,const char * propq)112 CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *libctx, const char *propq)
113 {
114     CMS_ContentInfo *cms = CMS_ContentInfo_new_ex(libctx, propq);
115 
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 
ossl_cms_content_bio(CMS_ContentInfo * cms)124 BIO *ossl_cms_content_bio(CMS_ContentInfo *cms)
125 {
126     ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
127 
128     if (pos == NULL)
129         return NULL;
130     /* If content detached data goes nowhere: create NULL BIO */
131     if (*pos == NULL)
132         return BIO_new(BIO_s_null());
133     /*
134      * If content not detached and created return memory BIO
135      */
136     if (*pos == NULL || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
137         return BIO_new(BIO_s_mem());
138     /* Else content was read in: return read only BIO for it */
139     return BIO_new_mem_buf((*pos)->data, (*pos)->length);
140 }
141 
CMS_dataInit(CMS_ContentInfo * cms,BIO * icont)142 BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
143 {
144     BIO *cmsbio, *cont;
145     if (icont)
146         cont = icont;
147     else
148         cont = ossl_cms_content_bio(cms);
149     if (!cont) {
150         ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
151         return NULL;
152     }
153     switch (OBJ_obj2nid(cms->contentType)) {
154 
155     case NID_pkcs7_data:
156         return cont;
157 
158     case NID_pkcs7_signed:
159         cmsbio = ossl_cms_SignedData_init_bio(cms);
160         break;
161 
162     case NID_pkcs7_digest:
163         cmsbio = ossl_cms_DigestedData_init_bio(cms);
164         break;
165 #ifndef OPENSSL_NO_ZLIB
166     case NID_id_smime_ct_compressedData:
167         cmsbio = ossl_cms_CompressedData_init_bio(cms);
168         break;
169 #endif
170 
171     case NID_pkcs7_encrypted:
172         cmsbio = ossl_cms_EncryptedData_init_bio(cms);
173         break;
174 
175     case NID_pkcs7_enveloped:
176         cmsbio = ossl_cms_EnvelopedData_init_bio(cms);
177         break;
178 
179     case NID_id_smime_ct_authEnvelopedData:
180         cmsbio = ossl_cms_AuthEnvelopedData_init_bio(cms);
181         break;
182 
183     default:
184         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
185         goto err;
186     }
187 
188     if (cmsbio)
189         return BIO_push(cmsbio, cont);
190 err:
191     if (!icont)
192         BIO_free(cont);
193     return NULL;
194 
195 }
196 
197 /* unfortunately cannot constify SMIME_write_ASN1() due to this function */
CMS_dataFinal(CMS_ContentInfo * cms,BIO * cmsbio)198 int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
199 {
200     return ossl_cms_DataFinal(cms, cmsbio, NULL, 0);
201 }
202 
ossl_cms_DataFinal(CMS_ContentInfo * cms,BIO * cmsbio,const unsigned char * precomp_md,unsigned int precomp_mdlen)203 int ossl_cms_DataFinal(CMS_ContentInfo *cms, BIO *cmsbio,
204                        const unsigned char *precomp_md,
205                        unsigned int precomp_mdlen)
206 {
207     ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
208 
209     if (pos == NULL)
210         return 0;
211     /* If embedded content find memory BIO and set content */
212     if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
213         BIO *mbio;
214         unsigned char *cont;
215         long contlen;
216         mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
217         if (!mbio) {
218             ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND);
219             return 0;
220         }
221         contlen = BIO_get_mem_data(mbio, &cont);
222         /* Set bio as read only so its content can't be clobbered */
223         BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
224         BIO_set_mem_eof_return(mbio, 0);
225         ASN1_STRING_set0(*pos, cont, contlen);
226         (*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
227     }
228 
229     switch (OBJ_obj2nid(cms->contentType)) {
230 
231     case NID_pkcs7_data:
232     case NID_pkcs7_encrypted:
233     case NID_id_smime_ct_compressedData:
234         /* Nothing to do */
235         return 1;
236 
237     case NID_pkcs7_enveloped:
238         return ossl_cms_EnvelopedData_final(cms, cmsbio);
239 
240     case NID_id_smime_ct_authEnvelopedData:
241         return ossl_cms_AuthEnvelopedData_final(cms, cmsbio);
242 
243     case NID_pkcs7_signed:
244         return ossl_cms_SignedData_final(cms, cmsbio, precomp_md, precomp_mdlen);
245 
246     case NID_pkcs7_digest:
247         return ossl_cms_DigestedData_do_final(cms, cmsbio, 0);
248 
249     default:
250         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE);
251         return 0;
252     }
253 }
254 
255 /*
256  * Return an OCTET STRING pointer to content. This allows it to be accessed
257  * or set later.
258  */
259 
CMS_get0_content(CMS_ContentInfo * cms)260 ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
261 {
262     switch (OBJ_obj2nid(cms->contentType)) {
263 
264     case NID_pkcs7_data:
265         return &cms->d.data;
266 
267     case NID_pkcs7_signed:
268         return &cms->d.signedData->encapContentInfo->eContent;
269 
270     case NID_pkcs7_enveloped:
271         return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
272 
273     case NID_pkcs7_digest:
274         return &cms->d.digestedData->encapContentInfo->eContent;
275 
276     case NID_pkcs7_encrypted:
277         return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
278 
279     case NID_id_smime_ct_authEnvelopedData:
280         return &cms->d.authEnvelopedData->authEncryptedContentInfo
281                                         ->encryptedContent;
282 
283     case NID_id_smime_ct_authData:
284         return &cms->d.authenticatedData->encapContentInfo->eContent;
285 
286     case NID_id_smime_ct_compressedData:
287         return &cms->d.compressedData->encapContentInfo->eContent;
288 
289     default:
290         if (cms->d.other->type == V_ASN1_OCTET_STRING)
291             return &cms->d.other->value.octet_string;
292         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
293         return NULL;
294 
295     }
296 }
297 
298 /*
299  * Return an ASN1_OBJECT pointer to content type. This allows it to be
300  * accessed or set later.
301  */
302 
cms_get0_econtent_type(CMS_ContentInfo * cms)303 static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
304 {
305     switch (OBJ_obj2nid(cms->contentType)) {
306 
307     case NID_pkcs7_signed:
308         return &cms->d.signedData->encapContentInfo->eContentType;
309 
310     case NID_pkcs7_enveloped:
311         return &cms->d.envelopedData->encryptedContentInfo->contentType;
312 
313     case NID_pkcs7_digest:
314         return &cms->d.digestedData->encapContentInfo->eContentType;
315 
316     case NID_pkcs7_encrypted:
317         return &cms->d.encryptedData->encryptedContentInfo->contentType;
318 
319     case NID_id_smime_ct_authEnvelopedData:
320         return &cms->d.authEnvelopedData->authEncryptedContentInfo
321                                         ->contentType;
322     case NID_id_smime_ct_authData:
323         return &cms->d.authenticatedData->encapContentInfo->eContentType;
324 
325     case NID_id_smime_ct_compressedData:
326         return &cms->d.compressedData->encapContentInfo->eContentType;
327 
328     default:
329         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
330         return NULL;
331 
332     }
333 }
334 
CMS_get0_eContentType(CMS_ContentInfo * cms)335 const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
336 {
337     ASN1_OBJECT **petype;
338     petype = cms_get0_econtent_type(cms);
339     if (petype)
340         return *petype;
341     return NULL;
342 }
343 
CMS_set1_eContentType(CMS_ContentInfo * cms,const ASN1_OBJECT * oid)344 int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
345 {
346     ASN1_OBJECT **petype, *etype;
347 
348     petype = cms_get0_econtent_type(cms);
349     if (petype == NULL)
350         return 0;
351     if (oid == NULL)
352         return 1;
353     etype = OBJ_dup(oid);
354     if (etype == NULL)
355         return 0;
356     ASN1_OBJECT_free(*petype);
357     *petype = etype;
358     return 1;
359 }
360 
CMS_is_detached(CMS_ContentInfo * cms)361 int CMS_is_detached(CMS_ContentInfo *cms)
362 {
363     ASN1_OCTET_STRING **pos;
364 
365     pos = CMS_get0_content(cms);
366     if (pos == NULL)
367         return -1;
368     if (*pos != NULL)
369         return 0;
370     return 1;
371 }
372 
CMS_set_detached(CMS_ContentInfo * cms,int detached)373 int CMS_set_detached(CMS_ContentInfo *cms, int detached)
374 {
375     ASN1_OCTET_STRING **pos;
376 
377     pos = CMS_get0_content(cms);
378     if (pos == NULL)
379         return 0;
380     if (detached) {
381         ASN1_OCTET_STRING_free(*pos);
382         *pos = NULL;
383         return 1;
384     }
385     if (*pos == NULL)
386         *pos = ASN1_OCTET_STRING_new();
387     if (*pos != NULL) {
388         /*
389          * NB: special flag to show content is created and not read in.
390          */
391         (*pos)->flags |= ASN1_STRING_FLAG_CONT;
392         return 1;
393     }
394     ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
395     return 0;
396 }
397 
398 /* Create a digest BIO from an X509_ALGOR structure */
399 
ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR * digestAlgorithm,const CMS_CTX * ctx)400 BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
401                                        const CMS_CTX *ctx)
402 {
403     BIO *mdbio = NULL;
404     const ASN1_OBJECT *digestoid;
405     const EVP_MD *digest = NULL;
406     EVP_MD *fetched_digest = NULL;
407     char alg[OSSL_MAX_NAME_SIZE];
408 
409     X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
410     OBJ_obj2txt(alg, sizeof(alg), digestoid, 0);
411 
412     (void)ERR_set_mark();
413     fetched_digest = EVP_MD_fetch(ossl_cms_ctx_get0_libctx(ctx), alg,
414                                   ossl_cms_ctx_get0_propq(ctx));
415 
416     if (fetched_digest != NULL)
417         digest = fetched_digest;
418     else
419         digest = EVP_get_digestbyobj(digestoid);
420     if (digest == NULL) {
421         (void)ERR_clear_last_mark();
422         ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_DIGEST_ALGORITHM);
423         goto err;
424     }
425     (void)ERR_pop_to_mark();
426 
427     mdbio = BIO_new(BIO_f_md());
428     if (mdbio == NULL || BIO_set_md(mdbio, digest) <= 0) {
429         ERR_raise(ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR);
430         goto err;
431     }
432     EVP_MD_free(fetched_digest);
433     return mdbio;
434  err:
435     EVP_MD_free(fetched_digest);
436     BIO_free(mdbio);
437     return NULL;
438 }
439 
440 /* Locate a message digest content from a BIO chain based on SignerInfo */
441 
ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX * mctx,BIO * chain,X509_ALGOR * mdalg)442 int ossl_cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
443                                       X509_ALGOR *mdalg)
444 {
445     int nid;
446     const ASN1_OBJECT *mdoid;
447     X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
448     nid = OBJ_obj2nid(mdoid);
449     /* Look for digest type to match signature */
450     for (;;) {
451         EVP_MD_CTX *mtmp;
452         chain = BIO_find_type(chain, BIO_TYPE_MD);
453         if (chain == NULL) {
454             ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_DIGEST);
455             return 0;
456         }
457         BIO_get_md_ctx(chain, &mtmp);
458         if (EVP_MD_CTX_get_type(mtmp) == nid
459             /*
460              * Workaround for broken implementations that use signature
461              * algorithm OID instead of digest.
462              */
463             || EVP_MD_get_pkey_type(EVP_MD_CTX_get0_md(mtmp)) == nid)
464             return EVP_MD_CTX_copy_ex(mctx, mtmp);
465         chain = BIO_next(chain);
466     }
467 }
468 
STACK_OF(CMS_CertificateChoices)469 static STACK_OF(CMS_CertificateChoices)
470 **cms_get0_certificate_choices(CMS_ContentInfo *cms)
471 {
472     switch (OBJ_obj2nid(cms->contentType)) {
473 
474     case NID_pkcs7_signed:
475         return &cms->d.signedData->certificates;
476 
477     case NID_pkcs7_enveloped:
478         if (cms->d.envelopedData->originatorInfo == NULL)
479             return NULL;
480         return &cms->d.envelopedData->originatorInfo->certificates;
481 
482     case NID_id_smime_ct_authEnvelopedData:
483         if (cms->d.authEnvelopedData->originatorInfo == NULL)
484             return NULL;
485         return &cms->d.authEnvelopedData->originatorInfo->certificates;
486 
487     default:
488         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
489         return NULL;
490 
491     }
492 }
493 
CMS_add0_CertificateChoices(CMS_ContentInfo * cms)494 CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
495 {
496     STACK_OF(CMS_CertificateChoices) **pcerts;
497     CMS_CertificateChoices *cch;
498 
499     pcerts = cms_get0_certificate_choices(cms);
500     if (pcerts == NULL)
501         return NULL;
502     if (*pcerts == NULL)
503         *pcerts = sk_CMS_CertificateChoices_new_null();
504     if (*pcerts == NULL)
505         return NULL;
506     cch = M_ASN1_new_of(CMS_CertificateChoices);
507     if (!cch)
508         return NULL;
509     if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
510         M_ASN1_free_of(cch, CMS_CertificateChoices);
511         return NULL;
512     }
513     return cch;
514 }
515 
CMS_add0_cert(CMS_ContentInfo * cms,X509 * cert)516 int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
517 {
518     CMS_CertificateChoices *cch;
519     STACK_OF(CMS_CertificateChoices) **pcerts;
520     int i;
521 
522     pcerts = cms_get0_certificate_choices(cms);
523     if (pcerts == NULL)
524         return 0;
525     for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
526         cch = sk_CMS_CertificateChoices_value(*pcerts, i);
527         if (cch->type == CMS_CERTCHOICE_CERT) {
528             if (X509_cmp(cch->d.certificate, cert) == 0) {
529                 X509_free(cert);
530                 return 1; /* cert already present */
531             }
532         }
533     }
534     cch = CMS_add0_CertificateChoices(cms);
535     if (!cch)
536         return 0;
537     cch->type = CMS_CERTCHOICE_CERT;
538     cch->d.certificate = cert;
539     return 1;
540 }
541 
CMS_add1_cert(CMS_ContentInfo * cms,X509 * cert)542 int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
543 {
544     if (!X509_up_ref(cert))
545         return 0;
546     if (CMS_add0_cert(cms, cert))
547         return 1;
548     X509_free(cert);
549     return 0;
550 }
551 
STACK_OF(CMS_RevocationInfoChoice)552 static STACK_OF(CMS_RevocationInfoChoice)
553 **cms_get0_revocation_choices(CMS_ContentInfo *cms)
554 {
555     switch (OBJ_obj2nid(cms->contentType)) {
556 
557     case NID_pkcs7_signed:
558         return &cms->d.signedData->crls;
559 
560     case NID_pkcs7_enveloped:
561         if (cms->d.envelopedData->originatorInfo == NULL)
562             return NULL;
563         return &cms->d.envelopedData->originatorInfo->crls;
564 
565     case NID_id_smime_ct_authEnvelopedData:
566         if (cms->d.authEnvelopedData->originatorInfo == NULL)
567             return NULL;
568         return &cms->d.authEnvelopedData->originatorInfo->crls;
569 
570     default:
571         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE);
572         return NULL;
573 
574     }
575 }
576 
CMS_add0_RevocationInfoChoice(CMS_ContentInfo * cms)577 CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
578 {
579     STACK_OF(CMS_RevocationInfoChoice) **pcrls;
580     CMS_RevocationInfoChoice *rch;
581 
582     pcrls = cms_get0_revocation_choices(cms);
583     if (pcrls == NULL)
584         return NULL;
585     if (*pcrls == NULL)
586         *pcrls = sk_CMS_RevocationInfoChoice_new_null();
587     if (*pcrls == NULL)
588         return NULL;
589     rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
590     if (rch == NULL)
591         return NULL;
592     if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
593         M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
594         return NULL;
595     }
596     return rch;
597 }
598 
CMS_add0_crl(CMS_ContentInfo * cms,X509_CRL * crl)599 int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
600 {
601     CMS_RevocationInfoChoice *rch = CMS_add0_RevocationInfoChoice(cms);
602 
603     if (rch == NULL)
604         return 0;
605     rch->type = CMS_REVCHOICE_CRL;
606     rch->d.crl = crl;
607     return 1;
608 }
609 
CMS_add1_crl(CMS_ContentInfo * cms,X509_CRL * crl)610 int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
611 {
612     if (!X509_CRL_up_ref(crl))
613         return 0;
614     if (CMS_add0_crl(cms, crl))
615         return 1;
616     X509_CRL_free(crl);
617     return 0;
618 }
619 
STACK_OF(X509)620 STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
621 {
622     STACK_OF(X509) *certs = NULL;
623     CMS_CertificateChoices *cch;
624     STACK_OF(CMS_CertificateChoices) **pcerts;
625     int i, n;
626 
627     pcerts = cms_get0_certificate_choices(cms);
628     if (pcerts == NULL)
629         return NULL;
630 
631     /* make sure to return NULL only on error */
632     n = sk_CMS_CertificateChoices_num(*pcerts);
633     if ((certs = sk_X509_new_reserve(NULL, n)) == NULL)
634         return NULL;
635 
636     for (i = 0; i < n; i++) {
637         cch = sk_CMS_CertificateChoices_value(*pcerts, i);
638         if (cch->type == 0) {
639             if (!ossl_x509_add_cert_new(&certs, cch->d.certificate,
640                                         X509_ADD_FLAG_UP_REF)) {
641                 OSSL_STACK_OF_X509_free(certs);
642                 return NULL;
643             }
644         }
645     }
646     return certs;
647 }
648 
STACK_OF(X509_CRL)649 STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
650 {
651     STACK_OF(X509_CRL) *crls = NULL;
652     STACK_OF(CMS_RevocationInfoChoice) **pcrls;
653     CMS_RevocationInfoChoice *rch;
654     int i, n;
655 
656     pcrls = cms_get0_revocation_choices(cms);
657     if (pcrls == NULL)
658         return NULL;
659 
660     /* make sure to return NULL only on error */
661     n = sk_CMS_RevocationInfoChoice_num(*pcrls);
662     if ((crls = sk_X509_CRL_new_reserve(NULL, n)) == NULL)
663         return NULL;
664 
665     for (i = 0; i < n; i++) {
666         rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
667         if (rch->type == 0) {
668             if (!sk_X509_CRL_push(crls, rch->d.crl)
669                     || !X509_CRL_up_ref(rch->d.crl)) {
670                 sk_X509_CRL_pop_free(crls, X509_CRL_free);
671                 return NULL;
672             }
673         }
674     }
675     return crls;
676 }
677 
ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber * ias,X509 * cert)678 int ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
679 {
680     int ret;
681     ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
682     if (ret)
683         return ret;
684     return ASN1_INTEGER_cmp(ias->serialNumber, X509_get0_serialNumber(cert));
685 }
686 
ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING * keyid,X509 * cert)687 int ossl_cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
688 {
689     const ASN1_OCTET_STRING *cert_keyid = X509_get0_subject_key_id(cert);
690 
691     if (cert_keyid == NULL)
692         return -1;
693     return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
694 }
695 
ossl_cms_set1_ias(CMS_IssuerAndSerialNumber ** pias,X509 * cert)696 int ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
697 {
698     CMS_IssuerAndSerialNumber *ias;
699     ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber);
700     if (!ias) {
701         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
702         goto err;
703     }
704     if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) {
705         ERR_raise(ERR_LIB_CMS, ERR_R_X509_LIB);
706         goto err;
707     }
708     if (!ASN1_STRING_copy(ias->serialNumber, X509_get0_serialNumber(cert))) {
709         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
710         goto err;
711     }
712     M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber);
713     *pias = ias;
714     return 1;
715  err:
716     M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber);
717     return 0;
718 }
719 
ossl_cms_set1_keyid(ASN1_OCTET_STRING ** pkeyid,X509 * cert)720 int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
721 {
722     ASN1_OCTET_STRING *keyid = NULL;
723     const ASN1_OCTET_STRING *cert_keyid;
724     cert_keyid = X509_get0_subject_key_id(cert);
725     if (cert_keyid == NULL) {
726         ERR_raise(ERR_LIB_CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID);
727         return 0;
728     }
729     keyid = ASN1_STRING_dup(cert_keyid);
730     if (!keyid) {
731         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
732         return 0;
733     }
734     ASN1_OCTET_STRING_free(*pkeyid);
735     *pkeyid = keyid;
736     return 1;
737 }
738