1183234Ssimon/* crypto/cms/cms_sd.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 "cryptlib.h" 56183234Ssimon#include <openssl/asn1t.h> 57183234Ssimon#include <openssl/pem.h> 58183234Ssimon#include <openssl/x509v3.h> 59183234Ssimon#include <openssl/err.h> 60183234Ssimon#include <openssl/cms.h> 61183234Ssimon#include "cms_lcl.h" 62238405Sjkim#include "asn1_locl.h" 63183234Ssimon 64183234Ssimon/* CMS SignedData Utilities */ 65183234Ssimon 66183234SsimonDECLARE_ASN1_ITEM(CMS_SignedData) 67183234Ssimon 68183234Ssimonstatic CMS_SignedData *cms_get0_signed(CMS_ContentInfo *cms) 69280304Sjkim{ 70280304Sjkim if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) { 71280304Sjkim CMSerr(CMS_F_CMS_GET0_SIGNED, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA); 72280304Sjkim return NULL; 73280304Sjkim } 74280304Sjkim return cms->d.signedData; 75280304Sjkim} 76183234Ssimon 77183234Ssimonstatic CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms) 78280304Sjkim{ 79280304Sjkim if (cms->d.other == NULL) { 80280304Sjkim cms->d.signedData = M_ASN1_new_of(CMS_SignedData); 81280304Sjkim if (!cms->d.signedData) { 82280304Sjkim CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE); 83280304Sjkim return NULL; 84280304Sjkim } 85280304Sjkim cms->d.signedData->version = 1; 86280304Sjkim cms->d.signedData->encapContentInfo->eContentType = 87280304Sjkim OBJ_nid2obj(NID_pkcs7_data); 88280304Sjkim cms->d.signedData->encapContentInfo->partial = 1; 89280304Sjkim ASN1_OBJECT_free(cms->contentType); 90280304Sjkim cms->contentType = OBJ_nid2obj(NID_pkcs7_signed); 91280304Sjkim return cms->d.signedData; 92280304Sjkim } 93280304Sjkim return cms_get0_signed(cms); 94280304Sjkim} 95183234Ssimon 96183234Ssimon/* Just initialize SignedData e.g. for certs only structure */ 97183234Ssimon 98183234Ssimonint CMS_SignedData_init(CMS_ContentInfo *cms) 99280304Sjkim{ 100280304Sjkim if (cms_signed_data_init(cms)) 101280304Sjkim return 1; 102280304Sjkim else 103280304Sjkim return 0; 104280304Sjkim} 105183234Ssimon 106183234Ssimon/* Check structures and fixup version numbers (if necessary) */ 107183234Ssimon 108183234Ssimonstatic void cms_sd_set_version(CMS_SignedData *sd) 109280304Sjkim{ 110280304Sjkim int i; 111280304Sjkim CMS_CertificateChoices *cch; 112280304Sjkim CMS_RevocationInfoChoice *rch; 113280304Sjkim CMS_SignerInfo *si; 114183234Ssimon 115280304Sjkim for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) { 116280304Sjkim cch = sk_CMS_CertificateChoices_value(sd->certificates, i); 117280304Sjkim if (cch->type == CMS_CERTCHOICE_OTHER) { 118280304Sjkim if (sd->version < 5) 119280304Sjkim sd->version = 5; 120280304Sjkim } else if (cch->type == CMS_CERTCHOICE_V2ACERT) { 121280304Sjkim if (sd->version < 4) 122280304Sjkim sd->version = 4; 123280304Sjkim } else if (cch->type == CMS_CERTCHOICE_V1ACERT) { 124280304Sjkim if (sd->version < 3) 125280304Sjkim sd->version = 3; 126280304Sjkim } 127280304Sjkim } 128183234Ssimon 129280304Sjkim for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) { 130280304Sjkim rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i); 131280304Sjkim if (rch->type == CMS_REVCHOICE_OTHER) { 132280304Sjkim if (sd->version < 5) 133280304Sjkim sd->version = 5; 134280304Sjkim } 135280304Sjkim } 136183234Ssimon 137280304Sjkim if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data) 138280304Sjkim && (sd->version < 3)) 139280304Sjkim sd->version = 3; 140183234Ssimon 141280304Sjkim for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) { 142280304Sjkim si = sk_CMS_SignerInfo_value(sd->signerInfos, i); 143280304Sjkim if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { 144280304Sjkim if (si->version < 3) 145280304Sjkim si->version = 3; 146280304Sjkim if (sd->version < 3) 147280304Sjkim sd->version = 3; 148280304Sjkim } else if (si->version < 1) 149280304Sjkim si->version = 1; 150280304Sjkim } 151183234Ssimon 152280304Sjkim if (sd->version < 1) 153280304Sjkim sd->version = 1; 154183234Ssimon 155280304Sjkim} 156280304Sjkim 157183234Ssimon/* Copy an existing messageDigest value */ 158183234Ssimon 159183234Ssimonstatic int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si) 160280304Sjkim{ 161280304Sjkim STACK_OF(CMS_SignerInfo) *sinfos; 162280304Sjkim CMS_SignerInfo *sitmp; 163280304Sjkim int i; 164280304Sjkim sinfos = CMS_get0_SignerInfos(cms); 165280304Sjkim for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 166280304Sjkim ASN1_OCTET_STRING *messageDigest; 167280304Sjkim sitmp = sk_CMS_SignerInfo_value(sinfos, i); 168280304Sjkim if (sitmp == si) 169280304Sjkim continue; 170280304Sjkim if (CMS_signed_get_attr_count(sitmp) < 0) 171280304Sjkim continue; 172280304Sjkim if (OBJ_cmp(si->digestAlgorithm->algorithm, 173280304Sjkim sitmp->digestAlgorithm->algorithm)) 174280304Sjkim continue; 175280304Sjkim messageDigest = CMS_signed_get0_data_by_OBJ(sitmp, 176280304Sjkim OBJ_nid2obj 177280304Sjkim (NID_pkcs9_messageDigest), 178280304Sjkim -3, V_ASN1_OCTET_STRING); 179280304Sjkim if (!messageDigest) { 180280304Sjkim CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, 181280304Sjkim CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); 182280304Sjkim return 0; 183280304Sjkim } 184183234Ssimon 185280304Sjkim if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, 186280304Sjkim V_ASN1_OCTET_STRING, 187280304Sjkim messageDigest, -1)) 188280304Sjkim return 1; 189280304Sjkim else 190280304Sjkim return 0; 191280304Sjkim } 192280304Sjkim CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST); 193280304Sjkim return 0; 194280304Sjkim} 195183234Ssimon 196183234Ssimonint cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type) 197280304Sjkim{ 198280304Sjkim switch (type) { 199280304Sjkim case CMS_SIGNERINFO_ISSUER_SERIAL: 200280304Sjkim sid->d.issuerAndSerialNumber = 201280304Sjkim M_ASN1_new_of(CMS_IssuerAndSerialNumber); 202280304Sjkim if (!sid->d.issuerAndSerialNumber) 203280304Sjkim goto merr; 204280304Sjkim if (!X509_NAME_set(&sid->d.issuerAndSerialNumber->issuer, 205280304Sjkim X509_get_issuer_name(cert))) 206280304Sjkim goto merr; 207280304Sjkim if (!ASN1_STRING_copy(sid->d.issuerAndSerialNumber->serialNumber, 208280304Sjkim X509_get_serialNumber(cert))) 209280304Sjkim goto merr; 210280304Sjkim break; 211183234Ssimon 212280304Sjkim case CMS_SIGNERINFO_KEYIDENTIFIER: 213280304Sjkim if (!cert->skid) { 214280304Sjkim CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, 215280304Sjkim CMS_R_CERTIFICATE_HAS_NO_KEYID); 216280304Sjkim return 0; 217280304Sjkim } 218280304Sjkim sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid); 219280304Sjkim if (!sid->d.subjectKeyIdentifier) 220280304Sjkim goto merr; 221280304Sjkim break; 222183234Ssimon 223280304Sjkim default: 224280304Sjkim CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID); 225280304Sjkim return 0; 226280304Sjkim } 227183234Ssimon 228280304Sjkim sid->type = type; 229183234Ssimon 230280304Sjkim return 1; 231183234Ssimon 232280304Sjkim merr: 233280304Sjkim CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, ERR_R_MALLOC_FAILURE); 234280304Sjkim return 0; 235183234Ssimon 236280304Sjkim} 237183234Ssimon 238183234Ssimonint cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, 239280304Sjkim ASN1_OCTET_STRING **keyid, 240280304Sjkim X509_NAME **issuer, 241280304Sjkim ASN1_INTEGER **sno) 242280304Sjkim{ 243280304Sjkim if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) { 244280304Sjkim if (issuer) 245280304Sjkim *issuer = sid->d.issuerAndSerialNumber->issuer; 246280304Sjkim if (sno) 247280304Sjkim *sno = sid->d.issuerAndSerialNumber->serialNumber; 248280304Sjkim } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { 249280304Sjkim if (keyid) 250280304Sjkim *keyid = sid->d.subjectKeyIdentifier; 251280304Sjkim } else 252280304Sjkim return 0; 253280304Sjkim return 1; 254280304Sjkim} 255183234Ssimon 256183234Ssimonint cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) 257280304Sjkim{ 258280304Sjkim int ret; 259280304Sjkim if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) { 260280304Sjkim ret = X509_NAME_cmp(sid->d.issuerAndSerialNumber->issuer, 261280304Sjkim X509_get_issuer_name(cert)); 262280304Sjkim if (ret) 263280304Sjkim return ret; 264280304Sjkim return ASN1_INTEGER_cmp(sid->d.issuerAndSerialNumber->serialNumber, 265280304Sjkim X509_get_serialNumber(cert)); 266280304Sjkim } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { 267280304Sjkim X509_check_purpose(cert, -1, -1); 268280304Sjkim if (!cert->skid) 269280304Sjkim return -1; 270280304Sjkim return ASN1_OCTET_STRING_cmp(sid->d.subjectKeyIdentifier, cert->skid); 271280304Sjkim } else 272280304Sjkim return -1; 273280304Sjkim} 274183234Ssimon 275183234SsimonCMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, 276280304Sjkim X509 *signer, EVP_PKEY *pk, const EVP_MD *md, 277280304Sjkim unsigned int flags) 278280304Sjkim{ 279280304Sjkim CMS_SignedData *sd; 280280304Sjkim CMS_SignerInfo *si = NULL; 281280304Sjkim X509_ALGOR *alg; 282280304Sjkim int i, type; 283280304Sjkim if (!X509_check_private_key(signer, pk)) { 284280304Sjkim CMSerr(CMS_F_CMS_ADD1_SIGNER, 285280304Sjkim CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); 286280304Sjkim return NULL; 287280304Sjkim } 288280304Sjkim sd = cms_signed_data_init(cms); 289280304Sjkim if (!sd) 290280304Sjkim goto err; 291280304Sjkim si = M_ASN1_new_of(CMS_SignerInfo); 292280304Sjkim if (!si) 293280304Sjkim goto merr; 294280304Sjkim X509_check_purpose(signer, -1, -1); 295183234Ssimon 296280304Sjkim CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); 297280304Sjkim CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); 298183234Ssimon 299280304Sjkim si->pkey = pk; 300280304Sjkim si->signer = signer; 301183234Ssimon 302280304Sjkim if (flags & CMS_USE_KEYID) { 303280304Sjkim si->version = 3; 304280304Sjkim if (sd->version < 3) 305280304Sjkim sd->version = 3; 306280304Sjkim type = CMS_SIGNERINFO_KEYIDENTIFIER; 307280304Sjkim } else { 308280304Sjkim type = CMS_SIGNERINFO_ISSUER_SERIAL; 309280304Sjkim si->version = 1; 310280304Sjkim } 311183234Ssimon 312280304Sjkim if (!cms_set1_SignerIdentifier(si->sid, signer, type)) 313280304Sjkim goto err; 314183234Ssimon 315280304Sjkim if (md == NULL) { 316280304Sjkim int def_nid; 317280304Sjkim if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) 318280304Sjkim goto err; 319280304Sjkim md = EVP_get_digestbynid(def_nid); 320280304Sjkim if (md == NULL) { 321280304Sjkim CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); 322280304Sjkim goto err; 323280304Sjkim } 324280304Sjkim } 325183234Ssimon 326280304Sjkim if (!md) { 327280304Sjkim CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); 328280304Sjkim goto err; 329280304Sjkim } 330183234Ssimon 331280304Sjkim cms_DigestAlgorithm_set(si->digestAlgorithm, md); 332183234Ssimon 333280304Sjkim /* See if digest is present in digestAlgorithms */ 334280304Sjkim for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { 335280304Sjkim ASN1_OBJECT *aoid; 336280304Sjkim alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); 337280304Sjkim X509_ALGOR_get0(&aoid, NULL, NULL, alg); 338280304Sjkim if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) 339280304Sjkim break; 340280304Sjkim } 341183234Ssimon 342280304Sjkim if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { 343280304Sjkim alg = X509_ALGOR_new(); 344280304Sjkim if (!alg) 345280304Sjkim goto merr; 346280304Sjkim cms_DigestAlgorithm_set(alg, md); 347280304Sjkim if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { 348280304Sjkim X509_ALGOR_free(alg); 349280304Sjkim goto merr; 350280304Sjkim } 351280304Sjkim } 352183234Ssimon 353280304Sjkim if (pk->ameth && pk->ameth->pkey_ctrl) { 354280304Sjkim i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN, 0, si); 355280304Sjkim if (i == -2) { 356280304Sjkim CMSerr(CMS_F_CMS_ADD1_SIGNER, 357280304Sjkim CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 358280304Sjkim goto err; 359280304Sjkim } 360280304Sjkim if (i <= 0) { 361280304Sjkim CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE); 362280304Sjkim goto err; 363280304Sjkim } 364280304Sjkim } 365183234Ssimon 366280304Sjkim if (!(flags & CMS_NOATTR)) { 367280304Sjkim /* 368280304Sjkim * Initialialize signed attributes strutucture so other attributes 369280304Sjkim * such as signing time etc are added later even if we add none here. 370280304Sjkim */ 371280304Sjkim if (!si->signedAttrs) { 372280304Sjkim si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); 373280304Sjkim if (!si->signedAttrs) 374280304Sjkim goto merr; 375280304Sjkim } 376183234Ssimon 377280304Sjkim if (!(flags & CMS_NOSMIMECAP)) { 378280304Sjkim STACK_OF(X509_ALGOR) *smcap = NULL; 379280304Sjkim i = CMS_add_standard_smimecap(&smcap); 380280304Sjkim if (i) 381280304Sjkim i = CMS_add_smimecap(si, smcap); 382280304Sjkim sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); 383280304Sjkim if (!i) 384280304Sjkim goto merr; 385280304Sjkim } 386280304Sjkim if (flags & CMS_REUSE_DIGEST) { 387280304Sjkim if (!cms_copy_messageDigest(cms, si)) 388280304Sjkim goto err; 389280304Sjkim if (!(flags & CMS_PARTIAL) && !CMS_SignerInfo_sign(si)) 390280304Sjkim goto err; 391280304Sjkim } 392280304Sjkim } 393183234Ssimon 394280304Sjkim if (!(flags & CMS_NOCERTS)) { 395280304Sjkim /* NB ignore -1 return for duplicate cert */ 396280304Sjkim if (!CMS_add1_cert(cms, signer)) 397280304Sjkim goto merr; 398280304Sjkim } 399183234Ssimon 400280304Sjkim if (!sd->signerInfos) 401280304Sjkim sd->signerInfos = sk_CMS_SignerInfo_new_null(); 402280304Sjkim if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) 403280304Sjkim goto merr; 404183234Ssimon 405280304Sjkim return si; 406183234Ssimon 407280304Sjkim merr: 408280304Sjkim CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); 409280304Sjkim err: 410280304Sjkim if (si) 411280304Sjkim M_ASN1_free_of(si, CMS_SignerInfo); 412280304Sjkim return NULL; 413183234Ssimon 414280304Sjkim} 415183234Ssimon 416183234Ssimonstatic int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t) 417280304Sjkim{ 418280304Sjkim ASN1_TIME *tt; 419280304Sjkim int r = 0; 420280304Sjkim if (t) 421280304Sjkim tt = t; 422280304Sjkim else 423280304Sjkim tt = X509_gmtime_adj(NULL, 0); 424183234Ssimon 425280304Sjkim if (!tt) 426280304Sjkim goto merr; 427183234Ssimon 428280304Sjkim if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime, 429280304Sjkim tt->type, tt, -1) <= 0) 430280304Sjkim goto merr; 431183234Ssimon 432280304Sjkim r = 1; 433183234Ssimon 434280304Sjkim merr: 435183234Ssimon 436280304Sjkim if (!t) 437280304Sjkim ASN1_TIME_free(tt); 438183234Ssimon 439280304Sjkim if (!r) 440280304Sjkim CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE); 441183234Ssimon 442280304Sjkim return r; 443183234Ssimon 444280304Sjkim} 445183234Ssimon 446183234SsimonSTACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms) 447280304Sjkim{ 448280304Sjkim CMS_SignedData *sd; 449280304Sjkim sd = cms_get0_signed(cms); 450280304Sjkim if (!sd) 451280304Sjkim return NULL; 452280304Sjkim return sd->signerInfos; 453280304Sjkim} 454183234Ssimon 455183234SsimonSTACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms) 456280304Sjkim{ 457280304Sjkim STACK_OF(X509) *signers = NULL; 458280304Sjkim STACK_OF(CMS_SignerInfo) *sinfos; 459280304Sjkim CMS_SignerInfo *si; 460280304Sjkim int i; 461280304Sjkim sinfos = CMS_get0_SignerInfos(cms); 462280304Sjkim for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 463280304Sjkim si = sk_CMS_SignerInfo_value(sinfos, i); 464280304Sjkim if (si->signer) { 465280304Sjkim if (!signers) { 466280304Sjkim signers = sk_X509_new_null(); 467280304Sjkim if (!signers) 468280304Sjkim return NULL; 469280304Sjkim } 470280304Sjkim if (!sk_X509_push(signers, si->signer)) { 471280304Sjkim sk_X509_free(signers); 472280304Sjkim return NULL; 473280304Sjkim } 474280304Sjkim } 475280304Sjkim } 476280304Sjkim return signers; 477280304Sjkim} 478183234Ssimon 479183234Ssimonvoid CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer) 480280304Sjkim{ 481280304Sjkim if (signer) { 482280304Sjkim CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); 483280304Sjkim if (si->pkey) 484280304Sjkim EVP_PKEY_free(si->pkey); 485280304Sjkim si->pkey = X509_get_pubkey(signer); 486280304Sjkim } 487280304Sjkim if (si->signer) 488280304Sjkim X509_free(si->signer); 489280304Sjkim si->signer = signer; 490280304Sjkim} 491183234Ssimon 492183234Ssimonint CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, 493280304Sjkim ASN1_OCTET_STRING **keyid, 494280304Sjkim X509_NAME **issuer, ASN1_INTEGER **sno) 495280304Sjkim{ 496280304Sjkim return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno); 497280304Sjkim} 498183234Ssimon 499183234Ssimonint CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert) 500280304Sjkim{ 501280304Sjkim return cms_SignerIdentifier_cert_cmp(si->sid, cert); 502280304Sjkim} 503183234Ssimon 504183234Ssimonint CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts, 505280304Sjkim unsigned int flags) 506280304Sjkim{ 507280304Sjkim CMS_SignedData *sd; 508280304Sjkim CMS_SignerInfo *si; 509280304Sjkim CMS_CertificateChoices *cch; 510280304Sjkim STACK_OF(CMS_CertificateChoices) *certs; 511280304Sjkim X509 *x; 512280304Sjkim int i, j; 513280304Sjkim int ret = 0; 514280304Sjkim sd = cms_get0_signed(cms); 515280304Sjkim if (!sd) 516280304Sjkim return -1; 517280304Sjkim certs = sd->certificates; 518280304Sjkim for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) { 519280304Sjkim si = sk_CMS_SignerInfo_value(sd->signerInfos, i); 520280304Sjkim if (si->signer) 521280304Sjkim continue; 522183234Ssimon 523280304Sjkim for (j = 0; j < sk_X509_num(scerts); j++) { 524280304Sjkim x = sk_X509_value(scerts, j); 525280304Sjkim if (CMS_SignerInfo_cert_cmp(si, x) == 0) { 526280304Sjkim CMS_SignerInfo_set1_signer_cert(si, x); 527280304Sjkim ret++; 528280304Sjkim break; 529280304Sjkim } 530280304Sjkim } 531183234Ssimon 532280304Sjkim if (si->signer || (flags & CMS_NOINTERN)) 533280304Sjkim continue; 534183234Ssimon 535280304Sjkim for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) { 536280304Sjkim cch = sk_CMS_CertificateChoices_value(certs, j); 537280304Sjkim if (cch->type != 0) 538280304Sjkim continue; 539280304Sjkim x = cch->d.certificate; 540280304Sjkim if (CMS_SignerInfo_cert_cmp(si, x) == 0) { 541280304Sjkim CMS_SignerInfo_set1_signer_cert(si, x); 542280304Sjkim ret++; 543280304Sjkim break; 544280304Sjkim } 545280304Sjkim } 546280304Sjkim } 547280304Sjkim return ret; 548280304Sjkim} 549183234Ssimon 550280304Sjkimvoid CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, 551280304Sjkim X509 **signer, X509_ALGOR **pdig, 552280304Sjkim X509_ALGOR **psig) 553280304Sjkim{ 554280304Sjkim if (pk) 555280304Sjkim *pk = si->pkey; 556280304Sjkim if (signer) 557280304Sjkim *signer = si->signer; 558280304Sjkim if (pdig) 559280304Sjkim *pdig = si->digestAlgorithm; 560280304Sjkim if (psig) 561280304Sjkim *psig = si->signatureAlgorithm; 562280304Sjkim} 563183234Ssimon 564183234Ssimonstatic int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, 565280304Sjkim CMS_SignerInfo *si, BIO *chain) 566280304Sjkim{ 567280304Sjkim EVP_MD_CTX mctx; 568280304Sjkim int r = 0; 569280304Sjkim EVP_MD_CTX_init(&mctx); 570183234Ssimon 571280304Sjkim if (!si->pkey) { 572280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY); 573280304Sjkim return 0; 574280304Sjkim } 575183234Ssimon 576280304Sjkim if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) 577280304Sjkim goto err; 578183234Ssimon 579280304Sjkim /* 580280304Sjkim * If any signed attributes calculate and add messageDigest attribute 581280304Sjkim */ 582183234Ssimon 583280304Sjkim if (CMS_signed_get_attr_count(si) >= 0) { 584280304Sjkim ASN1_OBJECT *ctype = 585280304Sjkim cms->d.signedData->encapContentInfo->eContentType; 586280304Sjkim unsigned char md[EVP_MAX_MD_SIZE]; 587280304Sjkim unsigned int mdlen; 588280304Sjkim if (!EVP_DigestFinal_ex(&mctx, md, &mdlen)) 589280304Sjkim goto err; 590280304Sjkim if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, 591280304Sjkim V_ASN1_OCTET_STRING, md, mdlen)) 592280304Sjkim goto err; 593280304Sjkim /* Copy content type across */ 594280304Sjkim if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType, 595280304Sjkim V_ASN1_OBJECT, ctype, -1) <= 0) 596280304Sjkim goto err; 597280304Sjkim if (!CMS_SignerInfo_sign(si)) 598280304Sjkim goto err; 599280304Sjkim } else { 600280304Sjkim unsigned char *sig; 601280304Sjkim unsigned int siglen; 602280304Sjkim sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey)); 603280304Sjkim if (!sig) { 604280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE); 605280304Sjkim goto err; 606280304Sjkim } 607280304Sjkim if (!EVP_SignFinal(&mctx, sig, &siglen, si->pkey)) { 608280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_SIGNFINAL_ERROR); 609280304Sjkim OPENSSL_free(sig); 610280304Sjkim goto err; 611280304Sjkim } 612280304Sjkim ASN1_STRING_set0(si->signature, sig, siglen); 613280304Sjkim } 614183234Ssimon 615280304Sjkim r = 1; 616183234Ssimon 617280304Sjkim err: 618280304Sjkim EVP_MD_CTX_cleanup(&mctx); 619280304Sjkim return r; 620183234Ssimon 621280304Sjkim} 622183234Ssimon 623183234Ssimonint cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) 624280304Sjkim{ 625280304Sjkim STACK_OF(CMS_SignerInfo) *sinfos; 626280304Sjkim CMS_SignerInfo *si; 627280304Sjkim int i; 628280304Sjkim sinfos = CMS_get0_SignerInfos(cms); 629280304Sjkim for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 630280304Sjkim si = sk_CMS_SignerInfo_value(sinfos, i); 631280304Sjkim if (!cms_SignerInfo_content_sign(cms, si, chain)) 632280304Sjkim return 0; 633280304Sjkim } 634280304Sjkim cms->d.signedData->encapContentInfo->partial = 0; 635280304Sjkim return 1; 636280304Sjkim} 637183234Ssimon 638183234Ssimonint CMS_SignerInfo_sign(CMS_SignerInfo *si) 639280304Sjkim{ 640280304Sjkim EVP_MD_CTX mctx; 641280304Sjkim EVP_PKEY_CTX *pctx; 642280304Sjkim unsigned char *abuf = NULL; 643280304Sjkim int alen; 644280304Sjkim size_t siglen; 645280304Sjkim const EVP_MD *md = NULL; 646183234Ssimon 647280304Sjkim md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); 648280304Sjkim if (md == NULL) 649280304Sjkim return 0; 650183234Ssimon 651280304Sjkim EVP_MD_CTX_init(&mctx); 652183234Ssimon 653280304Sjkim if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { 654280304Sjkim if (!cms_add1_signingTime(si, NULL)) 655280304Sjkim goto err; 656280304Sjkim } 657183234Ssimon 658280304Sjkim if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) 659280304Sjkim goto err; 660183234Ssimon 661280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 662280304Sjkim EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) { 663280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); 664280304Sjkim goto err; 665280304Sjkim } 666183234Ssimon 667280304Sjkim alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf, 668280304Sjkim ASN1_ITEM_rptr(CMS_Attributes_Sign)); 669280304Sjkim if (!abuf) 670280304Sjkim goto err; 671280304Sjkim if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0) 672280304Sjkim goto err; 673280304Sjkim if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) 674280304Sjkim goto err; 675280304Sjkim OPENSSL_free(abuf); 676280304Sjkim abuf = OPENSSL_malloc(siglen); 677280304Sjkim if (!abuf) 678280304Sjkim goto err; 679280304Sjkim if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) 680280304Sjkim goto err; 681238405Sjkim 682280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 683280304Sjkim EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) { 684280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); 685280304Sjkim goto err; 686280304Sjkim } 687238405Sjkim 688280304Sjkim EVP_MD_CTX_cleanup(&mctx); 689183234Ssimon 690280304Sjkim ASN1_STRING_set0(si->signature, abuf, siglen); 691183234Ssimon 692280304Sjkim return 1; 693183234Ssimon 694280304Sjkim err: 695280304Sjkim if (abuf) 696280304Sjkim OPENSSL_free(abuf); 697280304Sjkim EVP_MD_CTX_cleanup(&mctx); 698280304Sjkim return 0; 699183234Ssimon 700280304Sjkim} 701183234Ssimon 702183234Ssimonint CMS_SignerInfo_verify(CMS_SignerInfo *si) 703280304Sjkim{ 704280304Sjkim EVP_MD_CTX mctx; 705280304Sjkim EVP_PKEY_CTX *pctx; 706280304Sjkim unsigned char *abuf = NULL; 707280304Sjkim int alen, r = -1; 708280304Sjkim const EVP_MD *md = NULL; 709183234Ssimon 710280304Sjkim if (!si->pkey) { 711280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY); 712280304Sjkim return -1; 713280304Sjkim } 714183234Ssimon 715280304Sjkim md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); 716280304Sjkim if (md == NULL) 717280304Sjkim return -1; 718280304Sjkim EVP_MD_CTX_init(&mctx); 719280304Sjkim if (EVP_DigestVerifyInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) 720280304Sjkim goto err; 721183234Ssimon 722280304Sjkim alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf, 723280304Sjkim ASN1_ITEM_rptr(CMS_Attributes_Verify)); 724280304Sjkim if (!abuf) 725280304Sjkim goto err; 726280304Sjkim r = EVP_DigestVerifyUpdate(&mctx, abuf, alen); 727280304Sjkim OPENSSL_free(abuf); 728280304Sjkim if (r <= 0) { 729280304Sjkim r = -1; 730280304Sjkim goto err; 731280304Sjkim } 732280304Sjkim r = EVP_DigestVerifyFinal(&mctx, 733280304Sjkim si->signature->data, si->signature->length); 734280304Sjkim if (r <= 0) 735280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE); 736280304Sjkim err: 737280304Sjkim EVP_MD_CTX_cleanup(&mctx); 738280304Sjkim return r; 739280304Sjkim} 740183234Ssimon 741183234Ssimon/* Create a chain of digest BIOs from a CMS ContentInfo */ 742183234Ssimon 743183234SsimonBIO *cms_SignedData_init_bio(CMS_ContentInfo *cms) 744280304Sjkim{ 745280304Sjkim int i; 746280304Sjkim CMS_SignedData *sd; 747280304Sjkim BIO *chain = NULL; 748280304Sjkim sd = cms_get0_signed(cms); 749280304Sjkim if (!sd) 750280304Sjkim return NULL; 751280304Sjkim if (cms->d.signedData->encapContentInfo->partial) 752280304Sjkim cms_sd_set_version(sd); 753280304Sjkim for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { 754280304Sjkim X509_ALGOR *digestAlgorithm; 755280304Sjkim BIO *mdbio; 756280304Sjkim digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i); 757280304Sjkim mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm); 758280304Sjkim if (!mdbio) 759280304Sjkim goto err; 760280304Sjkim if (chain) 761280304Sjkim BIO_push(chain, mdbio); 762280304Sjkim else 763280304Sjkim chain = mdbio; 764280304Sjkim } 765280304Sjkim return chain; 766280304Sjkim err: 767280304Sjkim if (chain) 768280304Sjkim BIO_free_all(chain); 769280304Sjkim return NULL; 770280304Sjkim} 771183234Ssimon 772183234Ssimonint CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) 773280304Sjkim{ 774280304Sjkim ASN1_OCTET_STRING *os = NULL; 775280304Sjkim EVP_MD_CTX mctx; 776280304Sjkim int r = -1; 777280304Sjkim EVP_MD_CTX_init(&mctx); 778280304Sjkim /* If we have any signed attributes look for messageDigest value */ 779280304Sjkim if (CMS_signed_get_attr_count(si) >= 0) { 780280304Sjkim os = CMS_signed_get0_data_by_OBJ(si, 781280304Sjkim OBJ_nid2obj(NID_pkcs9_messageDigest), 782280304Sjkim -3, V_ASN1_OCTET_STRING); 783280304Sjkim if (!os) { 784280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 785280304Sjkim CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); 786280304Sjkim goto err; 787280304Sjkim } 788280304Sjkim } 789183234Ssimon 790280304Sjkim if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) 791280304Sjkim goto err; 792183234Ssimon 793280304Sjkim /* If messageDigest found compare it */ 794183234Ssimon 795280304Sjkim if (os) { 796280304Sjkim unsigned char mval[EVP_MAX_MD_SIZE]; 797280304Sjkim unsigned int mlen; 798280304Sjkim if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0) { 799280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 800280304Sjkim CMS_R_UNABLE_TO_FINALIZE_CONTEXT); 801280304Sjkim goto err; 802280304Sjkim } 803280304Sjkim if (mlen != (unsigned int)os->length) { 804280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 805280304Sjkim CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH); 806280304Sjkim goto err; 807280304Sjkim } 808183234Ssimon 809280304Sjkim if (memcmp(mval, os->data, mlen)) { 810280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 811280304Sjkim CMS_R_VERIFICATION_FAILURE); 812280304Sjkim r = 0; 813280304Sjkim } else 814280304Sjkim r = 1; 815280304Sjkim } else { 816280304Sjkim r = EVP_VerifyFinal(&mctx, si->signature->data, 817280304Sjkim si->signature->length, si->pkey); 818280304Sjkim if (r <= 0) { 819280304Sjkim CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 820280304Sjkim CMS_R_VERIFICATION_FAILURE); 821280304Sjkim r = 0; 822280304Sjkim } 823280304Sjkim } 824183234Ssimon 825280304Sjkim err: 826280304Sjkim EVP_MD_CTX_cleanup(&mctx); 827280304Sjkim return r; 828183234Ssimon 829280304Sjkim} 830183234Ssimon 831183234Ssimonint CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs) 832280304Sjkim{ 833280304Sjkim unsigned char *smder = NULL; 834280304Sjkim int smderlen, r; 835280304Sjkim smderlen = i2d_X509_ALGORS(algs, &smder); 836280304Sjkim if (smderlen <= 0) 837280304Sjkim return 0; 838280304Sjkim r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities, 839280304Sjkim V_ASN1_SEQUENCE, smder, smderlen); 840280304Sjkim OPENSSL_free(smder); 841280304Sjkim return r; 842280304Sjkim} 843183234Ssimon 844183234Ssimonint CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, 845280304Sjkim int algnid, int keysize) 846280304Sjkim{ 847280304Sjkim X509_ALGOR *alg; 848280304Sjkim ASN1_INTEGER *key = NULL; 849280304Sjkim if (keysize > 0) { 850280304Sjkim key = ASN1_INTEGER_new(); 851280304Sjkim if (!key || !ASN1_INTEGER_set(key, keysize)) 852280304Sjkim return 0; 853280304Sjkim } 854280304Sjkim alg = X509_ALGOR_new(); 855280304Sjkim if (!alg) { 856280304Sjkim if (key) 857280304Sjkim ASN1_INTEGER_free(key); 858280304Sjkim return 0; 859280304Sjkim } 860183234Ssimon 861280304Sjkim X509_ALGOR_set0(alg, OBJ_nid2obj(algnid), 862280304Sjkim key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key); 863280304Sjkim if (!*algs) 864280304Sjkim *algs = sk_X509_ALGOR_new_null(); 865280304Sjkim if (!*algs || !sk_X509_ALGOR_push(*algs, alg)) { 866280304Sjkim X509_ALGOR_free(alg); 867280304Sjkim return 0; 868280304Sjkim } 869280304Sjkim return 1; 870280304Sjkim} 871280304Sjkim 872183234Ssimon/* Check to see if a cipher exists and if so add S/MIME capabilities */ 873183234Ssimon 874183234Ssimonstatic int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) 875280304Sjkim{ 876280304Sjkim if (EVP_get_cipherbynid(nid)) 877280304Sjkim return CMS_add_simple_smimecap(sk, nid, arg); 878280304Sjkim return 1; 879280304Sjkim} 880238405Sjkim 881183234Ssimonstatic int cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) 882280304Sjkim{ 883280304Sjkim if (EVP_get_digestbynid(nid)) 884280304Sjkim return CMS_add_simple_smimecap(sk, nid, arg); 885280304Sjkim return 1; 886280304Sjkim} 887238405Sjkim 888183234Ssimonint CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap) 889280304Sjkim{ 890280304Sjkim if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1) 891280304Sjkim || !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1) 892280304Sjkim || !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) 893280304Sjkim || !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1) 894280304Sjkim || !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1) 895280304Sjkim || !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) 896280304Sjkim || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128) 897280304Sjkim || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64) 898280304Sjkim || !cms_add_cipher_smcap(smcap, NID_des_cbc, -1) 899280304Sjkim || !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40)) 900280304Sjkim return 0; 901280304Sjkim return 1; 902280304Sjkim} 903