xref: /dragonfly/crypto/libressl/crypto/cms/cms_lib.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1 /* $OpenBSD: cms_lib.c,v 1.15 2021/11/01 20:53:08 tb Exp $ */
2 /*
3  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4  * project.
5  */
6 /* ====================================================================
7  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  */
54 
55 #include <openssl/asn1t.h>
56 #include <openssl/x509v3.h>
57 #include <openssl/err.h>
58 #include <openssl/pem.h>
59 #include <openssl/bio.h>
60 #include <openssl/asn1.h>
61 #include <openssl/cms.h>
62 
63 #include "cms_lcl.h"
64 #include "x509_lcl.h"
65 
66 CMS_ContentInfo *
d2i_CMS_ContentInfo(CMS_ContentInfo ** a,const unsigned char ** in,long len)67 d2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len)
68 {
69           return (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
70               &CMS_ContentInfo_it);
71 }
72 
73 int
i2d_CMS_ContentInfo(CMS_ContentInfo * a,unsigned char ** out)74 i2d_CMS_ContentInfo(CMS_ContentInfo *a, unsigned char **out)
75 {
76           return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ContentInfo_it);
77 }
78 
79 CMS_ContentInfo *
CMS_ContentInfo_new(void)80 CMS_ContentInfo_new(void)
81 {
82           return (CMS_ContentInfo *)ASN1_item_new(&CMS_ContentInfo_it);
83 }
84 
85 void
CMS_ContentInfo_free(CMS_ContentInfo * a)86 CMS_ContentInfo_free(CMS_ContentInfo *a)
87 {
88           ASN1_item_free((ASN1_VALUE *)a, &CMS_ContentInfo_it);
89 }
90 
91 int
CMS_ContentInfo_print_ctx(BIO * out,CMS_ContentInfo * x,int indent,const ASN1_PCTX * pctx)92 CMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const ASN1_PCTX *pctx)
93 {
94           return ASN1_item_print(out, (ASN1_VALUE *)x, indent,
95               &CMS_ContentInfo_it, pctx);
96 }
97 
98 const ASN1_OBJECT *
CMS_get0_type(const CMS_ContentInfo * cms)99 CMS_get0_type(const CMS_ContentInfo *cms)
100 {
101           return cms->contentType;
102 }
103 
104 CMS_ContentInfo *
cms_Data_create(void)105 cms_Data_create(void)
106 {
107           CMS_ContentInfo *cms;
108 
109           cms = CMS_ContentInfo_new();
110           if (cms != NULL) {
111                     cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
112                     /* Never detached */
113                     CMS_set_detached(cms, 0);
114           }
115           return cms;
116 }
117 
118 BIO *
cms_content_bio(CMS_ContentInfo * cms)119 cms_content_bio(CMS_ContentInfo *cms)
120 {
121           ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
122 
123           if (!pos)
124                     return NULL;
125           /* If content detached data goes nowhere: create NULL BIO */
126           if (!*pos)
127                     return BIO_new(BIO_s_null());
128           /*
129            * If content not detached and created return memory BIO
130            */
131           if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
132                     return BIO_new(BIO_s_mem());
133 
134           /* Else content was read in: return read only BIO for it */
135           return BIO_new_mem_buf((*pos)->data, (*pos)->length);
136 }
137 
138 BIO *
CMS_dataInit(CMS_ContentInfo * cms,BIO * icont)139 CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
140 {
141           BIO *cmsbio, *cont;
142 
143           if (icont)
144                     cont = icont;
145           else
146                     cont = cms_content_bio(cms);
147           if (!cont) {
148                     CMSerror(CMS_R_NO_CONTENT);
149                     return NULL;
150           }
151           switch (OBJ_obj2nid(cms->contentType)) {
152 
153           case NID_pkcs7_data:
154                     return cont;
155 
156           case NID_pkcs7_signed:
157                     cmsbio = cms_SignedData_init_bio(cms);
158                     break;
159 
160           case NID_pkcs7_digest:
161                     cmsbio = cms_DigestedData_init_bio(cms);
162                     break;
163 #ifdef ZLIB
164           case NID_id_smime_ct_compressedData:
165                     cmsbio = cms_CompressedData_init_bio(cms);
166                     break;
167 #endif
168 
169           case NID_pkcs7_encrypted:
170                     cmsbio = cms_EncryptedData_init_bio(cms);
171                     break;
172 
173           case NID_pkcs7_enveloped:
174                     cmsbio = cms_EnvelopedData_init_bio(cms);
175                     break;
176 
177           default:
178                     CMSerror(CMS_R_UNSUPPORTED_TYPE);
179                     return NULL;
180           }
181 
182           if (cmsbio)
183                     return BIO_push(cmsbio, cont);
184 
185           if (!icont)
186                     BIO_free(cont);
187 
188           return NULL;
189 }
190 
191 int
CMS_dataFinal(CMS_ContentInfo * cms,BIO * cmsbio)192 CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
193 {
194           ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
195 
196           if (!pos)
197                     return 0;
198           /* If embedded content find memory BIO and set content */
199           if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
200                     BIO *mbio;
201                     unsigned char *cont;
202                     long contlen;
203                     mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
204                     if (!mbio) {
205                               CMSerror(CMS_R_CONTENT_NOT_FOUND);
206                               return 0;
207                     }
208                     contlen = BIO_get_mem_data(mbio, &cont);
209                     /* Set bio as read only so its content can't be clobbered */
210                     BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
211                     BIO_set_mem_eof_return(mbio, 0);
212                     ASN1_STRING_set0(*pos, cont, contlen);
213                     (*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
214           }
215 
216           switch (OBJ_obj2nid(cms->contentType)) {
217 
218           case NID_pkcs7_data:
219           case NID_pkcs7_enveloped:
220           case NID_pkcs7_encrypted:
221           case NID_id_smime_ct_compressedData:
222                     /* Nothing to do */
223                     return 1;
224 
225           case NID_pkcs7_signed:
226                     return cms_SignedData_final(cms, cmsbio);
227 
228           case NID_pkcs7_digest:
229                     return cms_DigestedData_do_final(cms, cmsbio, 0);
230 
231           default:
232                     CMSerror(CMS_R_UNSUPPORTED_TYPE);
233                     return 0;
234           }
235 }
236 
237 /*
238  * Return an OCTET STRING pointer to content. This allows it to be accessed
239  * or set later.
240  */
241 
242 ASN1_OCTET_STRING **
CMS_get0_content(CMS_ContentInfo * cms)243 CMS_get0_content(CMS_ContentInfo *cms)
244 {
245           switch (OBJ_obj2nid(cms->contentType)) {
246           case NID_pkcs7_data:
247                     return &cms->d.data;
248 
249           case NID_pkcs7_signed:
250                     return &cms->d.signedData->encapContentInfo->eContent;
251 
252           case NID_pkcs7_enveloped:
253                     return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
254 
255           case NID_pkcs7_digest:
256                     return &cms->d.digestedData->encapContentInfo->eContent;
257 
258           case NID_pkcs7_encrypted:
259                     return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
260 
261           case NID_id_smime_ct_authData:
262                     return &cms->d.authenticatedData->encapContentInfo->eContent;
263 
264           case NID_id_smime_ct_compressedData:
265                     return &cms->d.compressedData->encapContentInfo->eContent;
266 
267           default:
268                     if (cms->d.other->type == V_ASN1_OCTET_STRING)
269                               return &cms->d.other->value.octet_string;
270                     CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
271                     return NULL;
272           }
273 }
274 
275 /*
276  * Return an ASN1_OBJECT pointer to content type. This allows it to be
277  * accessed or set later.
278  */
279 
280 static ASN1_OBJECT **
cms_get0_econtent_type(CMS_ContentInfo * cms)281 cms_get0_econtent_type(CMS_ContentInfo *cms)
282 {
283           switch (OBJ_obj2nid(cms->contentType)) {
284           case NID_pkcs7_signed:
285                     return &cms->d.signedData->encapContentInfo->eContentType;
286 
287           case NID_pkcs7_enveloped:
288                     return &cms->d.envelopedData->encryptedContentInfo->contentType;
289 
290           case NID_pkcs7_digest:
291                     return &cms->d.digestedData->encapContentInfo->eContentType;
292 
293           case NID_pkcs7_encrypted:
294                     return &cms->d.encryptedData->encryptedContentInfo->contentType;
295 
296           case NID_id_smime_ct_authData:
297                     return &cms->d.authenticatedData->encapContentInfo->eContentType;
298 
299           case NID_id_smime_ct_compressedData:
300                     return &cms->d.compressedData->encapContentInfo->eContentType;
301 
302           default:
303                     CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
304                     return NULL;
305           }
306 }
307 
308 const ASN1_OBJECT *
CMS_get0_eContentType(CMS_ContentInfo * cms)309 CMS_get0_eContentType(CMS_ContentInfo *cms)
310 {
311           ASN1_OBJECT **petype;
312 
313           petype = cms_get0_econtent_type(cms);
314           if (petype)
315                     return *petype;
316 
317           return NULL;
318 }
319 
320 int
CMS_set1_eContentType(CMS_ContentInfo * cms,const ASN1_OBJECT * oid)321 CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
322 {
323           ASN1_OBJECT **petype, *etype;
324 
325           petype = cms_get0_econtent_type(cms);
326           if (!petype)
327                     return 0;
328           if (!oid)
329                     return 1;
330           etype = OBJ_dup(oid);
331           if (!etype)
332                     return 0;
333           ASN1_OBJECT_free(*petype);
334           *petype = etype;
335 
336           return 1;
337 }
338 
339 int
CMS_is_detached(CMS_ContentInfo * cms)340 CMS_is_detached(CMS_ContentInfo *cms)
341 {
342           ASN1_OCTET_STRING **pos;
343 
344           pos = CMS_get0_content(cms);
345           if (!pos)
346                     return -1;
347           if (*pos)
348                     return 0;
349 
350           return 1;
351 }
352 
353 int
CMS_set_detached(CMS_ContentInfo * cms,int detached)354 CMS_set_detached(CMS_ContentInfo *cms, int detached)
355 {
356           ASN1_OCTET_STRING **pos;
357 
358           pos = CMS_get0_content(cms);
359           if (!pos)
360                     return 0;
361           if (detached) {
362                     ASN1_OCTET_STRING_free(*pos);
363                     *pos = NULL;
364                     return 1;
365           }
366           if (*pos == NULL)
367                     *pos = ASN1_OCTET_STRING_new();
368           if (*pos != NULL) {
369                     /*
370                      * NB: special flag to show content is created and not read in.
371                      */
372                     (*pos)->flags |= ASN1_STRING_FLAG_CONT;
373                     return 1;
374           }
375           CMSerror(ERR_R_MALLOC_FAILURE);
376 
377           return 0;
378 }
379 
380 /* Create a digest BIO from an X509_ALGOR structure */
381 
382 BIO *
cms_DigestAlgorithm_init_bio(X509_ALGOR * digestAlgorithm)383 cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
384 {
385           BIO *mdbio = NULL;
386           const ASN1_OBJECT *digestoid;
387           const EVP_MD *digest;
388 
389           X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
390           digest = EVP_get_digestbyobj(digestoid);
391           if (!digest) {
392                     CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM);
393                     goto err;
394           }
395           mdbio = BIO_new(BIO_f_md());
396           if (mdbio == NULL || !BIO_set_md(mdbio, digest)) {
397                     CMSerror(CMS_R_MD_BIO_INIT_ERROR);
398                     goto err;
399           }
400           return mdbio;
401 
402  err:
403           BIO_free(mdbio);
404 
405           return NULL;
406 }
407 
408 /* Locate a message digest content from a BIO chain based on SignerInfo */
409 
410 int
cms_DigestAlgorithm_find_ctx(EVP_MD_CTX * mctx,BIO * chain,X509_ALGOR * mdalg)411 cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg)
412 {
413           int nid;
414           const ASN1_OBJECT *mdoid;
415 
416           X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
417           nid = OBJ_obj2nid(mdoid);
418           /* Look for digest type to match signature */
419           for (;;) {
420                     EVP_MD_CTX *mtmp;
421                     chain = BIO_find_type(chain, BIO_TYPE_MD);
422                     if (chain == NULL) {
423                               CMSerror(CMS_R_NO_MATCHING_DIGEST);
424                               return 0;
425                     }
426                     BIO_get_md_ctx(chain, &mtmp);
427                     if (EVP_MD_CTX_type(mtmp) == nid
428                               /*
429                                * Workaround for broken implementations that use signature
430                                * algorithm OID instead of digest.
431                                */
432                               || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid)
433                               return EVP_MD_CTX_copy_ex(mctx, mtmp);
434                     chain = BIO_next(chain);
435           }
436 }
437 
STACK_OF(CMS_CertificateChoices)438 static STACK_OF(CMS_CertificateChoices) **
439 cms_get0_certificate_choices(CMS_ContentInfo *cms)
440 {
441           switch (OBJ_obj2nid(cms->contentType)) {
442           case NID_pkcs7_signed:
443                     return &cms->d.signedData->certificates;
444 
445           case NID_pkcs7_enveloped:
446                     if (cms->d.envelopedData->originatorInfo == NULL)
447                               return NULL;
448                     return &cms->d.envelopedData->originatorInfo->certificates;
449 
450           default:
451                     CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
452                     return NULL;
453           }
454 }
455 
456 CMS_CertificateChoices *
CMS_add0_CertificateChoices(CMS_ContentInfo * cms)457 CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
458 {
459           STACK_OF(CMS_CertificateChoices) **pcerts;
460           CMS_CertificateChoices *cch;
461 
462           pcerts = cms_get0_certificate_choices(cms);
463           if (!pcerts)
464                     return NULL;
465           if (!*pcerts)
466                     *pcerts = sk_CMS_CertificateChoices_new_null();
467           if (!*pcerts)
468                     return NULL;
469           cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it);
470           if (!cch)
471                     return NULL;
472           if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
473                     ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it);
474                     return NULL;
475           }
476 
477           return cch;
478 }
479 
480 int
CMS_add0_cert(CMS_ContentInfo * cms,X509 * cert)481 CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
482 {
483           CMS_CertificateChoices *cch;
484           STACK_OF(CMS_CertificateChoices) **pcerts;
485           int i;
486 
487           pcerts = cms_get0_certificate_choices(cms);
488           if (!pcerts)
489                     return 0;
490           for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
491                     cch = sk_CMS_CertificateChoices_value(*pcerts, i);
492                     if (cch->type == CMS_CERTCHOICE_CERT) {
493                               if (!X509_cmp(cch->d.certificate, cert)) {
494                                   CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT);
495                                   return 0;
496                               }
497                     }
498           }
499           cch = CMS_add0_CertificateChoices(cms);
500           if (!cch)
501                     return 0;
502           cch->type = CMS_CERTCHOICE_CERT;
503           cch->d.certificate = cert;
504 
505           return 1;
506 }
507 
508 int
CMS_add1_cert(CMS_ContentInfo * cms,X509 * cert)509 CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
510 {
511           int r;
512 
513           r = CMS_add0_cert(cms, cert);
514           if (r > 0)
515                     X509_up_ref(cert);
516 
517           return r;
518 }
519 
STACK_OF(CMS_RevocationInfoChoice)520 static STACK_OF(CMS_RevocationInfoChoice) **
521 cms_get0_revocation_choices(CMS_ContentInfo *cms)
522 {
523           switch (OBJ_obj2nid(cms->contentType)) {
524           case NID_pkcs7_signed:
525                     return &cms->d.signedData->crls;
526 
527           case NID_pkcs7_enveloped:
528                     if (cms->d.envelopedData->originatorInfo == NULL)
529                               return NULL;
530                     return &cms->d.envelopedData->originatorInfo->crls;
531 
532           default:
533                     CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
534                     return NULL;
535           }
536 }
537 
538 CMS_RevocationInfoChoice *
CMS_add0_RevocationInfoChoice(CMS_ContentInfo * cms)539 CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
540 {
541           STACK_OF(CMS_RevocationInfoChoice) **pcrls;
542           CMS_RevocationInfoChoice *rch;
543 
544           pcrls = cms_get0_revocation_choices(cms);
545           if (!pcrls)
546                     return NULL;
547           if (!*pcrls)
548                     *pcrls = sk_CMS_RevocationInfoChoice_new_null();
549           if (!*pcrls)
550                     return NULL;
551           rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it);
552           if (!rch)
553                     return NULL;
554           if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
555                     ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it);
556                     return NULL;
557           }
558 
559           return rch;
560 }
561 
562 int
CMS_add0_crl(CMS_ContentInfo * cms,X509_CRL * crl)563 CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
564 {
565           CMS_RevocationInfoChoice *rch;
566 
567           rch = CMS_add0_RevocationInfoChoice(cms);
568           if (!rch)
569                     return 0;
570           rch->type = CMS_REVCHOICE_CRL;
571           rch->d.crl = crl;
572 
573           return 1;
574 }
575 
576 int
CMS_add1_crl(CMS_ContentInfo * cms,X509_CRL * crl)577 CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl)
578 {
579           int r;
580 
581           r = CMS_add0_crl(cms, crl);
582           if (r > 0)
583                     X509_CRL_up_ref(crl);
584 
585           return r;
586 }
587 
STACK_OF(X509)588 STACK_OF(X509) *
589 CMS_get1_certs(CMS_ContentInfo *cms)
590 {
591           STACK_OF(X509) *certs = NULL;
592           CMS_CertificateChoices *cch;
593           STACK_OF(CMS_CertificateChoices) **pcerts;
594           int i;
595 
596           pcerts = cms_get0_certificate_choices(cms);
597           if (!pcerts)
598                     return NULL;
599           for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
600                     cch = sk_CMS_CertificateChoices_value(*pcerts, i);
601                     if (cch->type == 0) {
602                               if (!certs) {
603                                   certs = sk_X509_new_null();
604                                   if (!certs)
605                                       return NULL;
606                               }
607                               if (!sk_X509_push(certs, cch->d.certificate)) {
608                                   sk_X509_pop_free(certs, X509_free);
609                                   return NULL;
610                               }
611                               X509_up_ref(cch->d.certificate);
612                     }
613           }
614           return certs;
615 }
616 
STACK_OF(X509_CRL)617 STACK_OF(X509_CRL) *
618 CMS_get1_crls(CMS_ContentInfo *cms)
619 {
620           STACK_OF(X509_CRL) *crls = NULL;
621           STACK_OF(CMS_RevocationInfoChoice) **pcrls;
622           CMS_RevocationInfoChoice *rch;
623           int i;
624 
625           pcrls = cms_get0_revocation_choices(cms);
626           if (!pcrls)
627                     return NULL;
628           for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
629                     rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
630                     if (rch->type == 0) {
631                               if (!crls) {
632                                   crls = sk_X509_CRL_new_null();
633                                   if (!crls)
634                                       return NULL;
635                               }
636                               if (!sk_X509_CRL_push(crls, rch->d.crl)) {
637                                   sk_X509_CRL_pop_free(crls, X509_CRL_free);
638                                   return NULL;
639                               }
640                               X509_CRL_up_ref(rch->d.crl);
641                     }
642           }
643           return crls;
644 }
645 
646 static const ASN1_OCTET_STRING *
cms_X509_get0_subject_key_id(X509 * x)647 cms_X509_get0_subject_key_id(X509 *x)
648 {
649           /* Call for side-effect of computing hash and caching extensions */
650           X509_check_purpose(x, -1, -1);
651           return x->skid;
652 }
653 
654 int
cms_ias_cert_cmp(CMS_IssuerAndSerialNumber * ias,X509 * cert)655 cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert)
656 {
657           int ret;
658 
659           ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert));
660           if (ret)
661                     return ret;
662 
663           return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert));
664 }
665 
666 int
cms_keyid_cert_cmp(ASN1_OCTET_STRING * keyid,X509 * cert)667 cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
668 {
669           const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert);
670 
671           if (cert_keyid == NULL)
672                     return -1;
673 
674           return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
675 }
676 
677 int
cms_set1_ias(CMS_IssuerAndSerialNumber ** pias,X509 * cert)678 cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
679 {
680           CMS_IssuerAndSerialNumber *ias;
681 
682           ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it);
683           if (!ias)
684                     goto err;
685           if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert)))
686                     goto err;
687           if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert)))
688                     goto err;
689           ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it);
690           *pias = ias;
691 
692           return 1;
693 
694  err:
695           ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it);
696           CMSerror(ERR_R_MALLOC_FAILURE);
697 
698           return 0;
699 }
700 
701 int
cms_set1_keyid(ASN1_OCTET_STRING ** pkeyid,X509 * cert)702 cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
703 {
704           ASN1_OCTET_STRING *keyid = NULL;
705           const ASN1_OCTET_STRING *cert_keyid;
706 
707           cert_keyid = cms_X509_get0_subject_key_id(cert);
708           if (cert_keyid == NULL) {
709                     CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID);
710                     return 0;
711           }
712           keyid = ASN1_STRING_dup(cert_keyid);
713           if (!keyid) {
714                     CMSerror(ERR_R_MALLOC_FAILURE);
715                     return 0;
716           }
717           ASN1_OCTET_STRING_free(*pkeyid);
718           *pkeyid = keyid;
719 
720           return 1;
721 }
722