1272343Sngie/* $OpenBSD: cms_lib.c,v 1.25 2024/03/30 01:53:05 joshua Exp $ */ 2272343Sngie/* 3272343Sngie * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4272343Sngie * project. 5272343Sngie */ 6272343Sngie/* ==================================================================== 7272343Sngie * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8272343Sngie * 9272343Sngie * Redistribution and use in source and binary forms, with or without 10272343Sngie * modification, are permitted provided that the following conditions 11272343Sngie * are met: 12272343Sngie * 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 16272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 17272343Sngie * notice, this list of conditions and the following disclaimer in 18272343Sngie * the documentation and/or other materials provided with the 19272343Sngie * distribution. 20272343Sngie * 21272343Sngie * 3. All advertising materials mentioning features or use of this 22272343Sngie * software must display the following acknowledgment: 23272343Sngie * "This product includes software developed by the OpenSSL Project 24272343Sngie * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25272343Sngie * 26272343Sngie * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27272343Sngie * endorse or promote products derived from this software without 28272343Sngie * prior written permission. For written permission, please contact 29272343Sngie * licensing@OpenSSL.org. 30272343Sngie * 31272343Sngie * 5. Products derived from this software may not be called "OpenSSL" 32272343Sngie * nor may "OpenSSL" appear in their names without prior written 33272343Sngie * permission of the OpenSSL Project. 34272343Sngie * 35272343Sngie * 6. Redistributions of any form whatsoever must retain the following 36272343Sngie * acknowledgment: 37272343Sngie * "This product includes software developed by the OpenSSL Project 38272343Sngie * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39272343Sngie * 40272343Sngie * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41272343Sngie * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44272343Sngie * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45272343Sngie * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46272343Sngie * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47272343Sngie * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49272343Sngie * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51272343Sngie * OF THE POSSIBILITY OF SUCH DAMAGE. 52272343Sngie * ==================================================================== 53272343Sngie */ 54272343Sngie 55272343Sngie#include <openssl/asn1t.h> 56272343Sngie#include <openssl/x509v3.h> 57272343Sngie#include <openssl/err.h> 58272343Sngie#include <openssl/pem.h> 59272343Sngie#include <openssl/bio.h> 60272343Sngie#include <openssl/asn1.h> 61272343Sngie#include <openssl/cms.h> 62272343Sngie 63272343Sngie#include "cms_local.h" 64272343Sngie#include "x509_local.h" 65272343Sngie 66272343SngieCMS_ContentInfo * 67272343Sngied2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len) 68272343Sngie{ 69272343Sngie return (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 70272343Sngie &CMS_ContentInfo_it); 71272343Sngie} 72272343SngieLCRYPTO_ALIAS(d2i_CMS_ContentInfo); 73272343Sngie 74272343Sngieint 75272343Sngiei2d_CMS_ContentInfo(CMS_ContentInfo *a, unsigned char **out) 76272343Sngie{ 77272343Sngie return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ContentInfo_it); 78272343Sngie} 79272343SngieLCRYPTO_ALIAS(i2d_CMS_ContentInfo); 80272343Sngie 81272343SngieCMS_ContentInfo * 82272343SngieCMS_ContentInfo_new(void) 83272343Sngie{ 84272343Sngie return (CMS_ContentInfo *)ASN1_item_new(&CMS_ContentInfo_it); 85272343Sngie} 86272343SngieLCRYPTO_ALIAS(CMS_ContentInfo_new); 87272343Sngie 88272343Sngievoid 89272343SngieCMS_ContentInfo_free(CMS_ContentInfo *a) 90272343Sngie{ 91272343Sngie ASN1_item_free((ASN1_VALUE *)a, &CMS_ContentInfo_it); 92272343Sngie} 93272343SngieLCRYPTO_ALIAS(CMS_ContentInfo_free); 94272343Sngie 95272343Sngieint 96272343SngieCMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const ASN1_PCTX *pctx) 97272343Sngie{ 98272343Sngie return ASN1_item_print(out, (ASN1_VALUE *)x, indent, 99272343Sngie &CMS_ContentInfo_it, pctx); 100272343Sngie} 101272343SngieLCRYPTO_ALIAS(CMS_ContentInfo_print_ctx); 102272343Sngie 103272343Sngieconst ASN1_OBJECT * 104272343SngieCMS_get0_type(const CMS_ContentInfo *cms) 105272343Sngie{ 106272343Sngie return cms->contentType; 107272343Sngie} 108272343SngieLCRYPTO_ALIAS(CMS_get0_type); 109272343Sngie 110272343SngieCMS_ContentInfo * 111272343Sngiecms_Data_create(void) 112272343Sngie{ 113272343Sngie CMS_ContentInfo *cms; 114272343Sngie 115272343Sngie cms = CMS_ContentInfo_new(); 116272343Sngie if (cms != NULL) { 117272343Sngie cms->contentType = OBJ_nid2obj(NID_pkcs7_data); 118272343Sngie /* Never detached */ 119272343Sngie CMS_set_detached(cms, 0); 120272343Sngie } 121272343Sngie return cms; 122272343Sngie} 123272343Sngie 124272343Sngiestatic BIO * 125272343Sngiecms_content_bio(CMS_ContentInfo *cms) 126272343Sngie{ 127272343Sngie ASN1_OCTET_STRING **pos; 128272343Sngie 129272343Sngie if ((pos = CMS_get0_content(cms)) == NULL) 130272343Sngie return NULL; 131272343Sngie 132272343Sngie /* If content is detached, data goes nowhere: create null BIO. */ 133272343Sngie if (*pos == NULL) 134272343Sngie return BIO_new(BIO_s_null()); 135272343Sngie 136272343Sngie /* If content is not detached and was created, return memory BIO. */ 137272343Sngie if ((*pos)->flags == ASN1_STRING_FLAG_CONT) 138272343Sngie return BIO_new(BIO_s_mem()); 139272343Sngie 140272343Sngie /* Else content was read in: return read-only BIO for it. */ 141272343Sngie return BIO_new_mem_buf((*pos)->data, (*pos)->length); 142272343Sngie} 143272343Sngie 144272343SngieBIO * 145272343SngieCMS_dataInit(CMS_ContentInfo *cms, BIO *in_content_bio) 146272343Sngie{ 147272343Sngie BIO *cms_bio = NULL, *content_bio = NULL; 148272343Sngie 149272343Sngie if ((content_bio = in_content_bio) == NULL) 150272343Sngie content_bio = cms_content_bio(cms); 151272343Sngie if (content_bio == NULL) { 152272343Sngie CMSerror(CMS_R_NO_CONTENT); 153272343Sngie goto err; 154272343Sngie } 155272343Sngie 156272343Sngie switch (OBJ_obj2nid(cms->contentType)) { 157272343Sngie case NID_pkcs7_data: 158272343Sngie return content_bio; 159272343Sngie case NID_pkcs7_signed: 160272343Sngie if ((cms_bio = cms_SignedData_init_bio(cms)) == NULL) 161272343Sngie goto err; 162272343Sngie break; 163272343Sngie case NID_pkcs7_digest: 164272343Sngie if ((cms_bio = cms_DigestedData_init_bio(cms)) == NULL) 165272343Sngie goto err; 166272343Sngie break; 167272343Sngie case NID_pkcs7_encrypted: 168272343Sngie if ((cms_bio = cms_EncryptedData_init_bio(cms)) == NULL) 169272343Sngie goto err; 170272343Sngie break; 171272343Sngie case NID_pkcs7_enveloped: 172272343Sngie if ((cms_bio = cms_EnvelopedData_init_bio(cms)) == NULL) 173272343Sngie goto err; 174272343Sngie break; 175272343Sngie default: 176272343Sngie CMSerror(CMS_R_UNSUPPORTED_TYPE); 177272343Sngie goto err; 178272343Sngie } 179272343Sngie 180272343Sngie return BIO_push(cms_bio, content_bio); 181272343Sngie 182272343Sngie err: 183272343Sngie if (content_bio != in_content_bio) 184272343Sngie BIO_free(content_bio); 185272343Sngie 186272343Sngie return NULL; 187272343Sngie} 188272343SngieLCRYPTO_ALIAS(CMS_dataInit); 189272343Sngie 190272343Sngieint 191272343SngieCMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) 192272343Sngie{ 193272343Sngie ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 194272343Sngie 195272343Sngie if (!pos) 196272343Sngie return 0; 197272343Sngie /* If embedded content find memory BIO and set content */ 198272343Sngie if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { 199272343Sngie BIO *mbio; 200272343Sngie unsigned char *cont; 201272343Sngie long contlen; 202272343Sngie mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); 203272343Sngie if (!mbio) { 204272343Sngie CMSerror(CMS_R_CONTENT_NOT_FOUND); 205272343Sngie return 0; 206272343Sngie } 207272343Sngie contlen = BIO_get_mem_data(mbio, &cont); 208272343Sngie /* Set bio as read only so its content can't be clobbered */ 209272343Sngie BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); 210272343Sngie BIO_set_mem_eof_return(mbio, 0); 211272343Sngie ASN1_STRING_set0(*pos, cont, contlen); 212272343Sngie (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; 213272343Sngie } 214272343Sngie 215272343Sngie switch (OBJ_obj2nid(cms->contentType)) { 216272343Sngie 217272343Sngie case NID_pkcs7_data: 218272343Sngie case NID_pkcs7_enveloped: 219272343Sngie case NID_pkcs7_encrypted: 220272343Sngie case NID_id_smime_ct_compressedData: 221272343Sngie /* Nothing to do */ 222272343Sngie return 1; 223272343Sngie 224272343Sngie case NID_pkcs7_signed: 225272343Sngie return cms_SignedData_final(cms, cmsbio); 226272343Sngie 227272343Sngie case NID_pkcs7_digest: 228272343Sngie return cms_DigestedData_do_final(cms, cmsbio, 0); 229272343Sngie 230272343Sngie default: 231272343Sngie CMSerror(CMS_R_UNSUPPORTED_TYPE); 232272343Sngie return 0; 233272343Sngie } 234272343Sngie} 235272343SngieLCRYPTO_ALIAS(CMS_dataFinal); 236272343Sngie 237272343Sngieint 238272343SngieCMS_get_version(const CMS_ContentInfo *cms, long *version) 239272343Sngie{ 240272343Sngie switch (OBJ_obj2nid(cms->contentType)) { 241272343Sngie case NID_pkcs7_signed: 242272343Sngie *version = cms->d.signedData->version; 243272343Sngie return 1; 244272343Sngie 245272343Sngie case NID_pkcs7_enveloped: 246272343Sngie *version = cms->d.envelopedData->version; 247272343Sngie return 1; 248272343Sngie 249272343Sngie case NID_pkcs7_digest: 250272343Sngie *version = cms->d.digestedData->version; 251272343Sngie return 1; 252272343Sngie 253272343Sngie case NID_pkcs7_encrypted: 254272343Sngie *version = cms->d.encryptedData->version; 255272343Sngie return 1; 256272343Sngie 257272343Sngie case NID_id_smime_ct_authData: 258272343Sngie *version = cms->d.authenticatedData->version; 259272343Sngie return 1; 260272343Sngie 261272343Sngie case NID_id_smime_ct_compressedData: 262272343Sngie *version = cms->d.compressedData->version; 263272343Sngie return 1; 264272343Sngie 265272343Sngie default: 266272343Sngie CMSerror(CMS_R_UNSUPPORTED_TYPE); 267272343Sngie return 0; 268272343Sngie } 269272343Sngie} 270272343SngieLCRYPTO_ALIAS(CMS_get_version); 271272343Sngie 272272343Sngieint 273272343SngieCMS_SignerInfo_get_version(const CMS_SignerInfo *si, long *version) 274272343Sngie{ 275272343Sngie *version = si->version; 276272343Sngie return 1; 277272343Sngie} 278272343SngieLCRYPTO_ALIAS(CMS_SignerInfo_get_version); 279272343Sngie 280272343Sngie/* 281272343Sngie * Return an OCTET STRING pointer to content. This allows it to be accessed 282272343Sngie * or set later. 283272343Sngie */ 284272343Sngie 285272343SngieASN1_OCTET_STRING ** 286272343SngieCMS_get0_content(CMS_ContentInfo *cms) 287272343Sngie{ 288272343Sngie switch (OBJ_obj2nid(cms->contentType)) { 289272343Sngie case NID_pkcs7_data: 290272343Sngie return &cms->d.data; 291272343Sngie 292272343Sngie case NID_pkcs7_signed: 293272343Sngie return &cms->d.signedData->encapContentInfo->eContent; 294272343Sngie 295272343Sngie case NID_pkcs7_enveloped: 296272343Sngie return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; 297272343Sngie 298272343Sngie case NID_pkcs7_digest: 299272343Sngie return &cms->d.digestedData->encapContentInfo->eContent; 300272343Sngie 301272343Sngie case NID_pkcs7_encrypted: 302272343Sngie return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; 303272343Sngie 304272343Sngie case NID_id_smime_ct_authData: 305272343Sngie return &cms->d.authenticatedData->encapContentInfo->eContent; 306272343Sngie 307272343Sngie case NID_id_smime_ct_compressedData: 308272343Sngie return &cms->d.compressedData->encapContentInfo->eContent; 309272343Sngie 310272343Sngie default: 311272343Sngie if (cms->d.other->type == V_ASN1_OCTET_STRING) 312272343Sngie return &cms->d.other->value.octet_string; 313272343Sngie CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 314272343Sngie return NULL; 315272343Sngie } 316272343Sngie} 317272343SngieLCRYPTO_ALIAS(CMS_get0_content); 318272343Sngie 319272343Sngie/* 320272343Sngie * Return an ASN1_OBJECT pointer to content type. This allows it to be 321272343Sngie * accessed or set later. 322272343Sngie */ 323272343Sngie 324272343Sngiestatic ASN1_OBJECT ** 325272343Sngiecms_get0_econtent_type(CMS_ContentInfo *cms) 326272343Sngie{ 327272343Sngie switch (OBJ_obj2nid(cms->contentType)) { 328272343Sngie case NID_pkcs7_signed: 329272343Sngie return &cms->d.signedData->encapContentInfo->eContentType; 330272343Sngie 331272343Sngie case NID_pkcs7_enveloped: 332272343Sngie return &cms->d.envelopedData->encryptedContentInfo->contentType; 333272343Sngie 334272343Sngie case NID_pkcs7_digest: 335272343Sngie return &cms->d.digestedData->encapContentInfo->eContentType; 336272343Sngie 337272343Sngie case NID_pkcs7_encrypted: 338272343Sngie return &cms->d.encryptedData->encryptedContentInfo->contentType; 339272343Sngie 340272343Sngie case NID_id_smime_ct_authData: 341272343Sngie return &cms->d.authenticatedData->encapContentInfo->eContentType; 342272343Sngie 343272343Sngie case NID_id_smime_ct_compressedData: 344272343Sngie return &cms->d.compressedData->encapContentInfo->eContentType; 345272343Sngie 346272343Sngie default: 347272343Sngie CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 348272343Sngie return NULL; 349272343Sngie } 350272343Sngie} 351272343Sngie 352const ASN1_OBJECT * 353CMS_get0_eContentType(CMS_ContentInfo *cms) 354{ 355 ASN1_OBJECT **petype; 356 357 petype = cms_get0_econtent_type(cms); 358 if (petype) 359 return *petype; 360 361 return NULL; 362} 363LCRYPTO_ALIAS(CMS_get0_eContentType); 364 365int 366CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) 367{ 368 ASN1_OBJECT **petype, *etype; 369 370 petype = cms_get0_econtent_type(cms); 371 if (!petype) 372 return 0; 373 if (!oid) 374 return 1; 375 etype = OBJ_dup(oid); 376 if (!etype) 377 return 0; 378 ASN1_OBJECT_free(*petype); 379 *petype = etype; 380 381 return 1; 382} 383LCRYPTO_ALIAS(CMS_set1_eContentType); 384 385int 386CMS_is_detached(CMS_ContentInfo *cms) 387{ 388 ASN1_OCTET_STRING **pos; 389 390 pos = CMS_get0_content(cms); 391 if (!pos) 392 return -1; 393 if (*pos) 394 return 0; 395 396 return 1; 397} 398LCRYPTO_ALIAS(CMS_is_detached); 399 400int 401CMS_set_detached(CMS_ContentInfo *cms, int detached) 402{ 403 ASN1_OCTET_STRING **pos; 404 405 pos = CMS_get0_content(cms); 406 if (!pos) 407 return 0; 408 if (detached) { 409 ASN1_OCTET_STRING_free(*pos); 410 *pos = NULL; 411 return 1; 412 } 413 if (*pos == NULL) 414 *pos = ASN1_OCTET_STRING_new(); 415 if (*pos != NULL) { 416 /* 417 * NB: special flag to show content is created and not read in. 418 */ 419 (*pos)->flags |= ASN1_STRING_FLAG_CONT; 420 return 1; 421 } 422 CMSerror(ERR_R_MALLOC_FAILURE); 423 424 return 0; 425} 426LCRYPTO_ALIAS(CMS_set_detached); 427 428/* Create a digest BIO from an X509_ALGOR structure */ 429 430BIO * 431cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) 432{ 433 BIO *mdbio = NULL; 434 const ASN1_OBJECT *digestoid; 435 const EVP_MD *digest; 436 437 X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); 438 digest = EVP_get_digestbyobj(digestoid); 439 if (!digest) { 440 CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM); 441 goto err; 442 } 443 mdbio = BIO_new(BIO_f_md()); 444 if (mdbio == NULL || !BIO_set_md(mdbio, digest)) { 445 CMSerror(CMS_R_MD_BIO_INIT_ERROR); 446 goto err; 447 } 448 return mdbio; 449 450 err: 451 BIO_free(mdbio); 452 453 return NULL; 454} 455 456/* Locate a message digest content from a BIO chain based on SignerInfo */ 457 458int 459cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg) 460{ 461 int nid; 462 const ASN1_OBJECT *mdoid; 463 464 X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); 465 nid = OBJ_obj2nid(mdoid); 466 /* Look for digest type to match signature */ 467 for (;;) { 468 EVP_MD_CTX *mtmp; 469 chain = BIO_find_type(chain, BIO_TYPE_MD); 470 if (chain == NULL) { 471 CMSerror(CMS_R_NO_MATCHING_DIGEST); 472 return 0; 473 } 474 BIO_get_md_ctx(chain, &mtmp); 475 if (EVP_MD_CTX_type(mtmp) == nid 476 /* 477 * Workaround for broken implementations that use signature 478 * algorithm OID instead of digest. 479 */ 480 || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) 481 return EVP_MD_CTX_copy_ex(mctx, mtmp); 482 chain = BIO_next(chain); 483 } 484} 485 486static STACK_OF(CMS_CertificateChoices) ** 487cms_get0_certificate_choices(CMS_ContentInfo *cms) 488{ 489 switch (OBJ_obj2nid(cms->contentType)) { 490 case NID_pkcs7_signed: 491 return &cms->d.signedData->certificates; 492 493 case NID_pkcs7_enveloped: 494 if (cms->d.envelopedData->originatorInfo == NULL) 495 return NULL; 496 return &cms->d.envelopedData->originatorInfo->certificates; 497 498 default: 499 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 500 return NULL; 501 } 502} 503 504CMS_CertificateChoices * 505CMS_add0_CertificateChoices(CMS_ContentInfo *cms) 506{ 507 STACK_OF(CMS_CertificateChoices) **pcerts; 508 CMS_CertificateChoices *cch; 509 510 pcerts = cms_get0_certificate_choices(cms); 511 if (!pcerts) 512 return NULL; 513 if (!*pcerts) 514 *pcerts = sk_CMS_CertificateChoices_new_null(); 515 if (!*pcerts) 516 return NULL; 517 cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it); 518 if (!cch) 519 return NULL; 520 if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { 521 ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it); 522 return NULL; 523 } 524 525 return cch; 526} 527LCRYPTO_ALIAS(CMS_add0_CertificateChoices); 528 529int 530CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 531{ 532 CMS_CertificateChoices *cch; 533 STACK_OF(CMS_CertificateChoices) **pcerts; 534 int i; 535 536 pcerts = cms_get0_certificate_choices(cms); 537 if (!pcerts) 538 return 0; 539 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 540 cch = sk_CMS_CertificateChoices_value(*pcerts, i); 541 if (cch->type == CMS_CERTCHOICE_CERT) { 542 if (!X509_cmp(cch->d.certificate, cert)) { 543 CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT); 544 return 0; 545 } 546 } 547 } 548 cch = CMS_add0_CertificateChoices(cms); 549 if (!cch) 550 return 0; 551 cch->type = CMS_CERTCHOICE_CERT; 552 cch->d.certificate = cert; 553 554 return 1; 555} 556LCRYPTO_ALIAS(CMS_add0_cert); 557 558int 559CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) 560{ 561 int r; 562 563 r = CMS_add0_cert(cms, cert); 564 if (r > 0) 565 X509_up_ref(cert); 566 567 return r; 568} 569LCRYPTO_ALIAS(CMS_add1_cert); 570 571static STACK_OF(CMS_RevocationInfoChoice) ** 572cms_get0_revocation_choices(CMS_ContentInfo *cms) 573{ 574 switch (OBJ_obj2nid(cms->contentType)) { 575 case NID_pkcs7_signed: 576 return &cms->d.signedData->crls; 577 578 case NID_pkcs7_enveloped: 579 if (cms->d.envelopedData->originatorInfo == NULL) 580 return NULL; 581 return &cms->d.envelopedData->originatorInfo->crls; 582 583 default: 584 CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 585 return NULL; 586 } 587} 588 589CMS_RevocationInfoChoice * 590CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) 591{ 592 STACK_OF(CMS_RevocationInfoChoice) **pcrls; 593 CMS_RevocationInfoChoice *rch; 594 595 pcrls = cms_get0_revocation_choices(cms); 596 if (!pcrls) 597 return NULL; 598 if (!*pcrls) 599 *pcrls = sk_CMS_RevocationInfoChoice_new_null(); 600 if (!*pcrls) 601 return NULL; 602 rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it); 603 if (!rch) 604 return NULL; 605 if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { 606 ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it); 607 return NULL; 608 } 609 610 return rch; 611} 612LCRYPTO_ALIAS(CMS_add0_RevocationInfoChoice); 613 614int 615CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) 616{ 617 CMS_RevocationInfoChoice *rch; 618 619 rch = CMS_add0_RevocationInfoChoice(cms); 620 if (!rch) 621 return 0; 622 rch->type = CMS_REVCHOICE_CRL; 623 rch->d.crl = crl; 624 625 return 1; 626} 627LCRYPTO_ALIAS(CMS_add0_crl); 628 629int 630CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) 631{ 632 int r; 633 634 r = CMS_add0_crl(cms, crl); 635 if (r > 0) 636 X509_CRL_up_ref(crl); 637 638 return r; 639} 640LCRYPTO_ALIAS(CMS_add1_crl); 641 642STACK_OF(X509) * 643CMS_get1_certs(CMS_ContentInfo *cms) 644{ 645 STACK_OF(X509) *certs = NULL; 646 CMS_CertificateChoices *cch; 647 STACK_OF(CMS_CertificateChoices) **pcerts; 648 int i; 649 650 pcerts = cms_get0_certificate_choices(cms); 651 if (!pcerts) 652 return NULL; 653 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 654 cch = sk_CMS_CertificateChoices_value(*pcerts, i); 655 if (cch->type == 0) { 656 if (!certs) { 657 certs = sk_X509_new_null(); 658 if (!certs) 659 return NULL; 660 } 661 if (!sk_X509_push(certs, cch->d.certificate)) { 662 sk_X509_pop_free(certs, X509_free); 663 return NULL; 664 } 665 X509_up_ref(cch->d.certificate); 666 } 667 } 668 return certs; 669} 670LCRYPTO_ALIAS(CMS_get1_certs); 671 672STACK_OF(X509_CRL) * 673CMS_get1_crls(CMS_ContentInfo *cms) 674{ 675 STACK_OF(X509_CRL) *crls = NULL; 676 STACK_OF(CMS_RevocationInfoChoice) **pcrls; 677 CMS_RevocationInfoChoice *rch; 678 int i; 679 680 pcrls = cms_get0_revocation_choices(cms); 681 if (!pcrls) 682 return NULL; 683 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { 684 rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); 685 if (rch->type == 0) { 686 if (!crls) { 687 crls = sk_X509_CRL_new_null(); 688 if (!crls) 689 return NULL; 690 } 691 if (!sk_X509_CRL_push(crls, rch->d.crl)) { 692 sk_X509_CRL_pop_free(crls, X509_CRL_free); 693 return NULL; 694 } 695 X509_CRL_up_ref(rch->d.crl); 696 } 697 } 698 return crls; 699} 700LCRYPTO_ALIAS(CMS_get1_crls); 701 702static const ASN1_OCTET_STRING * 703cms_X509_get0_subject_key_id(X509 *x) 704{ 705 /* Call for side-effect of computing hash and caching extensions */ 706 X509_check_purpose(x, -1, -1); 707 return x->skid; 708} 709 710int 711cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert) 712{ 713 int ret; 714 715 ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert)); 716 if (ret) 717 return ret; 718 719 return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert)); 720} 721 722int 723cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert) 724{ 725 const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert); 726 727 if (cert_keyid == NULL) 728 return -1; 729 730 return ASN1_OCTET_STRING_cmp(keyid, cert_keyid); 731} 732 733int 734cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) 735{ 736 CMS_IssuerAndSerialNumber *ias; 737 738 ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it); 739 if (!ias) 740 goto err; 741 if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) 742 goto err; 743 if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert))) 744 goto err; 745 ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it); 746 *pias = ias; 747 748 return 1; 749 750 err: 751 ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it); 752 CMSerror(ERR_R_MALLOC_FAILURE); 753 754 return 0; 755} 756 757int 758cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) 759{ 760 ASN1_OCTET_STRING *keyid = NULL; 761 const ASN1_OCTET_STRING *cert_keyid; 762 763 cert_keyid = cms_X509_get0_subject_key_id(cert); 764 if (cert_keyid == NULL) { 765 CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID); 766 return 0; 767 } 768 keyid = ASN1_STRING_dup(cert_keyid); 769 if (!keyid) { 770 CMSerror(ERR_R_MALLOC_FAILURE); 771 return 0; 772 } 773 ASN1_OCTET_STRING_free(*pkeyid); 774 *pkeyid = keyid; 775 776 return 1; 777} 778