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