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