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 * 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 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 * 80 CMS_ContentInfo_new(void) 81 { 82 return (CMS_ContentInfo *)ASN1_item_new(&CMS_ContentInfo_it); 83 } 84 85 void 86 CMS_ContentInfo_free(CMS_ContentInfo *a) 87 { 88 ASN1_item_free((ASN1_VALUE *)a, &CMS_ContentInfo_it); 89 } 90 91 int 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 * 99 CMS_get0_type(const CMS_ContentInfo *cms) 100 { 101 return cms->contentType; 102 } 103 104 CMS_ContentInfo * 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 * 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 * 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 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 ** 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 ** 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 * 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 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 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 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 * 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 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 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 * 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 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 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 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 * 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 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 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 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 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 * 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 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 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 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 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