1183234Ssimon/* crypto/cms/cms_lib.c */ 2183234Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3183234Ssimon * project. 4183234Ssimon */ 5183234Ssimon/* ==================================================================== 6183234Ssimon * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 7183234Ssimon * 8183234Ssimon * Redistribution and use in source and binary forms, with or without 9183234Ssimon * modification, are permitted provided that the following conditions 10183234Ssimon * are met: 11183234Ssimon * 12183234Ssimon * 1. Redistributions of source code must retain the above copyright 13183234Ssimon * notice, this list of conditions and the following disclaimer. 14183234Ssimon * 15183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright 16183234Ssimon * notice, this list of conditions and the following disclaimer in 17183234Ssimon * the documentation and/or other materials provided with the 18183234Ssimon * distribution. 19183234Ssimon * 20183234Ssimon * 3. All advertising materials mentioning features or use of this 21183234Ssimon * software must display the following acknowledgment: 22183234Ssimon * "This product includes software developed by the OpenSSL Project 23183234Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24183234Ssimon * 25183234Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26183234Ssimon * endorse or promote products derived from this software without 27183234Ssimon * prior written permission. For written permission, please contact 28183234Ssimon * licensing@OpenSSL.org. 29183234Ssimon * 30183234Ssimon * 5. Products derived from this software may not be called "OpenSSL" 31183234Ssimon * nor may "OpenSSL" appear in their names without prior written 32183234Ssimon * permission of the OpenSSL Project. 33183234Ssimon * 34183234Ssimon * 6. Redistributions of any form whatsoever must retain the following 35183234Ssimon * acknowledgment: 36183234Ssimon * "This product includes software developed by the OpenSSL Project 37183234Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38183234Ssimon * 39183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40183234Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41183234Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42183234Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43183234Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44183234Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45183234Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46183234Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47183234Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48183234Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50183234Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 51183234Ssimon * ==================================================================== 52183234Ssimon */ 53183234Ssimon 54183234Ssimon#include <openssl/asn1t.h> 55183234Ssimon#include <openssl/x509.h> 56183234Ssimon#include <openssl/err.h> 57183234Ssimon#include <openssl/pem.h> 58183234Ssimon#include <openssl/bio.h> 59183234Ssimon#include <openssl/asn1.h> 60183234Ssimon#include "cms.h" 61183234Ssimon#include "cms_lcl.h" 62183234Ssimon 63238405SjkimIMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo) 64238405SjkimIMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo) 65183234Ssimon 66183234SsimonDECLARE_ASN1_ITEM(CMS_CertificateChoices) 67183234SsimonDECLARE_ASN1_ITEM(CMS_RevocationInfoChoice) 68183234SsimonDECLARE_STACK_OF(CMS_CertificateChoices) 69183234SsimonDECLARE_STACK_OF(CMS_RevocationInfoChoice) 70183234Ssimon 71183234Ssimonconst ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms) 72183234Ssimon { 73183234Ssimon return cms->contentType; 74183234Ssimon } 75183234Ssimon 76183234SsimonCMS_ContentInfo *cms_Data_create(void) 77183234Ssimon { 78183234Ssimon CMS_ContentInfo *cms; 79183234Ssimon cms = CMS_ContentInfo_new(); 80183234Ssimon if (cms) 81183234Ssimon { 82183234Ssimon cms->contentType = OBJ_nid2obj(NID_pkcs7_data); 83183234Ssimon /* Never detached */ 84183234Ssimon CMS_set_detached(cms, 0); 85183234Ssimon } 86183234Ssimon return cms; 87183234Ssimon } 88183234Ssimon 89183234SsimonBIO *cms_content_bio(CMS_ContentInfo *cms) 90183234Ssimon { 91183234Ssimon ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 92183234Ssimon if (!pos) 93183234Ssimon return NULL; 94183234Ssimon /* If content detached data goes nowhere: create NULL BIO */ 95183234Ssimon if (!*pos) 96183234Ssimon return BIO_new(BIO_s_null()); 97183234Ssimon /* If content not detached and created return memory BIO 98183234Ssimon */ 99183234Ssimon if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) 100183234Ssimon return BIO_new(BIO_s_mem()); 101183234Ssimon /* Else content was read in: return read only BIO for it */ 102183234Ssimon return BIO_new_mem_buf((*pos)->data, (*pos)->length); 103183234Ssimon } 104183234Ssimon 105183234SsimonBIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) 106183234Ssimon { 107183234Ssimon BIO *cmsbio, *cont; 108183234Ssimon if (icont) 109183234Ssimon cont = icont; 110183234Ssimon else 111183234Ssimon cont = cms_content_bio(cms); 112183234Ssimon if (!cont) 113183234Ssimon { 114183234Ssimon CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT); 115183234Ssimon return NULL; 116183234Ssimon } 117183234Ssimon switch (OBJ_obj2nid(cms->contentType)) 118183234Ssimon { 119183234Ssimon 120183234Ssimon case NID_pkcs7_data: 121183234Ssimon return cont; 122183234Ssimon 123183234Ssimon case NID_pkcs7_signed: 124183234Ssimon cmsbio = cms_SignedData_init_bio(cms); 125183234Ssimon break; 126183234Ssimon 127183234Ssimon case NID_pkcs7_digest: 128183234Ssimon cmsbio = cms_DigestedData_init_bio(cms); 129183234Ssimon break; 130183234Ssimon#ifdef ZLIB 131183234Ssimon case NID_id_smime_ct_compressedData: 132183234Ssimon cmsbio = cms_CompressedData_init_bio(cms); 133183234Ssimon break; 134183234Ssimon#endif 135183234Ssimon 136183234Ssimon case NID_pkcs7_encrypted: 137183234Ssimon cmsbio = cms_EncryptedData_init_bio(cms); 138183234Ssimon break; 139183234Ssimon 140183234Ssimon case NID_pkcs7_enveloped: 141183234Ssimon cmsbio = cms_EnvelopedData_init_bio(cms); 142183234Ssimon break; 143183234Ssimon 144183234Ssimon default: 145183234Ssimon CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); 146183234Ssimon return NULL; 147183234Ssimon } 148183234Ssimon 149183234Ssimon if (cmsbio) 150183234Ssimon return BIO_push(cmsbio, cont); 151183234Ssimon 152183234Ssimon if (!icont) 153183234Ssimon BIO_free(cont); 154183234Ssimon return NULL; 155183234Ssimon 156183234Ssimon } 157183234Ssimon 158183234Ssimonint CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) 159183234Ssimon { 160183234Ssimon ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 161183234Ssimon if (!pos) 162183234Ssimon return 0; 163183234Ssimon /* If ebmedded content find memory BIO and set content */ 164183234Ssimon if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) 165183234Ssimon { 166183234Ssimon BIO *mbio; 167183234Ssimon unsigned char *cont; 168183234Ssimon long contlen; 169183234Ssimon mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); 170183234Ssimon if (!mbio) 171183234Ssimon { 172183234Ssimon CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); 173183234Ssimon return 0; 174183234Ssimon } 175183234Ssimon contlen = BIO_get_mem_data(mbio, &cont); 176183234Ssimon /* Set bio as read only so its content can't be clobbered */ 177183234Ssimon BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); 178183234Ssimon BIO_set_mem_eof_return(mbio, 0); 179183234Ssimon ASN1_STRING_set0(*pos, cont, contlen); 180183234Ssimon (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; 181183234Ssimon } 182183234Ssimon 183183234Ssimon switch (OBJ_obj2nid(cms->contentType)) 184183234Ssimon { 185183234Ssimon 186183234Ssimon case NID_pkcs7_data: 187183234Ssimon case NID_pkcs7_enveloped: 188183234Ssimon case NID_pkcs7_encrypted: 189183234Ssimon case NID_id_smime_ct_compressedData: 190183234Ssimon /* Nothing to do */ 191183234Ssimon return 1; 192183234Ssimon 193183234Ssimon case NID_pkcs7_signed: 194183234Ssimon return cms_SignedData_final(cms, cmsbio); 195183234Ssimon 196183234Ssimon case NID_pkcs7_digest: 197183234Ssimon return cms_DigestedData_do_final(cms, cmsbio, 0); 198183234Ssimon 199183234Ssimon default: 200183234Ssimon CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); 201183234Ssimon return 0; 202183234Ssimon } 203183234Ssimon } 204183234Ssimon 205183234Ssimon/* Return an OCTET STRING pointer to content. This allows it to 206183234Ssimon * be accessed or set later. 207183234Ssimon */ 208183234Ssimon 209183234SsimonASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) 210183234Ssimon { 211183234Ssimon switch (OBJ_obj2nid(cms->contentType)) 212183234Ssimon { 213183234Ssimon 214183234Ssimon case NID_pkcs7_data: 215183234Ssimon return &cms->d.data; 216183234Ssimon 217183234Ssimon case NID_pkcs7_signed: 218183234Ssimon return &cms->d.signedData->encapContentInfo->eContent; 219183234Ssimon 220183234Ssimon case NID_pkcs7_enveloped: 221183234Ssimon return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; 222183234Ssimon 223183234Ssimon case NID_pkcs7_digest: 224183234Ssimon return &cms->d.digestedData->encapContentInfo->eContent; 225183234Ssimon 226183234Ssimon case NID_pkcs7_encrypted: 227183234Ssimon return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; 228183234Ssimon 229183234Ssimon case NID_id_smime_ct_authData: 230183234Ssimon return &cms->d.authenticatedData->encapContentInfo->eContent; 231183234Ssimon 232183234Ssimon case NID_id_smime_ct_compressedData: 233183234Ssimon return &cms->d.compressedData->encapContentInfo->eContent; 234183234Ssimon 235183234Ssimon default: 236183234Ssimon if (cms->d.other->type == V_ASN1_OCTET_STRING) 237183234Ssimon return &cms->d.other->value.octet_string; 238183234Ssimon CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE); 239183234Ssimon return NULL; 240183234Ssimon 241183234Ssimon } 242183234Ssimon } 243183234Ssimon 244183234Ssimon/* Return an ASN1_OBJECT pointer to content type. This allows it to 245183234Ssimon * be accessed or set later. 246183234Ssimon */ 247183234Ssimon 248183234Ssimonstatic ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) 249183234Ssimon { 250183234Ssimon switch (OBJ_obj2nid(cms->contentType)) 251183234Ssimon { 252183234Ssimon 253183234Ssimon case NID_pkcs7_signed: 254183234Ssimon return &cms->d.signedData->encapContentInfo->eContentType; 255183234Ssimon 256183234Ssimon case NID_pkcs7_enveloped: 257183234Ssimon return &cms->d.envelopedData->encryptedContentInfo->contentType; 258183234Ssimon 259183234Ssimon case NID_pkcs7_digest: 260183234Ssimon return &cms->d.digestedData->encapContentInfo->eContentType; 261183234Ssimon 262183234Ssimon case NID_pkcs7_encrypted: 263183234Ssimon return &cms->d.encryptedData->encryptedContentInfo->contentType; 264183234Ssimon 265183234Ssimon case NID_id_smime_ct_authData: 266183234Ssimon return &cms->d.authenticatedData->encapContentInfo->eContentType; 267183234Ssimon 268183234Ssimon case NID_id_smime_ct_compressedData: 269183234Ssimon return &cms->d.compressedData->encapContentInfo->eContentType; 270183234Ssimon 271183234Ssimon default: 272183234Ssimon CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, 273183234Ssimon CMS_R_UNSUPPORTED_CONTENT_TYPE); 274183234Ssimon return NULL; 275183234Ssimon 276183234Ssimon } 277183234Ssimon } 278183234Ssimon 279183234Ssimonconst ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) 280183234Ssimon { 281183234Ssimon ASN1_OBJECT **petype; 282183234Ssimon petype = cms_get0_econtent_type(cms); 283183234Ssimon if (petype) 284183234Ssimon return *petype; 285183234Ssimon return NULL; 286183234Ssimon } 287183234Ssimon 288183234Ssimonint CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) 289183234Ssimon { 290183234Ssimon ASN1_OBJECT **petype, *etype; 291183234Ssimon petype = cms_get0_econtent_type(cms); 292183234Ssimon if (!petype) 293183234Ssimon return 0; 294183234Ssimon if (!oid) 295183234Ssimon return 1; 296183234Ssimon etype = OBJ_dup(oid); 297183234Ssimon if (!etype) 298183234Ssimon return 0; 299183234Ssimon ASN1_OBJECT_free(*petype); 300183234Ssimon *petype = etype; 301183234Ssimon return 1; 302183234Ssimon } 303183234Ssimon 304183234Ssimonint CMS_is_detached(CMS_ContentInfo *cms) 305183234Ssimon { 306183234Ssimon ASN1_OCTET_STRING **pos; 307183234Ssimon pos = CMS_get0_content(cms); 308183234Ssimon if (!pos) 309183234Ssimon return -1; 310183234Ssimon if (*pos) 311183234Ssimon return 0; 312183234Ssimon return 1; 313183234Ssimon } 314183234Ssimon 315183234Ssimonint CMS_set_detached(CMS_ContentInfo *cms, int detached) 316183234Ssimon { 317183234Ssimon ASN1_OCTET_STRING **pos; 318183234Ssimon pos = CMS_get0_content(cms); 319183234Ssimon if (!pos) 320183234Ssimon return 0; 321183234Ssimon if (detached) 322183234Ssimon { 323183234Ssimon if (*pos) 324183234Ssimon { 325183234Ssimon ASN1_OCTET_STRING_free(*pos); 326183234Ssimon *pos = NULL; 327183234Ssimon } 328183234Ssimon return 1; 329183234Ssimon } 330183234Ssimon if (!*pos) 331183234Ssimon *pos = ASN1_OCTET_STRING_new(); 332183234Ssimon if (*pos) 333183234Ssimon { 334183234Ssimon /* NB: special flag to show content is created and not 335183234Ssimon * read in. 336183234Ssimon */ 337183234Ssimon (*pos)->flags |= ASN1_STRING_FLAG_CONT; 338183234Ssimon return 1; 339183234Ssimon } 340183234Ssimon CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE); 341183234Ssimon return 0; 342183234Ssimon } 343183234Ssimon 344183234Ssimon/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ 345183234Ssimon 346183234Ssimonvoid cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md) 347183234Ssimon { 348183234Ssimon int param_type; 349183234Ssimon 350238405Sjkim if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT) 351183234Ssimon param_type = V_ASN1_UNDEF; 352238405Sjkim else 353183234Ssimon param_type = V_ASN1_NULL; 354183234Ssimon 355183234Ssimon X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); 356183234Ssimon 357183234Ssimon } 358183234Ssimon 359183234Ssimon/* Create a digest BIO from an X509_ALGOR structure */ 360183234Ssimon 361183234SsimonBIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) 362183234Ssimon { 363183234Ssimon BIO *mdbio = NULL; 364183234Ssimon ASN1_OBJECT *digestoid; 365183234Ssimon const EVP_MD *digest; 366183234Ssimon X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); 367183234Ssimon digest = EVP_get_digestbyobj(digestoid); 368183234Ssimon if (!digest) 369183234Ssimon { 370183234Ssimon CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 371183234Ssimon CMS_R_UNKNOWN_DIGEST_ALGORIHM); 372183234Ssimon goto err; 373183234Ssimon } 374183234Ssimon mdbio = BIO_new(BIO_f_md()); 375183234Ssimon if (!mdbio || !BIO_set_md(mdbio, digest)) 376183234Ssimon { 377183234Ssimon CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 378183234Ssimon CMS_R_MD_BIO_INIT_ERROR); 379183234Ssimon goto err; 380183234Ssimon } 381183234Ssimon return mdbio; 382183234Ssimon err: 383183234Ssimon if (mdbio) 384183234Ssimon BIO_free(mdbio); 385183234Ssimon return NULL; 386183234Ssimon } 387183234Ssimon 388183234Ssimon/* Locate a message digest content from a BIO chain based on SignerInfo */ 389183234Ssimon 390183234Ssimonint cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, 391183234Ssimon X509_ALGOR *mdalg) 392183234Ssimon { 393183234Ssimon int nid; 394183234Ssimon ASN1_OBJECT *mdoid; 395183234Ssimon X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); 396183234Ssimon nid = OBJ_obj2nid(mdoid); 397183234Ssimon /* Look for digest type to match signature */ 398183234Ssimon for (;;) 399183234Ssimon { 400183234Ssimon EVP_MD_CTX *mtmp; 401183234Ssimon chain = BIO_find_type(chain, BIO_TYPE_MD); 402183234Ssimon if (chain == NULL) 403183234Ssimon { 404183234Ssimon CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, 405183234Ssimon CMS_R_NO_MATCHING_DIGEST); 406183234Ssimon return 0; 407183234Ssimon } 408183234Ssimon BIO_get_md_ctx(chain, &mtmp); 409205128Ssimon if (EVP_MD_CTX_type(mtmp) == nid 410205128Ssimon /* Workaround for broken implementations that use signature 411205128Ssimon * algorithm OID instead of digest. 412205128Ssimon */ 413205128Ssimon || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) 414238405Sjkim return EVP_MD_CTX_copy_ex(mctx, mtmp); 415183234Ssimon chain = BIO_next(chain); 416183234Ssimon } 417183234Ssimon } 418183234Ssimon 419183234Ssimonstatic STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms) 420183234Ssimon { 421183234Ssimon switch (OBJ_obj2nid(cms->contentType)) 422183234Ssimon { 423183234Ssimon 424183234Ssimon case NID_pkcs7_signed: 425183234Ssimon return &cms->d.signedData->certificates; 426183234Ssimon 427183234Ssimon case NID_pkcs7_enveloped: 428183234Ssimon return &cms->d.envelopedData->originatorInfo->certificates; 429183234Ssimon 430183234Ssimon default: 431183234Ssimon CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES, 432183234Ssimon CMS_R_UNSUPPORTED_CONTENT_TYPE); 433183234Ssimon return NULL; 434183234Ssimon 435183234Ssimon } 436183234Ssimon } 437183234Ssimon 438183234SsimonCMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) 439183234Ssimon { 440183234Ssimon STACK_OF(CMS_CertificateChoices) **pcerts; 441183234Ssimon CMS_CertificateChoices *cch; 442183234Ssimon pcerts = cms_get0_certificate_choices(cms); 443183234Ssimon if (!pcerts) 444183234Ssimon return NULL; 445183234Ssimon if (!*pcerts) 446183234Ssimon *pcerts = sk_CMS_CertificateChoices_new_null(); 447183234Ssimon if (!*pcerts) 448183234Ssimon return NULL; 449183234Ssimon cch = M_ASN1_new_of(CMS_CertificateChoices); 450183234Ssimon if (!cch) 451183234Ssimon return NULL; 452183234Ssimon if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) 453183234Ssimon { 454183234Ssimon M_ASN1_free_of(cch, CMS_CertificateChoices); 455183234Ssimon return NULL; 456183234Ssimon } 457183234Ssimon return cch; 458183234Ssimon } 459183234Ssimon 460183234Ssimonint CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 461183234Ssimon { 462183234Ssimon CMS_CertificateChoices *cch; 463183234Ssimon STACK_OF(CMS_CertificateChoices) **pcerts; 464183234Ssimon int i; 465183234Ssimon pcerts = cms_get0_certificate_choices(cms); 466183234Ssimon if (!pcerts) 467183234Ssimon return 0; 468183234Ssimon for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) 469183234Ssimon { 470183234Ssimon cch = sk_CMS_CertificateChoices_value(*pcerts, i); 471183234Ssimon if (cch->type == CMS_CERTCHOICE_CERT) 472183234Ssimon { 473183234Ssimon if (!X509_cmp(cch->d.certificate, cert)) 474183234Ssimon { 475183234Ssimon CMSerr(CMS_F_CMS_ADD0_CERT, 476183234Ssimon CMS_R_CERTIFICATE_ALREADY_PRESENT); 477183234Ssimon return 0; 478183234Ssimon } 479183234Ssimon } 480183234Ssimon } 481183234Ssimon cch = CMS_add0_CertificateChoices(cms); 482183234Ssimon if (!cch) 483183234Ssimon return 0; 484183234Ssimon cch->type = CMS_CERTCHOICE_CERT; 485183234Ssimon cch->d.certificate = cert; 486183234Ssimon return 1; 487183234Ssimon } 488183234Ssimon 489183234Ssimonint CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) 490183234Ssimon { 491183234Ssimon int r; 492183234Ssimon r = CMS_add0_cert(cms, cert); 493183234Ssimon if (r > 0) 494183234Ssimon CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); 495183234Ssimon return r; 496183234Ssimon } 497183234Ssimon 498183234Ssimonstatic STACK_OF(CMS_RevocationInfoChoice) **cms_get0_revocation_choices(CMS_ContentInfo *cms) 499183234Ssimon { 500183234Ssimon switch (OBJ_obj2nid(cms->contentType)) 501183234Ssimon { 502183234Ssimon 503183234Ssimon case NID_pkcs7_signed: 504183234Ssimon return &cms->d.signedData->crls; 505183234Ssimon 506183234Ssimon case NID_pkcs7_enveloped: 507183234Ssimon return &cms->d.envelopedData->originatorInfo->crls; 508183234Ssimon 509183234Ssimon default: 510183234Ssimon CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES, 511183234Ssimon CMS_R_UNSUPPORTED_CONTENT_TYPE); 512183234Ssimon return NULL; 513183234Ssimon 514183234Ssimon } 515183234Ssimon } 516183234Ssimon 517183234SsimonCMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) 518183234Ssimon { 519183234Ssimon STACK_OF(CMS_RevocationInfoChoice) **pcrls; 520183234Ssimon CMS_RevocationInfoChoice *rch; 521183234Ssimon pcrls = cms_get0_revocation_choices(cms); 522183234Ssimon if (!pcrls) 523183234Ssimon return NULL; 524183234Ssimon if (!*pcrls) 525183234Ssimon *pcrls = sk_CMS_RevocationInfoChoice_new_null(); 526183234Ssimon if (!*pcrls) 527183234Ssimon return NULL; 528183234Ssimon rch = M_ASN1_new_of(CMS_RevocationInfoChoice); 529183234Ssimon if (!rch) 530183234Ssimon return NULL; 531183234Ssimon if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) 532183234Ssimon { 533183234Ssimon M_ASN1_free_of(rch, CMS_RevocationInfoChoice); 534183234Ssimon return NULL; 535183234Ssimon } 536183234Ssimon return rch; 537183234Ssimon } 538183234Ssimon 539183234Ssimonint CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) 540183234Ssimon { 541183234Ssimon CMS_RevocationInfoChoice *rch; 542183234Ssimon rch = CMS_add0_RevocationInfoChoice(cms); 543183234Ssimon if (!rch) 544183234Ssimon return 0; 545183234Ssimon rch->type = CMS_REVCHOICE_CRL; 546183234Ssimon rch->d.crl = crl; 547183234Ssimon return 1; 548183234Ssimon } 549183234Ssimon 550238405Sjkimint CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) 551238405Sjkim { 552238405Sjkim int r; 553238405Sjkim r = CMS_add0_crl(cms, crl); 554238405Sjkim if (r > 0) 555238405Sjkim CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); 556238405Sjkim return r; 557238405Sjkim } 558238405Sjkim 559183234SsimonSTACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) 560183234Ssimon { 561183234Ssimon STACK_OF(X509) *certs = NULL; 562183234Ssimon CMS_CertificateChoices *cch; 563183234Ssimon STACK_OF(CMS_CertificateChoices) **pcerts; 564183234Ssimon int i; 565183234Ssimon pcerts = cms_get0_certificate_choices(cms); 566183234Ssimon if (!pcerts) 567183234Ssimon return NULL; 568183234Ssimon for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) 569183234Ssimon { 570183234Ssimon cch = sk_CMS_CertificateChoices_value(*pcerts, i); 571183234Ssimon if (cch->type == 0) 572183234Ssimon { 573183234Ssimon if (!certs) 574183234Ssimon { 575183234Ssimon certs = sk_X509_new_null(); 576183234Ssimon if (!certs) 577183234Ssimon return NULL; 578183234Ssimon } 579183234Ssimon if (!sk_X509_push(certs, cch->d.certificate)) 580183234Ssimon { 581183234Ssimon sk_X509_pop_free(certs, X509_free); 582183234Ssimon return NULL; 583183234Ssimon } 584183234Ssimon CRYPTO_add(&cch->d.certificate->references, 585183234Ssimon 1, CRYPTO_LOCK_X509); 586183234Ssimon } 587183234Ssimon } 588183234Ssimon return certs; 589183234Ssimon 590183234Ssimon } 591183234Ssimon 592183234SsimonSTACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) 593183234Ssimon { 594183234Ssimon STACK_OF(X509_CRL) *crls = NULL; 595183234Ssimon STACK_OF(CMS_RevocationInfoChoice) **pcrls; 596183234Ssimon CMS_RevocationInfoChoice *rch; 597183234Ssimon int i; 598183234Ssimon pcrls = cms_get0_revocation_choices(cms); 599183234Ssimon if (!pcrls) 600183234Ssimon return NULL; 601183234Ssimon for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) 602183234Ssimon { 603183234Ssimon rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); 604183234Ssimon if (rch->type == 0) 605183234Ssimon { 606183234Ssimon if (!crls) 607183234Ssimon { 608183234Ssimon crls = sk_X509_CRL_new_null(); 609183234Ssimon if (!crls) 610183234Ssimon return NULL; 611183234Ssimon } 612183234Ssimon if (!sk_X509_CRL_push(crls, rch->d.crl)) 613183234Ssimon { 614183234Ssimon sk_X509_CRL_pop_free(crls, X509_CRL_free); 615183234Ssimon return NULL; 616183234Ssimon } 617183234Ssimon CRYPTO_add(&rch->d.crl->references, 618183234Ssimon 1, CRYPTO_LOCK_X509_CRL); 619183234Ssimon } 620183234Ssimon } 621183234Ssimon return crls; 622183234Ssimon } 623