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