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