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