9fc8453d9925d9fab667d53b894580ad7ea5c529
[openssl.git] / crypto / cms / cms_lib.c
1 /*
2  * Copyright 2008-2020 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 "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 DEFINE_STACK_OF(CMS_RevocationInfoChoice)
25 DEFINE_STACK_OF(X509)
26 DEFINE_STACK_OF(X509_CRL)
27
28 IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
29
30 CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
31                                      const unsigned char **in, long len)
32 {
33     CMS_ContentInfo *ci;
34
35     ci = (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
36                                           (CMS_ContentInfo_it()));
37     if (ci != NULL && a != NULL)
38         cms_resolve_libctx(ci);
39     return ci;
40 }
41
42 int i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out)
43 {
44     return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it()));
45 }
46
47 CMS_ContentInfo *CMS_ContentInfo_new_with_libctx(OPENSSL_CTX *libctx,
48                                                  const char *propq)
49 {
50     CMS_ContentInfo *ci;
51
52     ci = (CMS_ContentInfo *)ASN1_item_new(ASN1_ITEM_rptr(CMS_ContentInfo));
53     if (ci != NULL) {
54         ci->ctx.libctx = libctx;
55         ci->ctx.propq = NULL;
56         if (propq != NULL) {
57             ci->ctx.propq = OPENSSL_strdup(propq);
58             if (ci->ctx.propq == NULL) {
59                 CMS_ContentInfo_free(ci);
60                 ci = NULL;
61                 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
62             }
63         }
64     }
65     return ci;
66 }
67
68 CMS_ContentInfo *CMS_ContentInfo_new(void)
69 {
70     return CMS_ContentInfo_new_with_libctx(NULL, NULL);
71 }
72
73 void CMS_ContentInfo_free(CMS_ContentInfo *cms)
74 {
75     if (cms != NULL) {
76         OPENSSL_free(cms->ctx.propq);
77         ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo));
78     }
79 }
80
81 const CMS_CTX *cms_get0_cmsctx(const CMS_ContentInfo *cms)
82 {
83     return cms != NULL ? &cms->ctx : NULL;
84 }
85
86 OPENSSL_CTX *cms_ctx_get0_libctx(const CMS_CTX *ctx)
87 {
88     return ctx->libctx;
89 }
90
91 const char *cms_ctx_get0_propq(const CMS_CTX *ctx)
92 {
93     return ctx->propq;
94 }
95
96 void cms_resolve_libctx(CMS_ContentInfo *ci)
97 {
98     int i;
99     CMS_CertificateChoices *cch;
100     STACK_OF(CMS_CertificateChoices) **pcerts;
101     const CMS_CTX *ctx;
102
103     if (ci == NULL)
104         return;
105
106     ctx = cms_get0_cmsctx(ci);
107     cms_SignerInfos_set_cmsctx(ci);
108     cms_RecipientInfos_set_cmsctx(ci);
109
110     pcerts = cms_get0_certificate_choices(ci);
111     if (pcerts != NULL) {
112         for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
113             cch = sk_CMS_CertificateChoices_value(*pcerts, i);
114             if (cch->type == CMS_CERTCHOICE_CERT)
115                 x509_set0_libctx(cch->d.certificate, ctx->libctx, ctx->propq);
116         }
117     }
118 }
119
120 const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms)
121 {
122     return cms->contentType;
123 }
124
125 CMS_ContentInfo *cms_Data_create(OPENSSL_CTX *libctx, const char *propq)
126 {
127     CMS_ContentInfo *cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
128
129     if (cms != NULL) {
130         cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
131         /* Never detached */
132         CMS_set_detached(cms, 0);
133     }
134     return cms;
135 }
136
137 BIO *cms_content_bio(CMS_ContentInfo *cms)
138 {
139     ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
140
141     if (pos == NULL)
142         return NULL;
143     /* If content detached data goes nowhere: create NULL BIO */
144     if (*pos == NULL)
145         return BIO_new(BIO_s_null());
146     /*
147      * If content not detached and created return memory BIO
148      */
149     if (*pos == NULL || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
150         return BIO_new(BIO_s_mem());
151     /* Else content was read in: return read only BIO for it */
152     return BIO_new_mem_buf((*pos)->data, (*pos)->length);
153 }
154
155 BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
156 {
157     BIO *cmsbio, *cont;
158     if (icont)
159         cont = icont;
160     else
161         cont = cms_content_bio(cms);
162     if (!cont) {
163         CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT);
164         return NULL;
165     }
166     switch (OBJ_obj2nid(cms->contentType)) {
167
168     case NID_pkcs7_data:
169         return cont;
170
171     case NID_pkcs7_signed:
172         cmsbio = cms_SignedData_init_bio(cms);
173         break;
174
175     case NID_pkcs7_digest:
176         cmsbio = cms_DigestedData_init_bio(cms);
177         break;
178 #ifdef ZLIB
179     case NID_id_smime_ct_compressedData:
180         cmsbio = cms_CompressedData_init_bio(cms);
181         break;
182 #endif
183
184     case NID_pkcs7_encrypted:
185         cmsbio = cms_EncryptedData_init_bio(cms);
186         break;
187
188     case NID_pkcs7_enveloped:
189         cmsbio = cms_EnvelopedData_init_bio(cms);
190         break;
191
192     case NID_id_smime_ct_authEnvelopedData:
193         cmsbio = cms_AuthEnvelopedData_init_bio(cms);
194         break;
195
196     default:
197         CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
198         goto err;
199     }
200
201     if (cmsbio)
202         return BIO_push(cmsbio, cont);
203 err:
204     if (!icont)
205         BIO_free(cont);
206     return NULL;
207
208 }
209
210 /* unfortunately cannot constify SMIME_write_ASN1() due to this function */
211 int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
212 {
213     ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
214
215     if (pos == NULL)
216         return 0;
217     /* If embedded content find memory BIO and set content */
218     if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
219         BIO *mbio;
220         unsigned char *cont;
221         long contlen;
222         mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
223         if (!mbio) {
224             CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND);
225             return 0;
226         }
227         contlen = BIO_get_mem_data(mbio, &cont);
228         /* Set bio as read only so its content can't be clobbered */
229         BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
230         BIO_set_mem_eof_return(mbio, 0);
231         ASN1_STRING_set0(*pos, cont, contlen);
232         (*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
233     }
234
235     switch (OBJ_obj2nid(cms->contentType)) {
236
237     case NID_pkcs7_data:
238     case NID_pkcs7_encrypted:
239     case NID_id_smime_ct_compressedData:
240         /* Nothing to do */
241         return 1;
242
243     case NID_pkcs7_enveloped:
244         return cms_EnvelopedData_final(cms, cmsbio);
245
246     case NID_id_smime_ct_authEnvelopedData:
247         return cms_AuthEnvelopedData_final(cms, cmsbio);
248
249     case NID_pkcs7_signed:
250         return cms_SignedData_final(cms, cmsbio);
251
252     case NID_pkcs7_digest:
253         return cms_DigestedData_do_final(cms, cmsbio, 0);
254
255     default:
256         CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE);
257         return 0;
258     }
259 }
260
261 /*
262  * Return an OCTET STRING pointer to content. This allows it to be accessed
263  * or set later.
264  */
265
266 ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
267 {
268     switch (OBJ_obj2nid(cms->contentType)) {
269
270     case NID_pkcs7_data:
271         return &cms->d.data;
272
273     case NID_pkcs7_signed:
274         return &cms->d.signedData->encapContentInfo->eContent;
275
276     case NID_pkcs7_enveloped:
277         return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
278
279     case NID_pkcs7_digest:
280         return &cms->d.digestedData->encapContentInfo->eContent;
281
282     case NID_pkcs7_encrypted:
283         return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
284
285     case NID_id_smime_ct_authEnvelopedData:
286         return &cms->d.authEnvelopedData->authEncryptedContentInfo
287                                         ->encryptedContent;
288
289     case NID_id_smime_ct_authData:
290         return &cms->d.authenticatedData->encapContentInfo->eContent;
291
292     case NID_id_smime_ct_compressedData:
293         return &cms->d.compressedData->encapContentInfo->eContent;
294
295     default:
296         if (cms->d.other->type == V_ASN1_OCTET_STRING)
297             return &cms->d.other->value.octet_string;
298         CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE);
299         return NULL;
300
301     }
302 }
303
304 /*
305  * Return an ASN1_OBJECT pointer to content type. This allows it to be
306  * accessed or set later.
307  */
308
309 static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
310 {
311     switch (OBJ_obj2nid(cms->contentType)) {
312
313     case NID_pkcs7_signed:
314         return &cms->d.signedData->encapContentInfo->eContentType;
315
316     case NID_pkcs7_enveloped:
317         return &cms->d.envelopedData->encryptedContentInfo->contentType;
318
319     case NID_pkcs7_digest:
320         return &cms->d.digestedData->encapContentInfo->eContentType;
321
322     case NID_pkcs7_encrypted:
323         return &cms->d.encryptedData->encryptedContentInfo->contentType;
324
325     case NID_id_smime_ct_authEnvelopedData:
326         return &cms->d.authEnvelopedData->authEncryptedContentInfo
327                                         ->contentType;
328     case NID_id_smime_ct_authData:
329         return &cms->d.authenticatedData->encapContentInfo->eContentType;
330
331     case NID_id_smime_ct_compressedData:
332         return &cms->d.compressedData->encapContentInfo->eContentType;
333
334     default:
335         CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE);
336         return NULL;
337
338     }
339 }
340
341 const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
342 {
343     ASN1_OBJECT **petype;
344     petype = cms_get0_econtent_type(cms);
345     if (petype)
346         return *petype;
347     return NULL;
348 }
349
350 int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
351 {
352     ASN1_OBJECT **petype, *etype;
353
354     petype = cms_get0_econtent_type(cms);
355     if (petype == NULL)
356         return 0;
357     if (oid == NULL)
358         return 1;
359     etype = OBJ_dup(oid);
360     if (etype == NULL)
361         return 0;
362     ASN1_OBJECT_free(*petype);
363     *petype = etype;
364     return 1;
365 }
366
367 int CMS_is_detached(CMS_ContentInfo *cms)
368 {
369     ASN1_OCTET_STRING **pos;
370
371     pos = CMS_get0_content(cms);
372     if (pos == NULL)
373         return -1;
374     if (*pos != NULL)
375         return 0;
376     return 1;
377 }
378
379 int CMS_set_detached(CMS_ContentInfo *cms, int detached)
380 {
381     ASN1_OCTET_STRING **pos;
382
383     pos = CMS_get0_content(cms);
384     if (pos == NULL)
385         return 0;
386     if (detached) {
387         ASN1_OCTET_STRING_free(*pos);
388         *pos = NULL;
389         return 1;
390     }
391     if (*pos == NULL)
392         *pos = ASN1_OCTET_STRING_new();
393     if (*pos != NULL) {
394         /*
395          * NB: special flag to show content is created and not read in.
396          */
397         (*pos)->flags |= ASN1_STRING_FLAG_CONT;
398         return 1;
399     }
400     CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE);
401     return 0;
402 }
403
404 /* Create a digest BIO from an X509_ALGOR structure */
405
406 BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
407                                   const CMS_CTX *ctx)
408 {
409     BIO *mdbio = NULL;
410     const ASN1_OBJECT *digestoid;
411     const EVP_MD *digest = NULL;
412     EVP_MD *fetched_digest = NULL;
413     const char *alg;
414
415     X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
416     alg = OBJ_nid2sn(OBJ_obj2nid(digestoid));
417
418     (void)ERR_set_mark();
419     fetched_digest = EVP_MD_fetch(ctx->libctx, alg, ctx->propq);
420
421     if (fetched_digest != NULL)
422         digest = fetched_digest;
423     else
424         digest = EVP_get_digestbyobj(digestoid);
425     if (digest == NULL) {
426         (void)ERR_clear_last_mark();
427         CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
428                CMS_R_UNKNOWN_DIGEST_ALGORITHM);
429         goto err;
430     }
431     (void)ERR_pop_to_mark();
432
433     mdbio = BIO_new(BIO_f_md());
434     if (mdbio == NULL || !BIO_set_md(mdbio, digest)) {
435         CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR);
436         goto err;
437     }
438     EVP_MD_free(fetched_digest);
439     return mdbio;
440  err:
441     EVP_MD_free(fetched_digest);
442     BIO_free(mdbio);
443     return NULL;
444 }
445
446 /* Locate a message digest content from a BIO chain based on SignerInfo */
447
448 int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
449                                  X509_ALGOR *mdalg)
450 {
451     int nid;
452     const ASN1_OBJECT *mdoid;
453     X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
454     nid = OBJ_obj2nid(mdoid);
455     /* Look for digest type to match signature */
456     for (;;) {
457         EVP_MD_CTX *mtmp;
458         chain = BIO_find_type(chain, BIO_TYPE_MD);
459         if (chain == NULL) {
460             CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX,
461                    CMS_R_NO_MATCHING_DIGEST);
462             return 0;
463         }
464         BIO_get_md_ctx(chain, &mtmp);
465         if (EVP_MD_CTX_type(mtmp) == nid
466             /*
467              * Workaround for broken implementations that use signature
468              * algorithm OID instead of digest.
469              */
470             || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
471             return EVP_MD_CTX_copy_ex(mctx, mtmp);
472         chain = BIO_next(chain);
473     }
474 }
475
476 static STACK_OF(CMS_CertificateChoices)
477 **cms_get0_certificate_choices(CMS_ContentInfo *cms)
478 {
479     switch (OBJ_obj2nid(cms->contentType)) {
480
481     case NID_pkcs7_signed:
482         return &cms->d.signedData->certificates;
483
484     case NID_pkcs7_enveloped:
485         if (cms->d.envelopedData->originatorInfo == NULL)
486             return NULL;
487         return &cms->d.envelopedData->originatorInfo->certificates;
488
489     case NID_id_smime_ct_authEnvelopedData:
490         if (cms->d.authEnvelopedData->originatorInfo == NULL)
491             return NULL;
492         return &cms->d.authEnvelopedData->originatorInfo->certificates;
493
494     default:
495         CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES,
496                CMS_R_UNSUPPORTED_CONTENT_TYPE);
497         return NULL;
498
499     }
500 }
501
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
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                 CMSerr(CMS_F_CMS_ADD0_CERT,
538                        CMS_R_CERTIFICATE_ALREADY_PRESENT);
539                 return 0;
540             }
541         }
542     }
543     cch = CMS_add0_CertificateChoices(cms);
544     if (!cch)
545         return 0;
546     cch->type = CMS_CERTCHOICE_CERT;
547     cch->d.certificate = cert;
548     return 1;
549 }
550
551 int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
552 {
553     int r;
554     r = CMS_add0_cert(cms, cert);
555     if (r > 0)
556         X509_up_ref(cert);
557     return r;
558 }
559
560 static STACK_OF(CMS_RevocationInfoChoice)
561 **cms_get0_revocation_choices(CMS_ContentInfo *cms)
562 {
563     switch (OBJ_obj2nid(cms->contentType)) {
564
565     case NID_pkcs7_signed:
566         return &cms->d.signedData->crls;
567
568     case NID_pkcs7_enveloped:
569         if (cms->d.envelopedData->originatorInfo == NULL)
570             return NULL;
571         return &cms->d.envelopedData->originatorInfo->crls;
572
573     case NID_id_smime_ct_authEnvelopedData:
574         if (cms->d.authEnvelopedData->originatorInfo == NULL)
575             return NULL;
576         return &cms->d.authEnvelopedData->originatorInfo->crls;
577
578     default:
579         CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES,
580                CMS_R_UNSUPPORTED_CONTENT_TYPE);
581         return NULL;
582
583     }
584 }
585
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
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
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
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 (!X509_add_cert_new(&certs, cch->d.certificate,
642                                    X509_ADD_FLAG_UP_REF)) {
643                 sk_X509_pop_free(certs, X509_free);
644                 return NULL;
645             }
646         }
647     }
648     return certs;
649
650 }
651
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
680 int 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
689 int 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
698 int 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     CMSerr(CMS_F_CMS_SET1_IAS, ERR_R_MALLOC_FAILURE);
714     return 0;
715 }
716
717 int 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         CMSerr(CMS_F_CMS_SET1_KEYID, CMS_R_CERTIFICATE_HAS_NO_KEYID);
724         return 0;
725     }
726     keyid = ASN1_STRING_dup(cert_keyid);
727     if (!keyid) {
728         CMSerr(CMS_F_CMS_SET1_KEYID, ERR_R_MALLOC_FAILURE);
729         return 0;
730     }
731     ASN1_OCTET_STRING_free(*pkeyid);
732     *pkeyid = keyid;
733     return 1;
734 }