1183234Ssimon/* crypto/cms/cms_lib.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4183234Ssimon * project. 5183234Ssimon */ 6183234Ssimon/* ==================================================================== 7183234Ssimon * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8183234Ssimon * 9183234Ssimon * Redistribution and use in source and binary forms, with or without 10183234Ssimon * modification, are permitted provided that the following conditions 11183234Ssimon * are met: 12183234Ssimon * 13183234Ssimon * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 15183234Ssimon * 16183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright 17183234Ssimon * notice, this list of conditions and the following disclaimer in 18183234Ssimon * the documentation and/or other materials provided with the 19183234Ssimon * distribution. 20183234Ssimon * 21183234Ssimon * 3. All advertising materials mentioning features or use of this 22183234Ssimon * software must display the following acknowledgment: 23183234Ssimon * "This product includes software developed by the OpenSSL Project 24183234Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25183234Ssimon * 26183234Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27183234Ssimon * endorse or promote products derived from this software without 28183234Ssimon * prior written permission. For written permission, please contact 29183234Ssimon * licensing@OpenSSL.org. 30183234Ssimon * 31183234Ssimon * 5. Products derived from this software may not be called "OpenSSL" 32183234Ssimon * nor may "OpenSSL" appear in their names without prior written 33183234Ssimon * permission of the OpenSSL Project. 34183234Ssimon * 35183234Ssimon * 6. Redistributions of any form whatsoever must retain the following 36183234Ssimon * acknowledgment: 37183234Ssimon * "This product includes software developed by the OpenSSL Project 38183234Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39183234Ssimon * 40183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41183234Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42183234Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43183234Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44183234Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45183234Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46183234Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47183234Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48183234Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49183234Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51183234Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 52183234Ssimon * ==================================================================== 53183234Ssimon */ 54183234Ssimon 55183234Ssimon#include <openssl/asn1t.h> 56183234Ssimon#include <openssl/x509.h> 57183234Ssimon#include <openssl/err.h> 58183234Ssimon#include <openssl/pem.h> 59183234Ssimon#include <openssl/bio.h> 60183234Ssimon#include <openssl/asn1.h> 61183234Ssimon#include "cms.h" 62183234Ssimon#include "cms_lcl.h" 63183234Ssimon 64238405SjkimIMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo) 65238405SjkimIMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo) 66183234Ssimon 67183234SsimonDECLARE_ASN1_ITEM(CMS_CertificateChoices) 68183234SsimonDECLARE_ASN1_ITEM(CMS_RevocationInfoChoice) 69183234SsimonDECLARE_STACK_OF(CMS_CertificateChoices) 70183234SsimonDECLARE_STACK_OF(CMS_RevocationInfoChoice) 71183234Ssimon 72183234Ssimonconst ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms) 73280304Sjkim{ 74280304Sjkim return cms->contentType; 75280304Sjkim} 76183234Ssimon 77183234SsimonCMS_ContentInfo *cms_Data_create(void) 78280304Sjkim{ 79280304Sjkim CMS_ContentInfo *cms; 80280304Sjkim cms = CMS_ContentInfo_new(); 81280304Sjkim if (cms) { 82280304Sjkim cms->contentType = OBJ_nid2obj(NID_pkcs7_data); 83280304Sjkim /* Never detached */ 84280304Sjkim CMS_set_detached(cms, 0); 85280304Sjkim } 86280304Sjkim return cms; 87280304Sjkim} 88183234Ssimon 89183234SsimonBIO *cms_content_bio(CMS_ContentInfo *cms) 90280304Sjkim{ 91280304Sjkim ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 92280304Sjkim if (!pos) 93280304Sjkim return NULL; 94280304Sjkim /* If content detached data goes nowhere: create NULL BIO */ 95280304Sjkim if (!*pos) 96280304Sjkim return BIO_new(BIO_s_null()); 97280304Sjkim /* 98280304Sjkim * If content not detached and created return memory BIO 99280304Sjkim */ 100280304Sjkim if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) 101280304Sjkim return BIO_new(BIO_s_mem()); 102280304Sjkim /* Else content was read in: return read only BIO for it */ 103280304Sjkim return BIO_new_mem_buf((*pos)->data, (*pos)->length); 104280304Sjkim} 105183234Ssimon 106183234SsimonBIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) 107280304Sjkim{ 108280304Sjkim BIO *cmsbio, *cont; 109280304Sjkim if (icont) 110280304Sjkim cont = icont; 111280304Sjkim else 112280304Sjkim cont = cms_content_bio(cms); 113280304Sjkim if (!cont) { 114280304Sjkim CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT); 115280304Sjkim return NULL; 116280304Sjkim } 117280304Sjkim switch (OBJ_obj2nid(cms->contentType)) { 118183234Ssimon 119280304Sjkim case NID_pkcs7_data: 120280304Sjkim return cont; 121183234Ssimon 122280304Sjkim case NID_pkcs7_signed: 123280304Sjkim cmsbio = cms_SignedData_init_bio(cms); 124280304Sjkim break; 125183234Ssimon 126280304Sjkim case NID_pkcs7_digest: 127280304Sjkim cmsbio = cms_DigestedData_init_bio(cms); 128280304Sjkim break; 129183234Ssimon#ifdef ZLIB 130280304Sjkim case NID_id_smime_ct_compressedData: 131280304Sjkim cmsbio = cms_CompressedData_init_bio(cms); 132280304Sjkim break; 133183234Ssimon#endif 134183234Ssimon 135280304Sjkim case NID_pkcs7_encrypted: 136280304Sjkim cmsbio = cms_EncryptedData_init_bio(cms); 137280304Sjkim break; 138183234Ssimon 139280304Sjkim case NID_pkcs7_enveloped: 140280304Sjkim cmsbio = cms_EnvelopedData_init_bio(cms); 141280304Sjkim break; 142183234Ssimon 143280304Sjkim default: 144280304Sjkim CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); 145280304Sjkim return NULL; 146280304Sjkim } 147183234Ssimon 148280304Sjkim if (cmsbio) 149280304Sjkim return BIO_push(cmsbio, cont); 150183234Ssimon 151280304Sjkim if (!icont) 152280304Sjkim BIO_free(cont); 153280304Sjkim return NULL; 154183234Ssimon 155280304Sjkim} 156183234Ssimon 157183234Ssimonint CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) 158280304Sjkim{ 159280304Sjkim ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 160280304Sjkim if (!pos) 161280304Sjkim return 0; 162280304Sjkim /* If ebmedded content find memory BIO and set content */ 163280304Sjkim if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { 164280304Sjkim BIO *mbio; 165280304Sjkim unsigned char *cont; 166280304Sjkim long contlen; 167280304Sjkim mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); 168280304Sjkim if (!mbio) { 169280304Sjkim CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); 170280304Sjkim return 0; 171280304Sjkim } 172280304Sjkim contlen = BIO_get_mem_data(mbio, &cont); 173280304Sjkim /* Set bio as read only so its content can't be clobbered */ 174280304Sjkim BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); 175280304Sjkim BIO_set_mem_eof_return(mbio, 0); 176280304Sjkim ASN1_STRING_set0(*pos, cont, contlen); 177280304Sjkim (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; 178280304Sjkim } 179183234Ssimon 180280304Sjkim switch (OBJ_obj2nid(cms->contentType)) { 181183234Ssimon 182280304Sjkim case NID_pkcs7_data: 183280304Sjkim case NID_pkcs7_enveloped: 184280304Sjkim case NID_pkcs7_encrypted: 185280304Sjkim case NID_id_smime_ct_compressedData: 186280304Sjkim /* Nothing to do */ 187280304Sjkim return 1; 188183234Ssimon 189280304Sjkim case NID_pkcs7_signed: 190280304Sjkim return cms_SignedData_final(cms, cmsbio); 191183234Ssimon 192280304Sjkim case NID_pkcs7_digest: 193280304Sjkim return cms_DigestedData_do_final(cms, cmsbio, 0); 194183234Ssimon 195280304Sjkim default: 196280304Sjkim CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); 197280304Sjkim return 0; 198280304Sjkim } 199280304Sjkim} 200183234Ssimon 201280304Sjkim/* 202280304Sjkim * Return an OCTET STRING pointer to content. This allows it to be accessed 203280304Sjkim * or set later. 204183234Ssimon */ 205183234Ssimon 206183234SsimonASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) 207280304Sjkim{ 208280304Sjkim switch (OBJ_obj2nid(cms->contentType)) { 209183234Ssimon 210280304Sjkim case NID_pkcs7_data: 211280304Sjkim return &cms->d.data; 212183234Ssimon 213280304Sjkim case NID_pkcs7_signed: 214280304Sjkim return &cms->d.signedData->encapContentInfo->eContent; 215183234Ssimon 216280304Sjkim case NID_pkcs7_enveloped: 217280304Sjkim return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; 218183234Ssimon 219280304Sjkim case NID_pkcs7_digest: 220280304Sjkim return &cms->d.digestedData->encapContentInfo->eContent; 221183234Ssimon 222280304Sjkim case NID_pkcs7_encrypted: 223280304Sjkim return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; 224183234Ssimon 225280304Sjkim case NID_id_smime_ct_authData: 226280304Sjkim return &cms->d.authenticatedData->encapContentInfo->eContent; 227183234Ssimon 228280304Sjkim case NID_id_smime_ct_compressedData: 229280304Sjkim return &cms->d.compressedData->encapContentInfo->eContent; 230183234Ssimon 231280304Sjkim default: 232280304Sjkim if (cms->d.other->type == V_ASN1_OCTET_STRING) 233280304Sjkim return &cms->d.other->value.octet_string; 234280304Sjkim CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE); 235280304Sjkim return NULL; 236183234Ssimon 237280304Sjkim } 238280304Sjkim} 239183234Ssimon 240280304Sjkim/* 241280304Sjkim * Return an ASN1_OBJECT pointer to content type. This allows it to be 242280304Sjkim * accessed or set later. 243183234Ssimon */ 244183234Ssimon 245183234Ssimonstatic ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) 246280304Sjkim{ 247280304Sjkim switch (OBJ_obj2nid(cms->contentType)) { 248183234Ssimon 249280304Sjkim case NID_pkcs7_signed: 250280304Sjkim return &cms->d.signedData->encapContentInfo->eContentType; 251183234Ssimon 252280304Sjkim case NID_pkcs7_enveloped: 253280304Sjkim return &cms->d.envelopedData->encryptedContentInfo->contentType; 254183234Ssimon 255280304Sjkim case NID_pkcs7_digest: 256280304Sjkim return &cms->d.digestedData->encapContentInfo->eContentType; 257183234Ssimon 258280304Sjkim case NID_pkcs7_encrypted: 259280304Sjkim return &cms->d.encryptedData->encryptedContentInfo->contentType; 260183234Ssimon 261280304Sjkim case NID_id_smime_ct_authData: 262280304Sjkim return &cms->d.authenticatedData->encapContentInfo->eContentType; 263183234Ssimon 264280304Sjkim case NID_id_smime_ct_compressedData: 265280304Sjkim return &cms->d.compressedData->encapContentInfo->eContentType; 266183234Ssimon 267280304Sjkim default: 268280304Sjkim CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE); 269280304Sjkim return NULL; 270183234Ssimon 271280304Sjkim } 272280304Sjkim} 273183234Ssimon 274183234Ssimonconst ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) 275280304Sjkim{ 276280304Sjkim ASN1_OBJECT **petype; 277280304Sjkim petype = cms_get0_econtent_type(cms); 278280304Sjkim if (petype) 279280304Sjkim return *petype; 280280304Sjkim return NULL; 281280304Sjkim} 282183234Ssimon 283183234Ssimonint CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) 284280304Sjkim{ 285280304Sjkim ASN1_OBJECT **petype, *etype; 286280304Sjkim petype = cms_get0_econtent_type(cms); 287280304Sjkim if (!petype) 288280304Sjkim return 0; 289280304Sjkim if (!oid) 290280304Sjkim return 1; 291280304Sjkim etype = OBJ_dup(oid); 292280304Sjkim if (!etype) 293280304Sjkim return 0; 294280304Sjkim ASN1_OBJECT_free(*petype); 295280304Sjkim *petype = etype; 296280304Sjkim return 1; 297280304Sjkim} 298183234Ssimon 299183234Ssimonint CMS_is_detached(CMS_ContentInfo *cms) 300280304Sjkim{ 301280304Sjkim ASN1_OCTET_STRING **pos; 302280304Sjkim pos = CMS_get0_content(cms); 303280304Sjkim if (!pos) 304280304Sjkim return -1; 305280304Sjkim if (*pos) 306280304Sjkim return 0; 307280304Sjkim return 1; 308280304Sjkim} 309183234Ssimon 310183234Ssimonint CMS_set_detached(CMS_ContentInfo *cms, int detached) 311280304Sjkim{ 312280304Sjkim ASN1_OCTET_STRING **pos; 313280304Sjkim pos = CMS_get0_content(cms); 314280304Sjkim if (!pos) 315280304Sjkim return 0; 316280304Sjkim if (detached) { 317280304Sjkim if (*pos) { 318280304Sjkim ASN1_OCTET_STRING_free(*pos); 319280304Sjkim *pos = NULL; 320280304Sjkim } 321280304Sjkim return 1; 322280304Sjkim } 323280304Sjkim if (!*pos) 324280304Sjkim *pos = ASN1_OCTET_STRING_new(); 325280304Sjkim if (*pos) { 326280304Sjkim /* 327280304Sjkim * NB: special flag to show content is created and not read in. 328280304Sjkim */ 329280304Sjkim (*pos)->flags |= ASN1_STRING_FLAG_CONT; 330280304Sjkim return 1; 331280304Sjkim } 332280304Sjkim CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE); 333280304Sjkim return 0; 334280304Sjkim} 335183234Ssimon 336183234Ssimon/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ 337183234Ssimon 338183234Ssimonvoid cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md) 339280304Sjkim{ 340280304Sjkim int param_type; 341183234Ssimon 342280304Sjkim if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT) 343280304Sjkim param_type = V_ASN1_UNDEF; 344280304Sjkim else 345280304Sjkim param_type = V_ASN1_NULL; 346183234Ssimon 347280304Sjkim X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); 348183234Ssimon 349280304Sjkim} 350183234Ssimon 351183234Ssimon/* Create a digest BIO from an X509_ALGOR structure */ 352183234Ssimon 353183234SsimonBIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) 354280304Sjkim{ 355280304Sjkim BIO *mdbio = NULL; 356280304Sjkim ASN1_OBJECT *digestoid; 357280304Sjkim const EVP_MD *digest; 358280304Sjkim X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); 359280304Sjkim digest = EVP_get_digestbyobj(digestoid); 360280304Sjkim if (!digest) { 361280304Sjkim CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 362280304Sjkim CMS_R_UNKNOWN_DIGEST_ALGORIHM); 363280304Sjkim goto err; 364280304Sjkim } 365280304Sjkim mdbio = BIO_new(BIO_f_md()); 366280304Sjkim if (!mdbio || !BIO_set_md(mdbio, digest)) { 367280304Sjkim CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR); 368280304Sjkim goto err; 369280304Sjkim } 370280304Sjkim return mdbio; 371280304Sjkim err: 372280304Sjkim if (mdbio) 373280304Sjkim BIO_free(mdbio); 374280304Sjkim return NULL; 375280304Sjkim} 376183234Ssimon 377183234Ssimon/* Locate a message digest content from a BIO chain based on SignerInfo */ 378183234Ssimon 379183234Ssimonint cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, 380280304Sjkim X509_ALGOR *mdalg) 381280304Sjkim{ 382280304Sjkim int nid; 383280304Sjkim ASN1_OBJECT *mdoid; 384280304Sjkim X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); 385280304Sjkim nid = OBJ_obj2nid(mdoid); 386280304Sjkim /* Look for digest type to match signature */ 387280304Sjkim for (;;) { 388280304Sjkim EVP_MD_CTX *mtmp; 389280304Sjkim chain = BIO_find_type(chain, BIO_TYPE_MD); 390280304Sjkim if (chain == NULL) { 391280304Sjkim CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, 392280304Sjkim CMS_R_NO_MATCHING_DIGEST); 393280304Sjkim return 0; 394280304Sjkim } 395280304Sjkim BIO_get_md_ctx(chain, &mtmp); 396280304Sjkim if (EVP_MD_CTX_type(mtmp) == nid 397280304Sjkim /* 398280304Sjkim * Workaround for broken implementations that use signature 399280304Sjkim * algorithm OID instead of digest. 400280304Sjkim */ 401280304Sjkim || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) 402280304Sjkim return EVP_MD_CTX_copy_ex(mctx, mtmp); 403280304Sjkim chain = BIO_next(chain); 404280304Sjkim } 405280304Sjkim} 406183234Ssimon 407280304Sjkimstatic STACK_OF(CMS_CertificateChoices) 408280304Sjkim**cms_get0_certificate_choices(CMS_ContentInfo *cms) 409280304Sjkim{ 410280304Sjkim switch (OBJ_obj2nid(cms->contentType)) { 411183234Ssimon 412280304Sjkim case NID_pkcs7_signed: 413280304Sjkim return &cms->d.signedData->certificates; 414183234Ssimon 415280304Sjkim case NID_pkcs7_enveloped: 416280304Sjkim return &cms->d.envelopedData->originatorInfo->certificates; 417183234Ssimon 418280304Sjkim default: 419280304Sjkim CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES, 420280304Sjkim CMS_R_UNSUPPORTED_CONTENT_TYPE); 421280304Sjkim return NULL; 422183234Ssimon 423280304Sjkim } 424280304Sjkim} 425183234Ssimon 426183234SsimonCMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) 427280304Sjkim{ 428280304Sjkim STACK_OF(CMS_CertificateChoices) **pcerts; 429280304Sjkim CMS_CertificateChoices *cch; 430280304Sjkim pcerts = cms_get0_certificate_choices(cms); 431280304Sjkim if (!pcerts) 432280304Sjkim return NULL; 433280304Sjkim if (!*pcerts) 434280304Sjkim *pcerts = sk_CMS_CertificateChoices_new_null(); 435280304Sjkim if (!*pcerts) 436280304Sjkim return NULL; 437280304Sjkim cch = M_ASN1_new_of(CMS_CertificateChoices); 438280304Sjkim if (!cch) 439280304Sjkim return NULL; 440280304Sjkim if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { 441280304Sjkim M_ASN1_free_of(cch, CMS_CertificateChoices); 442280304Sjkim return NULL; 443280304Sjkim } 444280304Sjkim return cch; 445280304Sjkim} 446183234Ssimon 447183234Ssimonint CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 448280304Sjkim{ 449280304Sjkim CMS_CertificateChoices *cch; 450280304Sjkim STACK_OF(CMS_CertificateChoices) **pcerts; 451280304Sjkim int i; 452280304Sjkim pcerts = cms_get0_certificate_choices(cms); 453280304Sjkim if (!pcerts) 454280304Sjkim return 0; 455280304Sjkim for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 456280304Sjkim cch = sk_CMS_CertificateChoices_value(*pcerts, i); 457280304Sjkim if (cch->type == CMS_CERTCHOICE_CERT) { 458280304Sjkim if (!X509_cmp(cch->d.certificate, cert)) { 459280304Sjkim CMSerr(CMS_F_CMS_ADD0_CERT, 460280304Sjkim CMS_R_CERTIFICATE_ALREADY_PRESENT); 461280304Sjkim return 0; 462280304Sjkim } 463280304Sjkim } 464280304Sjkim } 465280304Sjkim cch = CMS_add0_CertificateChoices(cms); 466280304Sjkim if (!cch) 467280304Sjkim return 0; 468280304Sjkim cch->type = CMS_CERTCHOICE_CERT; 469280304Sjkim cch->d.certificate = cert; 470280304Sjkim return 1; 471280304Sjkim} 472183234Ssimon 473183234Ssimonint CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) 474280304Sjkim{ 475280304Sjkim int r; 476280304Sjkim r = CMS_add0_cert(cms, cert); 477280304Sjkim if (r > 0) 478280304Sjkim CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); 479280304Sjkim return r; 480280304Sjkim} 481183234Ssimon 482280304Sjkimstatic STACK_OF(CMS_RevocationInfoChoice) 483280304Sjkim**cms_get0_revocation_choices(CMS_ContentInfo *cms) 484280304Sjkim{ 485280304Sjkim switch (OBJ_obj2nid(cms->contentType)) { 486183234Ssimon 487280304Sjkim case NID_pkcs7_signed: 488280304Sjkim return &cms->d.signedData->crls; 489183234Ssimon 490280304Sjkim case NID_pkcs7_enveloped: 491280304Sjkim return &cms->d.envelopedData->originatorInfo->crls; 492183234Ssimon 493280304Sjkim default: 494280304Sjkim CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES, 495280304Sjkim CMS_R_UNSUPPORTED_CONTENT_TYPE); 496280304Sjkim return NULL; 497183234Ssimon 498280304Sjkim } 499280304Sjkim} 500183234Ssimon 501183234SsimonCMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) 502280304Sjkim{ 503280304Sjkim STACK_OF(CMS_RevocationInfoChoice) **pcrls; 504280304Sjkim CMS_RevocationInfoChoice *rch; 505280304Sjkim pcrls = cms_get0_revocation_choices(cms); 506280304Sjkim if (!pcrls) 507280304Sjkim return NULL; 508280304Sjkim if (!*pcrls) 509280304Sjkim *pcrls = sk_CMS_RevocationInfoChoice_new_null(); 510280304Sjkim if (!*pcrls) 511280304Sjkim return NULL; 512280304Sjkim rch = M_ASN1_new_of(CMS_RevocationInfoChoice); 513280304Sjkim if (!rch) 514280304Sjkim return NULL; 515280304Sjkim if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { 516280304Sjkim M_ASN1_free_of(rch, CMS_RevocationInfoChoice); 517280304Sjkim return NULL; 518280304Sjkim } 519280304Sjkim return rch; 520280304Sjkim} 521183234Ssimon 522183234Ssimonint CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) 523280304Sjkim{ 524280304Sjkim CMS_RevocationInfoChoice *rch; 525280304Sjkim rch = CMS_add0_RevocationInfoChoice(cms); 526280304Sjkim if (!rch) 527280304Sjkim return 0; 528280304Sjkim rch->type = CMS_REVCHOICE_CRL; 529280304Sjkim rch->d.crl = crl; 530280304Sjkim return 1; 531280304Sjkim} 532183234Ssimon 533238405Sjkimint CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) 534280304Sjkim{ 535280304Sjkim int r; 536280304Sjkim r = CMS_add0_crl(cms, crl); 537280304Sjkim if (r > 0) 538280304Sjkim CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); 539280304Sjkim return r; 540280304Sjkim} 541238405Sjkim 542183234SsimonSTACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) 543280304Sjkim{ 544280304Sjkim STACK_OF(X509) *certs = NULL; 545280304Sjkim CMS_CertificateChoices *cch; 546280304Sjkim STACK_OF(CMS_CertificateChoices) **pcerts; 547280304Sjkim int i; 548280304Sjkim pcerts = cms_get0_certificate_choices(cms); 549280304Sjkim if (!pcerts) 550280304Sjkim return NULL; 551280304Sjkim for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 552280304Sjkim cch = sk_CMS_CertificateChoices_value(*pcerts, i); 553280304Sjkim if (cch->type == 0) { 554280304Sjkim if (!certs) { 555280304Sjkim certs = sk_X509_new_null(); 556280304Sjkim if (!certs) 557280304Sjkim return NULL; 558280304Sjkim } 559280304Sjkim if (!sk_X509_push(certs, cch->d.certificate)) { 560280304Sjkim sk_X509_pop_free(certs, X509_free); 561280304Sjkim return NULL; 562280304Sjkim } 563280304Sjkim CRYPTO_add(&cch->d.certificate->references, 1, CRYPTO_LOCK_X509); 564280304Sjkim } 565280304Sjkim } 566280304Sjkim return certs; 567183234Ssimon 568280304Sjkim} 569183234Ssimon 570183234SsimonSTACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) 571280304Sjkim{ 572280304Sjkim STACK_OF(X509_CRL) *crls = NULL; 573280304Sjkim STACK_OF(CMS_RevocationInfoChoice) **pcrls; 574280304Sjkim CMS_RevocationInfoChoice *rch; 575280304Sjkim int i; 576280304Sjkim pcrls = cms_get0_revocation_choices(cms); 577280304Sjkim if (!pcrls) 578280304Sjkim return NULL; 579280304Sjkim for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { 580280304Sjkim rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); 581280304Sjkim if (rch->type == 0) { 582280304Sjkim if (!crls) { 583280304Sjkim crls = sk_X509_CRL_new_null(); 584280304Sjkim if (!crls) 585280304Sjkim return NULL; 586280304Sjkim } 587280304Sjkim if (!sk_X509_CRL_push(crls, rch->d.crl)) { 588280304Sjkim sk_X509_CRL_pop_free(crls, X509_CRL_free); 589280304Sjkim return NULL; 590280304Sjkim } 591280304Sjkim CRYPTO_add(&rch->d.crl->references, 1, CRYPTO_LOCK_X509_CRL); 592280304Sjkim } 593280304Sjkim } 594280304Sjkim return crls; 595280304Sjkim} 596