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