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