1*7a9020cdStb /* $OpenBSD: cms_lib.c,v 1.26 2024/11/01 18:53:35 tb Exp $ */ 2b8b016bfSjsing /* 3f29d8588Sjsing * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4f29d8588Sjsing * project. 5f29d8588Sjsing */ 6f29d8588Sjsing /* ==================================================================== 7f29d8588Sjsing * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8b8b016bfSjsing * 9f29d8588Sjsing * Redistribution and use in source and binary forms, with or without 10f29d8588Sjsing * modification, are permitted provided that the following conditions 11f29d8588Sjsing * are met: 12f29d8588Sjsing * 13f29d8588Sjsing * 1. Redistributions of source code must retain the above copyright 14f29d8588Sjsing * notice, this list of conditions and the following disclaimer. 15f29d8588Sjsing * 16f29d8588Sjsing * 2. Redistributions in binary form must reproduce the above copyright 17f29d8588Sjsing * notice, this list of conditions and the following disclaimer in 18f29d8588Sjsing * the documentation and/or other materials provided with the 19f29d8588Sjsing * distribution. 20f29d8588Sjsing * 21f29d8588Sjsing * 3. All advertising materials mentioning features or use of this 22f29d8588Sjsing * software must display the following acknowledgment: 23f29d8588Sjsing * "This product includes software developed by the OpenSSL Project 24f29d8588Sjsing * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25f29d8588Sjsing * 26f29d8588Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27f29d8588Sjsing * endorse or promote products derived from this software without 28f29d8588Sjsing * prior written permission. For written permission, please contact 29f29d8588Sjsing * licensing@OpenSSL.org. 30f29d8588Sjsing * 31f29d8588Sjsing * 5. Products derived from this software may not be called "OpenSSL" 32f29d8588Sjsing * nor may "OpenSSL" appear in their names without prior written 33f29d8588Sjsing * permission of the OpenSSL Project. 34f29d8588Sjsing * 35f29d8588Sjsing * 6. Redistributions of any form whatsoever must retain the following 36f29d8588Sjsing * acknowledgment: 37f29d8588Sjsing * "This product includes software developed by the OpenSSL Project 38f29d8588Sjsing * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39f29d8588Sjsing * 40f29d8588Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41f29d8588Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42f29d8588Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43f29d8588Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44f29d8588Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45f29d8588Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46f29d8588Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47f29d8588Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48f29d8588Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49f29d8588Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50f29d8588Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51f29d8588Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE. 52f29d8588Sjsing * ==================================================================== 53b8b016bfSjsing */ 54b8b016bfSjsing 55*7a9020cdStb #include <stddef.h> 56*7a9020cdStb 57b8b016bfSjsing #include <openssl/asn1.h> 58*7a9020cdStb #include <openssl/bio.h> 59b8b016bfSjsing #include <openssl/cms.h> 60*7a9020cdStb #include <openssl/err.h> 61*7a9020cdStb #include <openssl/evp.h> 62*7a9020cdStb #include <openssl/objects.h> 63*7a9020cdStb #include <openssl/x509.h> 64*7a9020cdStb #include <openssl/x509v3.h> 65b8b016bfSjsing 66c9675a23Stb #include "cms_local.h" 67c9675a23Stb #include "x509_local.h" 680a940e1fSjsing 690a940e1fSjsing CMS_ContentInfo * 700a940e1fSjsing d2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len) 710a940e1fSjsing { 720a940e1fSjsing return (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 730a940e1fSjsing &CMS_ContentInfo_it); 740a940e1fSjsing } 75ead8f799Sbeck LCRYPTO_ALIAS(d2i_CMS_ContentInfo); 760a940e1fSjsing 770a940e1fSjsing int 780a940e1fSjsing i2d_CMS_ContentInfo(CMS_ContentInfo *a, unsigned char **out) 790a940e1fSjsing { 800a940e1fSjsing return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ContentInfo_it); 810a940e1fSjsing } 82ead8f799Sbeck LCRYPTO_ALIAS(i2d_CMS_ContentInfo); 830a940e1fSjsing 840a940e1fSjsing CMS_ContentInfo * 850a940e1fSjsing CMS_ContentInfo_new(void) 860a940e1fSjsing { 870a940e1fSjsing return (CMS_ContentInfo *)ASN1_item_new(&CMS_ContentInfo_it); 880a940e1fSjsing } 89ead8f799Sbeck LCRYPTO_ALIAS(CMS_ContentInfo_new); 900a940e1fSjsing 910a940e1fSjsing void 920a940e1fSjsing CMS_ContentInfo_free(CMS_ContentInfo *a) 930a940e1fSjsing { 940a940e1fSjsing ASN1_item_free((ASN1_VALUE *)a, &CMS_ContentInfo_it); 950a940e1fSjsing } 96ead8f799Sbeck LCRYPTO_ALIAS(CMS_ContentInfo_free); 970a940e1fSjsing 980a940e1fSjsing int 990a940e1fSjsing CMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const ASN1_PCTX *pctx) 1000a940e1fSjsing { 1010a940e1fSjsing return ASN1_item_print(out, (ASN1_VALUE *)x, indent, 1020a940e1fSjsing &CMS_ContentInfo_it, pctx); 1030a940e1fSjsing } 104ead8f799Sbeck LCRYPTO_ALIAS(CMS_ContentInfo_print_ctx); 105b8b016bfSjsing 10672419cc7Sjsing const ASN1_OBJECT * 10772419cc7Sjsing CMS_get0_type(const CMS_ContentInfo *cms) 108b8b016bfSjsing { 109b8b016bfSjsing return cms->contentType; 110b8b016bfSjsing } 111ead8f799Sbeck LCRYPTO_ALIAS(CMS_get0_type); 112b8b016bfSjsing 11372419cc7Sjsing CMS_ContentInfo * 11472419cc7Sjsing cms_Data_create(void) 115b8b016bfSjsing { 116b8b016bfSjsing CMS_ContentInfo *cms; 11772419cc7Sjsing 118b8b016bfSjsing cms = CMS_ContentInfo_new(); 119b8b016bfSjsing if (cms != NULL) { 120b8b016bfSjsing cms->contentType = OBJ_nid2obj(NID_pkcs7_data); 121b8b016bfSjsing /* Never detached */ 122b8b016bfSjsing CMS_set_detached(cms, 0); 123b8b016bfSjsing } 124b8b016bfSjsing return cms; 125b8b016bfSjsing } 126b8b016bfSjsing 12790fa8d06Stb static BIO * 12872419cc7Sjsing cms_content_bio(CMS_ContentInfo *cms) 129b8b016bfSjsing { 1303a0e71e8Stb ASN1_OCTET_STRING **pos; 13172419cc7Sjsing 1323a0e71e8Stb if ((pos = CMS_get0_content(cms)) == NULL) 133b8b016bfSjsing return NULL; 1343a0e71e8Stb 1353a0e71e8Stb /* If content is detached, data goes nowhere: create null BIO. */ 1363a0e71e8Stb if (*pos == NULL) 137b8b016bfSjsing return BIO_new(BIO_s_null()); 1383a0e71e8Stb 1393a0e71e8Stb /* If content is not detached and was created, return memory BIO. */ 1403a0e71e8Stb if ((*pos)->flags == ASN1_STRING_FLAG_CONT) 141b8b016bfSjsing return BIO_new(BIO_s_mem()); 14272419cc7Sjsing 1433a0e71e8Stb /* Else content was read in: return read-only BIO for it. */ 144b8b016bfSjsing return BIO_new_mem_buf((*pos)->data, (*pos)->length); 145b8b016bfSjsing } 146b8b016bfSjsing 14772419cc7Sjsing BIO * 14837128564Stb CMS_dataInit(CMS_ContentInfo *cms, BIO *in_content_bio) 149b8b016bfSjsing { 15037128564Stb BIO *cms_bio = NULL, *content_bio = NULL; 15172419cc7Sjsing 15237128564Stb if ((content_bio = in_content_bio) == NULL) 15337128564Stb content_bio = cms_content_bio(cms); 15437128564Stb if (content_bio == NULL) { 155be6ec861Sjsing CMSerror(CMS_R_NO_CONTENT); 1566590b22dStb goto err; 157b8b016bfSjsing } 158b8b016bfSjsing 15971d39bbeStb switch (OBJ_obj2nid(cms->contentType)) { 160b8b016bfSjsing case NID_pkcs7_data: 16137128564Stb return content_bio; 162b8b016bfSjsing case NID_pkcs7_signed: 16337128564Stb if ((cms_bio = cms_SignedData_init_bio(cms)) == NULL) 16471d39bbeStb goto err; 165b8b016bfSjsing break; 166b8b016bfSjsing case NID_pkcs7_digest: 16737128564Stb if ((cms_bio = cms_DigestedData_init_bio(cms)) == NULL) 16871d39bbeStb goto err; 169b8b016bfSjsing break; 170b8b016bfSjsing case NID_pkcs7_encrypted: 17137128564Stb if ((cms_bio = cms_EncryptedData_init_bio(cms)) == NULL) 17271d39bbeStb goto err; 173b8b016bfSjsing break; 174b8b016bfSjsing case NID_pkcs7_enveloped: 17537128564Stb if ((cms_bio = cms_EnvelopedData_init_bio(cms)) == NULL) 17671d39bbeStb goto err; 177b8b016bfSjsing break; 178b8b016bfSjsing default: 179be6ec861Sjsing CMSerror(CMS_R_UNSUPPORTED_TYPE); 1806590b22dStb goto err; 181b8b016bfSjsing } 182b8b016bfSjsing 18337128564Stb return BIO_push(cms_bio, content_bio); 184b8b016bfSjsing 1856590b22dStb err: 18637128564Stb if (content_bio != in_content_bio) 18737128564Stb BIO_free(content_bio); 188b8b016bfSjsing 18972419cc7Sjsing return NULL; 190b8b016bfSjsing } 191ead8f799Sbeck LCRYPTO_ALIAS(CMS_dataInit); 192b8b016bfSjsing 19372419cc7Sjsing int 19472419cc7Sjsing CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) 195b8b016bfSjsing { 196b8b016bfSjsing ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 19772419cc7Sjsing 198b8b016bfSjsing if (!pos) 199b8b016bfSjsing return 0; 200b8b016bfSjsing /* If embedded content find memory BIO and set content */ 201b8b016bfSjsing if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { 202b8b016bfSjsing BIO *mbio; 203b8b016bfSjsing unsigned char *cont; 204b8b016bfSjsing long contlen; 205b8b016bfSjsing mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); 206b8b016bfSjsing if (!mbio) { 207be6ec861Sjsing CMSerror(CMS_R_CONTENT_NOT_FOUND); 208b8b016bfSjsing return 0; 209b8b016bfSjsing } 210b8b016bfSjsing contlen = BIO_get_mem_data(mbio, &cont); 211b8b016bfSjsing /* Set bio as read only so its content can't be clobbered */ 212b8b016bfSjsing BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); 213b8b016bfSjsing BIO_set_mem_eof_return(mbio, 0); 214b8b016bfSjsing ASN1_STRING_set0(*pos, cont, contlen); 215b8b016bfSjsing (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; 216b8b016bfSjsing } 217b8b016bfSjsing 218b8b016bfSjsing switch (OBJ_obj2nid(cms->contentType)) { 219b8b016bfSjsing 220b8b016bfSjsing case NID_pkcs7_data: 221b8b016bfSjsing case NID_pkcs7_enveloped: 222b8b016bfSjsing case NID_pkcs7_encrypted: 223b8b016bfSjsing case NID_id_smime_ct_compressedData: 224b8b016bfSjsing /* Nothing to do */ 225b8b016bfSjsing return 1; 226b8b016bfSjsing 227b8b016bfSjsing case NID_pkcs7_signed: 228b8b016bfSjsing return cms_SignedData_final(cms, cmsbio); 229b8b016bfSjsing 230b8b016bfSjsing case NID_pkcs7_digest: 231b8b016bfSjsing return cms_DigestedData_do_final(cms, cmsbio, 0); 232b8b016bfSjsing 233b8b016bfSjsing default: 234be6ec861Sjsing CMSerror(CMS_R_UNSUPPORTED_TYPE); 235b8b016bfSjsing return 0; 236b8b016bfSjsing } 237b8b016bfSjsing } 238ead8f799Sbeck LCRYPTO_ALIAS(CMS_dataFinal); 239b8b016bfSjsing 2405e651e03Stb int 2415e651e03Stb CMS_get_version(const CMS_ContentInfo *cms, long *version) 2425e651e03Stb { 2435e651e03Stb switch (OBJ_obj2nid(cms->contentType)) { 2445e651e03Stb case NID_pkcs7_signed: 2455e651e03Stb *version = cms->d.signedData->version; 2465e651e03Stb return 1; 2475e651e03Stb 2485e651e03Stb case NID_pkcs7_enveloped: 2495e651e03Stb *version = cms->d.envelopedData->version; 2505e651e03Stb return 1; 2515e651e03Stb 2525e651e03Stb case NID_pkcs7_digest: 2535e651e03Stb *version = cms->d.digestedData->version; 2545e651e03Stb return 1; 2555e651e03Stb 2565e651e03Stb case NID_pkcs7_encrypted: 2575e651e03Stb *version = cms->d.encryptedData->version; 2585e651e03Stb return 1; 2595e651e03Stb 2605e651e03Stb case NID_id_smime_ct_authData: 2615e651e03Stb *version = cms->d.authenticatedData->version; 2625e651e03Stb return 1; 2635e651e03Stb 2645e651e03Stb case NID_id_smime_ct_compressedData: 2655e651e03Stb *version = cms->d.compressedData->version; 2665e651e03Stb return 1; 2675e651e03Stb 2685e651e03Stb default: 2695e651e03Stb CMSerror(CMS_R_UNSUPPORTED_TYPE); 2705e651e03Stb return 0; 2715e651e03Stb } 2725e651e03Stb } 2735e651e03Stb LCRYPTO_ALIAS(CMS_get_version); 2745e651e03Stb 2755e651e03Stb int 2765e651e03Stb CMS_SignerInfo_get_version(const CMS_SignerInfo *si, long *version) 2775e651e03Stb { 2785e651e03Stb *version = si->version; 2795e651e03Stb return 1; 2805e651e03Stb } 2815e651e03Stb LCRYPTO_ALIAS(CMS_SignerInfo_get_version); 2825e651e03Stb 283b8b016bfSjsing /* 284b8b016bfSjsing * Return an OCTET STRING pointer to content. This allows it to be accessed 285b8b016bfSjsing * or set later. 286b8b016bfSjsing */ 287b8b016bfSjsing 28872419cc7Sjsing ASN1_OCTET_STRING ** 28972419cc7Sjsing CMS_get0_content(CMS_ContentInfo *cms) 290b8b016bfSjsing { 291b8b016bfSjsing switch (OBJ_obj2nid(cms->contentType)) { 292b8b016bfSjsing case NID_pkcs7_data: 293b8b016bfSjsing return &cms->d.data; 294b8b016bfSjsing 295b8b016bfSjsing case NID_pkcs7_signed: 296b8b016bfSjsing return &cms->d.signedData->encapContentInfo->eContent; 297b8b016bfSjsing 298b8b016bfSjsing case NID_pkcs7_enveloped: 299b8b016bfSjsing return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; 300b8b016bfSjsing 301b8b016bfSjsing case NID_pkcs7_digest: 302b8b016bfSjsing return &cms->d.digestedData->encapContentInfo->eContent; 303b8b016bfSjsing 304b8b016bfSjsing case NID_pkcs7_encrypted: 305b8b016bfSjsing return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; 306b8b016bfSjsing 307b8b016bfSjsing case NID_id_smime_ct_authData: 308b8b016bfSjsing return &cms->d.authenticatedData->encapContentInfo->eContent; 309b8b016bfSjsing 310b8b016bfSjsing case NID_id_smime_ct_compressedData: 311b8b016bfSjsing return &cms->d.compressedData->encapContentInfo->eContent; 312b8b016bfSjsing 313b8b016bfSjsing default: 314b8b016bfSjsing if (cms->d.other->type == V_ASN1_OCTET_STRING) 315b8b016bfSjsing return &cms->d.other->value.octet_string; 316be6ec861Sjsing CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 317b8b016bfSjsing return NULL; 318b8b016bfSjsing } 319b8b016bfSjsing } 3207bfedc82Sjoshua LCRYPTO_ALIAS(CMS_get0_content); 321b8b016bfSjsing 322b8b016bfSjsing /* 323b8b016bfSjsing * Return an ASN1_OBJECT pointer to content type. This allows it to be 324b8b016bfSjsing * accessed or set later. 325b8b016bfSjsing */ 326b8b016bfSjsing 32772419cc7Sjsing static ASN1_OBJECT ** 32872419cc7Sjsing cms_get0_econtent_type(CMS_ContentInfo *cms) 329b8b016bfSjsing { 330b8b016bfSjsing switch (OBJ_obj2nid(cms->contentType)) { 331b8b016bfSjsing case NID_pkcs7_signed: 332b8b016bfSjsing return &cms->d.signedData->encapContentInfo->eContentType; 333b8b016bfSjsing 334b8b016bfSjsing case NID_pkcs7_enveloped: 335b8b016bfSjsing return &cms->d.envelopedData->encryptedContentInfo->contentType; 336b8b016bfSjsing 337b8b016bfSjsing case NID_pkcs7_digest: 338b8b016bfSjsing return &cms->d.digestedData->encapContentInfo->eContentType; 339b8b016bfSjsing 340b8b016bfSjsing case NID_pkcs7_encrypted: 341b8b016bfSjsing return &cms->d.encryptedData->encryptedContentInfo->contentType; 342b8b016bfSjsing 343b8b016bfSjsing case NID_id_smime_ct_authData: 344b8b016bfSjsing return &cms->d.authenticatedData->encapContentInfo->eContentType; 345b8b016bfSjsing 346b8b016bfSjsing case NID_id_smime_ct_compressedData: 347b8b016bfSjsing return &cms->d.compressedData->encapContentInfo->eContentType; 348b8b016bfSjsing 349b8b016bfSjsing default: 350be6ec861Sjsing CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 351b8b016bfSjsing return NULL; 352b8b016bfSjsing } 353b8b016bfSjsing } 354b8b016bfSjsing 35572419cc7Sjsing const ASN1_OBJECT * 35672419cc7Sjsing CMS_get0_eContentType(CMS_ContentInfo *cms) 357b8b016bfSjsing { 358b8b016bfSjsing ASN1_OBJECT **petype; 35972419cc7Sjsing 360b8b016bfSjsing petype = cms_get0_econtent_type(cms); 361b8b016bfSjsing if (petype) 362b8b016bfSjsing return *petype; 36372419cc7Sjsing 364b8b016bfSjsing return NULL; 365b8b016bfSjsing } 366ead8f799Sbeck LCRYPTO_ALIAS(CMS_get0_eContentType); 367b8b016bfSjsing 36872419cc7Sjsing int 36972419cc7Sjsing CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) 370b8b016bfSjsing { 371b8b016bfSjsing ASN1_OBJECT **petype, *etype; 37272419cc7Sjsing 373b8b016bfSjsing petype = cms_get0_econtent_type(cms); 374b8b016bfSjsing if (!petype) 375b8b016bfSjsing return 0; 376b8b016bfSjsing if (!oid) 377b8b016bfSjsing return 1; 378b8b016bfSjsing etype = OBJ_dup(oid); 379b8b016bfSjsing if (!etype) 380b8b016bfSjsing return 0; 381b8b016bfSjsing ASN1_OBJECT_free(*petype); 382b8b016bfSjsing *petype = etype; 38372419cc7Sjsing 384b8b016bfSjsing return 1; 385b8b016bfSjsing } 386ead8f799Sbeck LCRYPTO_ALIAS(CMS_set1_eContentType); 387b8b016bfSjsing 38872419cc7Sjsing int 38972419cc7Sjsing CMS_is_detached(CMS_ContentInfo *cms) 390b8b016bfSjsing { 391b8b016bfSjsing ASN1_OCTET_STRING **pos; 39272419cc7Sjsing 393b8b016bfSjsing pos = CMS_get0_content(cms); 394b8b016bfSjsing if (!pos) 395b8b016bfSjsing return -1; 396b8b016bfSjsing if (*pos) 397b8b016bfSjsing return 0; 39872419cc7Sjsing 399b8b016bfSjsing return 1; 400b8b016bfSjsing } 401ead8f799Sbeck LCRYPTO_ALIAS(CMS_is_detached); 402b8b016bfSjsing 40372419cc7Sjsing int 40472419cc7Sjsing CMS_set_detached(CMS_ContentInfo *cms, int detached) 405b8b016bfSjsing { 406b8b016bfSjsing ASN1_OCTET_STRING **pos; 40772419cc7Sjsing 408b8b016bfSjsing pos = CMS_get0_content(cms); 409b8b016bfSjsing if (!pos) 410b8b016bfSjsing return 0; 411b8b016bfSjsing if (detached) { 412b8b016bfSjsing ASN1_OCTET_STRING_free(*pos); 413b8b016bfSjsing *pos = NULL; 414b8b016bfSjsing return 1; 415b8b016bfSjsing } 416b8b016bfSjsing if (*pos == NULL) 417b8b016bfSjsing *pos = ASN1_OCTET_STRING_new(); 418b8b016bfSjsing if (*pos != NULL) { 419b8b016bfSjsing /* 420b8b016bfSjsing * NB: special flag to show content is created and not read in. 421b8b016bfSjsing */ 422b8b016bfSjsing (*pos)->flags |= ASN1_STRING_FLAG_CONT; 423b8b016bfSjsing return 1; 424b8b016bfSjsing } 425be6ec861Sjsing CMSerror(ERR_R_MALLOC_FAILURE); 42672419cc7Sjsing 427b8b016bfSjsing return 0; 428b8b016bfSjsing } 429ead8f799Sbeck LCRYPTO_ALIAS(CMS_set_detached); 430b8b016bfSjsing 431b8b016bfSjsing /* Create a digest BIO from an X509_ALGOR structure */ 432b8b016bfSjsing 43372419cc7Sjsing BIO * 43472419cc7Sjsing cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) 435b8b016bfSjsing { 436b8b016bfSjsing BIO *mdbio = NULL; 437b8b016bfSjsing const ASN1_OBJECT *digestoid; 438b8b016bfSjsing const EVP_MD *digest; 43972419cc7Sjsing 440b8b016bfSjsing X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); 441b8b016bfSjsing digest = EVP_get_digestbyobj(digestoid); 442b8b016bfSjsing if (!digest) { 443be6ec861Sjsing CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM); 444b8b016bfSjsing goto err; 445b8b016bfSjsing } 446b8b016bfSjsing mdbio = BIO_new(BIO_f_md()); 447b8b016bfSjsing if (mdbio == NULL || !BIO_set_md(mdbio, digest)) { 448be6ec861Sjsing CMSerror(CMS_R_MD_BIO_INIT_ERROR); 449b8b016bfSjsing goto err; 450b8b016bfSjsing } 451b8b016bfSjsing return mdbio; 45272419cc7Sjsing 453b8b016bfSjsing err: 454b8b016bfSjsing BIO_free(mdbio); 45572419cc7Sjsing 456b8b016bfSjsing return NULL; 457b8b016bfSjsing } 458b8b016bfSjsing 459b8b016bfSjsing /* Locate a message digest content from a BIO chain based on SignerInfo */ 460b8b016bfSjsing 46172419cc7Sjsing int 46272419cc7Sjsing cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg) 463b8b016bfSjsing { 464b8b016bfSjsing int nid; 465b8b016bfSjsing const ASN1_OBJECT *mdoid; 46672419cc7Sjsing 467b8b016bfSjsing X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); 468b8b016bfSjsing nid = OBJ_obj2nid(mdoid); 469b8b016bfSjsing /* Look for digest type to match signature */ 470b8b016bfSjsing for (;;) { 471b8b016bfSjsing EVP_MD_CTX *mtmp; 472b8b016bfSjsing chain = BIO_find_type(chain, BIO_TYPE_MD); 473b8b016bfSjsing if (chain == NULL) { 474be6ec861Sjsing CMSerror(CMS_R_NO_MATCHING_DIGEST); 475b8b016bfSjsing return 0; 476b8b016bfSjsing } 477b8b016bfSjsing BIO_get_md_ctx(chain, &mtmp); 478b8b016bfSjsing if (EVP_MD_CTX_type(mtmp) == nid 479b8b016bfSjsing /* 480b8b016bfSjsing * Workaround for broken implementations that use signature 481b8b016bfSjsing * algorithm OID instead of digest. 482b8b016bfSjsing */ 483b8b016bfSjsing || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) 484b8b016bfSjsing return EVP_MD_CTX_copy_ex(mctx, mtmp); 485b8b016bfSjsing chain = BIO_next(chain); 486b8b016bfSjsing } 487b8b016bfSjsing } 488b8b016bfSjsing 48972419cc7Sjsing static STACK_OF(CMS_CertificateChoices) ** 49072419cc7Sjsing cms_get0_certificate_choices(CMS_ContentInfo *cms) 491b8b016bfSjsing { 492b8b016bfSjsing switch (OBJ_obj2nid(cms->contentType)) { 493b8b016bfSjsing case NID_pkcs7_signed: 494b8b016bfSjsing return &cms->d.signedData->certificates; 495b8b016bfSjsing 496b8b016bfSjsing case NID_pkcs7_enveloped: 497b8b016bfSjsing if (cms->d.envelopedData->originatorInfo == NULL) 498b8b016bfSjsing return NULL; 499b8b016bfSjsing return &cms->d.envelopedData->originatorInfo->certificates; 500b8b016bfSjsing 501b8b016bfSjsing default: 502be6ec861Sjsing CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 503b8b016bfSjsing return NULL; 504b8b016bfSjsing } 505b8b016bfSjsing } 506b8b016bfSjsing 50772419cc7Sjsing CMS_CertificateChoices * 50872419cc7Sjsing CMS_add0_CertificateChoices(CMS_ContentInfo *cms) 509b8b016bfSjsing { 510b8b016bfSjsing STACK_OF(CMS_CertificateChoices) **pcerts; 511b8b016bfSjsing CMS_CertificateChoices *cch; 51272419cc7Sjsing 513b8b016bfSjsing pcerts = cms_get0_certificate_choices(cms); 514b8b016bfSjsing if (!pcerts) 515b8b016bfSjsing return NULL; 516b8b016bfSjsing if (!*pcerts) 517b8b016bfSjsing *pcerts = sk_CMS_CertificateChoices_new_null(); 518b8b016bfSjsing if (!*pcerts) 519b8b016bfSjsing return NULL; 520f2f5f7c4Sjsing cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it); 521b8b016bfSjsing if (!cch) 522b8b016bfSjsing return NULL; 523b8b016bfSjsing if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { 524f2f5f7c4Sjsing ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it); 525b8b016bfSjsing return NULL; 526b8b016bfSjsing } 52772419cc7Sjsing 528b8b016bfSjsing return cch; 529b8b016bfSjsing } 530ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_CertificateChoices); 531b8b016bfSjsing 53272419cc7Sjsing int 53372419cc7Sjsing CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 534b8b016bfSjsing { 535b8b016bfSjsing CMS_CertificateChoices *cch; 536b8b016bfSjsing STACK_OF(CMS_CertificateChoices) **pcerts; 537b8b016bfSjsing int i; 53872419cc7Sjsing 539b8b016bfSjsing pcerts = cms_get0_certificate_choices(cms); 540b8b016bfSjsing if (!pcerts) 541b8b016bfSjsing return 0; 542b8b016bfSjsing for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 543b8b016bfSjsing cch = sk_CMS_CertificateChoices_value(*pcerts, i); 544b8b016bfSjsing if (cch->type == CMS_CERTCHOICE_CERT) { 545b8b016bfSjsing if (!X509_cmp(cch->d.certificate, cert)) { 546be6ec861Sjsing CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT); 547b8b016bfSjsing return 0; 548b8b016bfSjsing } 549b8b016bfSjsing } 550b8b016bfSjsing } 551b8b016bfSjsing cch = CMS_add0_CertificateChoices(cms); 552b8b016bfSjsing if (!cch) 553b8b016bfSjsing return 0; 554b8b016bfSjsing cch->type = CMS_CERTCHOICE_CERT; 555b8b016bfSjsing cch->d.certificate = cert; 55672419cc7Sjsing 557b8b016bfSjsing return 1; 558b8b016bfSjsing } 559ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_cert); 560b8b016bfSjsing 56172419cc7Sjsing int 56272419cc7Sjsing CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) 563b8b016bfSjsing { 564b8b016bfSjsing int r; 56572419cc7Sjsing 566b8b016bfSjsing r = CMS_add0_cert(cms, cert); 567b8b016bfSjsing if (r > 0) 568b8b016bfSjsing X509_up_ref(cert); 56972419cc7Sjsing 570b8b016bfSjsing return r; 571b8b016bfSjsing } 572ead8f799Sbeck LCRYPTO_ALIAS(CMS_add1_cert); 573b8b016bfSjsing 57472419cc7Sjsing static STACK_OF(CMS_RevocationInfoChoice) ** 57572419cc7Sjsing cms_get0_revocation_choices(CMS_ContentInfo *cms) 576b8b016bfSjsing { 577b8b016bfSjsing switch (OBJ_obj2nid(cms->contentType)) { 578b8b016bfSjsing case NID_pkcs7_signed: 579b8b016bfSjsing return &cms->d.signedData->crls; 580b8b016bfSjsing 581b8b016bfSjsing case NID_pkcs7_enveloped: 582b8b016bfSjsing if (cms->d.envelopedData->originatorInfo == NULL) 583b8b016bfSjsing return NULL; 584b8b016bfSjsing return &cms->d.envelopedData->originatorInfo->crls; 585b8b016bfSjsing 586b8b016bfSjsing default: 587be6ec861Sjsing CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE); 588b8b016bfSjsing return NULL; 589b8b016bfSjsing } 590b8b016bfSjsing } 591b8b016bfSjsing 59272419cc7Sjsing CMS_RevocationInfoChoice * 59372419cc7Sjsing CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) 594b8b016bfSjsing { 595b8b016bfSjsing STACK_OF(CMS_RevocationInfoChoice) **pcrls; 596b8b016bfSjsing CMS_RevocationInfoChoice *rch; 59772419cc7Sjsing 598b8b016bfSjsing pcrls = cms_get0_revocation_choices(cms); 599b8b016bfSjsing if (!pcrls) 600b8b016bfSjsing return NULL; 601b8b016bfSjsing if (!*pcrls) 602b8b016bfSjsing *pcrls = sk_CMS_RevocationInfoChoice_new_null(); 603b8b016bfSjsing if (!*pcrls) 604b8b016bfSjsing return NULL; 605f2f5f7c4Sjsing rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it); 606b8b016bfSjsing if (!rch) 607b8b016bfSjsing return NULL; 608b8b016bfSjsing if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { 609f2f5f7c4Sjsing ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it); 610b8b016bfSjsing return NULL; 611b8b016bfSjsing } 61272419cc7Sjsing 613b8b016bfSjsing return rch; 614b8b016bfSjsing } 615ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_RevocationInfoChoice); 616b8b016bfSjsing 61772419cc7Sjsing int 61872419cc7Sjsing CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) 619b8b016bfSjsing { 620b8b016bfSjsing CMS_RevocationInfoChoice *rch; 62172419cc7Sjsing 622b8b016bfSjsing rch = CMS_add0_RevocationInfoChoice(cms); 623b8b016bfSjsing if (!rch) 624b8b016bfSjsing return 0; 625b8b016bfSjsing rch->type = CMS_REVCHOICE_CRL; 626b8b016bfSjsing rch->d.crl = crl; 62772419cc7Sjsing 628b8b016bfSjsing return 1; 629b8b016bfSjsing } 630ead8f799Sbeck LCRYPTO_ALIAS(CMS_add0_crl); 631b8b016bfSjsing 63272419cc7Sjsing int 63372419cc7Sjsing CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) 634b8b016bfSjsing { 635b8b016bfSjsing int r; 63672419cc7Sjsing 637b8b016bfSjsing r = CMS_add0_crl(cms, crl); 638b8b016bfSjsing if (r > 0) 639b8b016bfSjsing X509_CRL_up_ref(crl); 64072419cc7Sjsing 641b8b016bfSjsing return r; 642b8b016bfSjsing } 643ead8f799Sbeck LCRYPTO_ALIAS(CMS_add1_crl); 644b8b016bfSjsing 64572419cc7Sjsing STACK_OF(X509) * 64672419cc7Sjsing CMS_get1_certs(CMS_ContentInfo *cms) 647b8b016bfSjsing { 648b8b016bfSjsing STACK_OF(X509) *certs = NULL; 649b8b016bfSjsing CMS_CertificateChoices *cch; 650b8b016bfSjsing STACK_OF(CMS_CertificateChoices) **pcerts; 651b8b016bfSjsing int i; 65272419cc7Sjsing 653b8b016bfSjsing pcerts = cms_get0_certificate_choices(cms); 654b8b016bfSjsing if (!pcerts) 655b8b016bfSjsing return NULL; 656b8b016bfSjsing for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { 657b8b016bfSjsing cch = sk_CMS_CertificateChoices_value(*pcerts, i); 658b8b016bfSjsing if (cch->type == 0) { 659b8b016bfSjsing if (!certs) { 660b8b016bfSjsing certs = sk_X509_new_null(); 661b8b016bfSjsing if (!certs) 662b8b016bfSjsing return NULL; 663b8b016bfSjsing } 664b8b016bfSjsing if (!sk_X509_push(certs, cch->d.certificate)) { 665b8b016bfSjsing sk_X509_pop_free(certs, X509_free); 666b8b016bfSjsing return NULL; 667b8b016bfSjsing } 668b8b016bfSjsing X509_up_ref(cch->d.certificate); 669b8b016bfSjsing } 670b8b016bfSjsing } 671b8b016bfSjsing return certs; 672b8b016bfSjsing } 673ead8f799Sbeck LCRYPTO_ALIAS(CMS_get1_certs); 674b8b016bfSjsing 67572419cc7Sjsing STACK_OF(X509_CRL) * 67672419cc7Sjsing CMS_get1_crls(CMS_ContentInfo *cms) 677b8b016bfSjsing { 678b8b016bfSjsing STACK_OF(X509_CRL) *crls = NULL; 679b8b016bfSjsing STACK_OF(CMS_RevocationInfoChoice) **pcrls; 680b8b016bfSjsing CMS_RevocationInfoChoice *rch; 681b8b016bfSjsing int i; 68272419cc7Sjsing 683b8b016bfSjsing pcrls = cms_get0_revocation_choices(cms); 684b8b016bfSjsing if (!pcrls) 685b8b016bfSjsing return NULL; 686b8b016bfSjsing for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { 687b8b016bfSjsing rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); 688b8b016bfSjsing if (rch->type == 0) { 689b8b016bfSjsing if (!crls) { 690b8b016bfSjsing crls = sk_X509_CRL_new_null(); 691b8b016bfSjsing if (!crls) 692b8b016bfSjsing return NULL; 693b8b016bfSjsing } 694b8b016bfSjsing if (!sk_X509_CRL_push(crls, rch->d.crl)) { 695b8b016bfSjsing sk_X509_CRL_pop_free(crls, X509_CRL_free); 696b8b016bfSjsing return NULL; 697b8b016bfSjsing } 698b8b016bfSjsing X509_CRL_up_ref(rch->d.crl); 699b8b016bfSjsing } 700b8b016bfSjsing } 701b8b016bfSjsing return crls; 702b8b016bfSjsing } 703ead8f799Sbeck LCRYPTO_ALIAS(CMS_get1_crls); 704b8b016bfSjsing 705969b657eSjsing static const ASN1_OCTET_STRING * 706969b657eSjsing cms_X509_get0_subject_key_id(X509 *x) 707969b657eSjsing { 708969b657eSjsing /* Call for side-effect of computing hash and caching extensions */ 709969b657eSjsing X509_check_purpose(x, -1, -1); 710969b657eSjsing return x->skid; 711969b657eSjsing } 712969b657eSjsing 71372419cc7Sjsing int 71472419cc7Sjsing cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert) 715b8b016bfSjsing { 716b8b016bfSjsing int ret; 71772419cc7Sjsing 718b8b016bfSjsing ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert)); 719b8b016bfSjsing if (ret) 720b8b016bfSjsing return ret; 72172419cc7Sjsing 722b8b016bfSjsing return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert)); 723b8b016bfSjsing } 724b8b016bfSjsing 72572419cc7Sjsing int 72672419cc7Sjsing cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert) 727b8b016bfSjsing { 728969b657eSjsing const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert); 729b8b016bfSjsing 730b8b016bfSjsing if (cert_keyid == NULL) 731b8b016bfSjsing return -1; 73272419cc7Sjsing 733b8b016bfSjsing return ASN1_OCTET_STRING_cmp(keyid, cert_keyid); 734b8b016bfSjsing } 735b8b016bfSjsing 73672419cc7Sjsing int 73772419cc7Sjsing cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) 738b8b016bfSjsing { 739b8b016bfSjsing CMS_IssuerAndSerialNumber *ias; 74072419cc7Sjsing 741f2f5f7c4Sjsing ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it); 742b8b016bfSjsing if (!ias) 743b8b016bfSjsing goto err; 744b8b016bfSjsing if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) 745b8b016bfSjsing goto err; 746b8b016bfSjsing if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert))) 747b8b016bfSjsing goto err; 748f2f5f7c4Sjsing ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it); 749b8b016bfSjsing *pias = ias; 75072419cc7Sjsing 751b8b016bfSjsing return 1; 75272419cc7Sjsing 753b8b016bfSjsing err: 754f2f5f7c4Sjsing ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it); 755be6ec861Sjsing CMSerror(ERR_R_MALLOC_FAILURE); 75672419cc7Sjsing 757b8b016bfSjsing return 0; 758b8b016bfSjsing } 759b8b016bfSjsing 76072419cc7Sjsing int 76172419cc7Sjsing cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) 762b8b016bfSjsing { 763b8b016bfSjsing ASN1_OCTET_STRING *keyid = NULL; 764b8b016bfSjsing const ASN1_OCTET_STRING *cert_keyid; 76572419cc7Sjsing 766969b657eSjsing cert_keyid = cms_X509_get0_subject_key_id(cert); 767b8b016bfSjsing if (cert_keyid == NULL) { 768be6ec861Sjsing CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID); 769b8b016bfSjsing return 0; 770b8b016bfSjsing } 771b8b016bfSjsing keyid = ASN1_STRING_dup(cert_keyid); 772b8b016bfSjsing if (!keyid) { 773be6ec861Sjsing CMSerror(ERR_R_MALLOC_FAILURE); 774b8b016bfSjsing return 0; 775b8b016bfSjsing } 776b8b016bfSjsing ASN1_OCTET_STRING_free(*pkeyid); 777b8b016bfSjsing *pkeyid = keyid; 77872419cc7Sjsing 779b8b016bfSjsing return 1; 780b8b016bfSjsing } 781