1 /* $OpenBSD: cms_lib.c,v 1.17 2023/06/11 05:35:43 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_local.h" 64 #include "x509_local.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 164 case NID_pkcs7_encrypted: 165 cmsbio = cms_EncryptedData_init_bio(cms); 166 break; 167 168 case NID_pkcs7_enveloped: 169 cmsbio = cms_EnvelopedData_init_bio(cms); 170 break; 171 172 default: 173 CMSerror(CMS_R_UNSUPPORTED_TYPE); 174 return NULL; 175 } 176 177 if (cmsbio) 178 return BIO_push(cmsbio, cont); 179 180 if (!icont) 181 BIO_free(cont); 182 183 return NULL; 184 } 185 186 int 187 CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) 188 { 189 ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 190 191 if (!pos) 192 return 0; 193 /* If embedded content find memory BIO and set content */ 194 if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { 195 BIO *mbio; 196 unsigned char *cont; 197 long contlen; 198 mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); 199 if (!mbio) { 200 CMSerror(CMS_R_CONTENT_NOT_FOUND); 201 return 0; 202 } 203 contlen = BIO_get_mem_data(mbio, &cont); 204 /* Set bio as read only so its content can't be clobbered */ 205 BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); 206 BIO_set_mem_eof_return(mbio, 0); 207 ASN1_STRING_set0(*pos, cont, contlen); 208 (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; 209 } 210 211 switch (OBJ_obj2nid(cms->contentType)) { 212 213 case NID_pkcs7_data: 214 case NID_pkcs7_enveloped: 215 case NID_pkcs7_encrypted: 216 case NID_id_smime_ct_compressedData: 217 /* Nothing to do */ 218 return 1; 219 220 case NID_pkcs7_signed: 221 return cms_SignedData_final(cms, cmsbio); 222 223 case NID_pkcs7_digest: 224 return cms_DigestedData_do_final(cms, cmsbio, 0); 225 226 default: 227 CMSerror(CMS_R_UNSUPPORTED_TYPE); 228 return 0; 229 } 230 } 231 232 /* 233 * Return an OCTET STRING pointer to content. This allows it to be accessed 234 * or set later. 235 */ 236 237 ASN1_OCTET_STRING ** 238 CMS_get0_content(CMS_ContentInfo *cms) 239 { 240 switch (OBJ_obj2nid(cms->contentType)) { 241 case NID_pkcs7_data: 242 return &cms->d.data; 243 244 case NID_pkcs7_signed: 245 return &cms->d.signedData->encapContentInfo->eContent; 246 247 case NID_pkcs7_enveloped: 248 return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; 249 250 case NID_pkcs7_digest: 251 return &cms->d.digestedData->encapContentInfo->eContent; 252 253 case NID_pkcs7_encrypted: 254 return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; 255 256 case NID_id_smime_ct_authData: 257 return &cms->d.authenticatedData->encapContentInfo->eContent; 258 259 case NID_id_smime_ct_compressedData: 260 return &cms->d.compressedData->encapContentInfo->eContent; 261 262 default: 263 if (cms->d.other->type == V_ASN1_OCTET_STRING) 264 return &cms->d.other->value.octet_string; 265 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 266 return NULL; 267 } 268 } 269 270 /* 271 * Return an ASN1_OBJECT pointer to content type. This allows it to be 272 * accessed or set later. 273 */ 274 275 static ASN1_OBJECT ** 276 cms_get0_econtent_type(CMS_ContentInfo *cms) 277 { 278 switch (OBJ_obj2nid(cms->contentType)) { 279 case NID_pkcs7_signed: 280 return &cms->d.signedData->encapContentInfo->eContentType; 281 282 case NID_pkcs7_enveloped: 283 return &cms->d.envelopedData->encryptedContentInfo->contentType; 284 285 case NID_pkcs7_digest: 286 return &cms->d.digestedData->encapContentInfo->eContentType; 287 288 case NID_pkcs7_encrypted: 289 return &cms->d.encryptedData->encryptedContentInfo->contentType; 290 291 case NID_id_smime_ct_authData: 292 return &cms->d.authenticatedData->encapContentInfo->eContentType; 293 294 case NID_id_smime_ct_compressedData: 295 return &cms->d.compressedData->encapContentInfo->eContentType; 296 297 default: 298 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 299 return NULL; 300 } 301 } 302 303 const ASN1_OBJECT * 304 CMS_get0_eContentType(CMS_ContentInfo *cms) 305 { 306 ASN1_OBJECT **petype; 307 308 petype = cms_get0_econtent_type(cms); 309 if (petype) 310 return *petype; 311 312 return NULL; 313 } 314 315 int 316 CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) 317 { 318 ASN1_OBJECT **petype, *etype; 319 320 petype = cms_get0_econtent_type(cms); 321 if (!petype) 322 return 0; 323 if (!oid) 324 return 1; 325 etype = OBJ_dup(oid); 326 if (!etype) 327 return 0; 328 ASN1_OBJECT_free(*petype); 329 *petype = etype; 330 331 return 1; 332 } 333 334 int 335 CMS_is_detached(CMS_ContentInfo *cms) 336 { 337 ASN1_OCTET_STRING **pos; 338 339 pos = CMS_get0_content(cms); 340 if (!pos) 341 return -1; 342 if (*pos) 343 return 0; 344 345 return 1; 346 } 347 348 int 349 CMS_set_detached(CMS_ContentInfo *cms, int detached) 350 { 351 ASN1_OCTET_STRING **pos; 352 353 pos = CMS_get0_content(cms); 354 if (!pos) 355 return 0; 356 if (detached) { 357 ASN1_OCTET_STRING_free(*pos); 358 *pos = NULL; 359 return 1; 360 } 361 if (*pos == NULL) 362 *pos = ASN1_OCTET_STRING_new(); 363 if (*pos != NULL) { 364 /* 365 * NB: special flag to show content is created and not read in. 366 */ 367 (*pos)->flags |= ASN1_STRING_FLAG_CONT; 368 return 1; 369 } 370 CMSerror(ERR_R_MALLOC_FAILURE); 371 372 return 0; 373 } 374 375 /* Create a digest BIO from an X509_ALGOR structure */ 376 377 BIO * 378 cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) 379 { 380 BIO *mdbio = NULL; 381 const ASN1_OBJECT *digestoid; 382 const EVP_MD *digest; 383 384 X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); 385 digest = EVP_get_digestbyobj(digestoid); 386 if (!digest) { 387 CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM); 388 goto err; 389 } 390 mdbio = BIO_new(BIO_f_md()); 391 if (mdbio == NULL || !BIO_set_md(mdbio, digest)) { 392 CMSerror(CMS_R_MD_BIO_INIT_ERROR); 393 goto err; 394 } 395 return mdbio; 396 397 err: 398 BIO_free(mdbio); 399 400 return NULL; 401 } 402 403 /* Locate a message digest content from a BIO chain based on SignerInfo */ 404 405 int 406 cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg) 407 { 408 int nid; 409 const ASN1_OBJECT *mdoid; 410 411 X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); 412 nid = OBJ_obj2nid(mdoid); 413 /* Look for digest type to match signature */ 414 for (;;) { 415 EVP_MD_CTX *mtmp; 416 chain = BIO_find_type(chain, BIO_TYPE_MD); 417 if (chain == NULL) { 418 CMSerror(CMS_R_NO_MATCHING_DIGEST); 419 return 0; 420 } 421 BIO_get_md_ctx(chain, &mtmp); 422 if (EVP_MD_CTX_type(mtmp) == nid 423 /* 424 * Workaround for broken implementations that use signature 425 * algorithm OID instead of digest. 426 */ 427 || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) 428 return EVP_MD_CTX_copy_ex(mctx, mtmp); 429 chain = BIO_next(chain); 430 } 431 } 432 433 static STACK_OF(CMS_CertificateChoices) ** 434 cms_get0_certificate_choices(CMS_ContentInfo *cms) 435 { 436 switch (OBJ_obj2nid(cms->contentType)) { 437 case NID_pkcs7_signed: 438 return &cms->d.signedData->certificates; 439 440 case NID_pkcs7_enveloped: 441 if (cms->d.envelopedData->originatorInfo == NULL) 442 return NULL; 443 return &cms->d.envelopedData->originatorInfo->certificates; 444 445 default: 446 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 447 return NULL; 448 } 449 } 450 451 CMS_CertificateChoices * 452 CMS_add0_CertificateChoices(CMS_ContentInfo *cms) 453 { 454 STACK_OF(CMS_CertificateChoices) **pcerts; 455 CMS_CertificateChoices *cch; 456 457 pcerts = cms_get0_certificate_choices(cms); 458 if (!pcerts) 459 return NULL; 460 if (!*pcerts) 461 *pcerts = sk_CMS_CertificateChoices_new_null(); 462 if (!*pcerts) 463 return NULL; 464 cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it); 465 if (!cch) 466 return NULL; 467 if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { 468 ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it); 469 return NULL; 470 } 471 472 return cch; 473 } 474 475 int 476 CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 477 { 478 CMS_CertificateChoices *cch; 479 STACK_OF(CMS_CertificateChoices) **pcerts; 480 int i; 481 482 pcerts = cms_get0_certificate_choices(cms); 483 if (!pcerts) 484 return 0; 485 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 486 cch = sk_CMS_CertificateChoices_value(*pcerts, i); 487 if (cch->type == CMS_CERTCHOICE_CERT) { 488 if (!X509_cmp(cch->d.certificate, cert)) { 489 CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT); 490 return 0; 491 } 492 } 493 } 494 cch = CMS_add0_CertificateChoices(cms); 495 if (!cch) 496 return 0; 497 cch->type = CMS_CERTCHOICE_CERT; 498 cch->d.certificate = cert; 499 500 return 1; 501 } 502 503 int 504 CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) 505 { 506 int r; 507 508 r = CMS_add0_cert(cms, cert); 509 if (r > 0) 510 X509_up_ref(cert); 511 512 return r; 513 } 514 515 static STACK_OF(CMS_RevocationInfoChoice) ** 516 cms_get0_revocation_choices(CMS_ContentInfo *cms) 517 { 518 switch (OBJ_obj2nid(cms->contentType)) { 519 case NID_pkcs7_signed: 520 return &cms->d.signedData->crls; 521 522 case NID_pkcs7_enveloped: 523 if (cms->d.envelopedData->originatorInfo == NULL) 524 return NULL; 525 return &cms->d.envelopedData->originatorInfo->crls; 526 527 default: 528 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 529 return NULL; 530 } 531 } 532 533 CMS_RevocationInfoChoice * 534 CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) 535 { 536 STACK_OF(CMS_RevocationInfoChoice) **pcrls; 537 CMS_RevocationInfoChoice *rch; 538 539 pcrls = cms_get0_revocation_choices(cms); 540 if (!pcrls) 541 return NULL; 542 if (!*pcrls) 543 *pcrls = sk_CMS_RevocationInfoChoice_new_null(); 544 if (!*pcrls) 545 return NULL; 546 rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it); 547 if (!rch) 548 return NULL; 549 if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { 550 ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it); 551 return NULL; 552 } 553 554 return rch; 555 } 556 557 int 558 CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) 559 { 560 CMS_RevocationInfoChoice *rch; 561 562 rch = CMS_add0_RevocationInfoChoice(cms); 563 if (!rch) 564 return 0; 565 rch->type = CMS_REVCHOICE_CRL; 566 rch->d.crl = crl; 567 568 return 1; 569 } 570 571 int 572 CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) 573 { 574 int r; 575 576 r = CMS_add0_crl(cms, crl); 577 if (r > 0) 578 X509_CRL_up_ref(crl); 579 580 return r; 581 } 582 583 STACK_OF(X509) * 584 CMS_get1_certs(CMS_ContentInfo *cms) 585 { 586 STACK_OF(X509) *certs = NULL; 587 CMS_CertificateChoices *cch; 588 STACK_OF(CMS_CertificateChoices) **pcerts; 589 int i; 590 591 pcerts = cms_get0_certificate_choices(cms); 592 if (!pcerts) 593 return NULL; 594 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 595 cch = sk_CMS_CertificateChoices_value(*pcerts, i); 596 if (cch->type == 0) { 597 if (!certs) { 598 certs = sk_X509_new_null(); 599 if (!certs) 600 return NULL; 601 } 602 if (!sk_X509_push(certs, cch->d.certificate)) { 603 sk_X509_pop_free(certs, X509_free); 604 return NULL; 605 } 606 X509_up_ref(cch->d.certificate); 607 } 608 } 609 return certs; 610 } 611 612 STACK_OF(X509_CRL) * 613 CMS_get1_crls(CMS_ContentInfo *cms) 614 { 615 STACK_OF(X509_CRL) *crls = NULL; 616 STACK_OF(CMS_RevocationInfoChoice) **pcrls; 617 CMS_RevocationInfoChoice *rch; 618 int i; 619 620 pcrls = cms_get0_revocation_choices(cms); 621 if (!pcrls) 622 return NULL; 623 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { 624 rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); 625 if (rch->type == 0) { 626 if (!crls) { 627 crls = sk_X509_CRL_new_null(); 628 if (!crls) 629 return NULL; 630 } 631 if (!sk_X509_CRL_push(crls, rch->d.crl)) { 632 sk_X509_CRL_pop_free(crls, X509_CRL_free); 633 return NULL; 634 } 635 X509_CRL_up_ref(rch->d.crl); 636 } 637 } 638 return crls; 639 } 640 641 static const ASN1_OCTET_STRING * 642 cms_X509_get0_subject_key_id(X509 *x) 643 { 644 /* Call for side-effect of computing hash and caching extensions */ 645 X509_check_purpose(x, -1, -1); 646 return x->skid; 647 } 648 649 int 650 cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert) 651 { 652 int ret; 653 654 ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert)); 655 if (ret) 656 return ret; 657 658 return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert)); 659 } 660 661 int 662 cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert) 663 { 664 const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert); 665 666 if (cert_keyid == NULL) 667 return -1; 668 669 return ASN1_OCTET_STRING_cmp(keyid, cert_keyid); 670 } 671 672 int 673 cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) 674 { 675 CMS_IssuerAndSerialNumber *ias; 676 677 ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it); 678 if (!ias) 679 goto err; 680 if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) 681 goto err; 682 if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert))) 683 goto err; 684 ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it); 685 *pias = ias; 686 687 return 1; 688 689 err: 690 ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it); 691 CMSerror(ERR_R_MALLOC_FAILURE); 692 693 return 0; 694 } 695 696 int 697 cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) 698 { 699 ASN1_OCTET_STRING *keyid = NULL; 700 const ASN1_OCTET_STRING *cert_keyid; 701 702 cert_keyid = cms_X509_get0_subject_key_id(cert); 703 if (cert_keyid == NULL) { 704 CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID); 705 return 0; 706 } 707 keyid = ASN1_STRING_dup(cert_keyid); 708 if (!keyid) { 709 CMSerror(ERR_R_MALLOC_FAILURE); 710 return 0; 711 } 712 ASN1_OCTET_STRING_free(*pkeyid); 713 *pkeyid = keyid; 714 715 return 1; 716 } 717