1183234Ssimon/* crypto/cms/cms_env.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 "cryptlib.h" 55183234Ssimon#include <openssl/asn1t.h> 56183234Ssimon#include <openssl/pem.h> 57183234Ssimon#include <openssl/x509v3.h> 58183234Ssimon#include <openssl/err.h> 59183234Ssimon#include <openssl/cms.h> 60183234Ssimon#include <openssl/rand.h> 61183234Ssimon#include <openssl/aes.h> 62183234Ssimon#include "cms_lcl.h" 63238405Sjkim#include "asn1_locl.h" 64183234Ssimon 65183234Ssimon/* CMS EnvelopedData Utilities */ 66183234Ssimon 67183234SsimonDECLARE_ASN1_ITEM(CMS_EnvelopedData) 68183234SsimonDECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo) 69183234SsimonDECLARE_ASN1_ITEM(CMS_KEKRecipientInfo) 70183234SsimonDECLARE_ASN1_ITEM(CMS_OtherKeyAttribute) 71183234Ssimon 72183234SsimonDECLARE_STACK_OF(CMS_RecipientInfo) 73183234Ssimon 74238405SjkimCMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms) 75183234Ssimon { 76183234Ssimon if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) 77183234Ssimon { 78183234Ssimon CMSerr(CMS_F_CMS_GET0_ENVELOPED, 79183234Ssimon CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA); 80183234Ssimon return NULL; 81183234Ssimon } 82183234Ssimon return cms->d.envelopedData; 83183234Ssimon } 84183234Ssimon 85183234Ssimonstatic CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms) 86183234Ssimon { 87183234Ssimon if (cms->d.other == NULL) 88183234Ssimon { 89183234Ssimon cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData); 90183234Ssimon if (!cms->d.envelopedData) 91183234Ssimon { 92183234Ssimon CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, 93183234Ssimon ERR_R_MALLOC_FAILURE); 94183234Ssimon return NULL; 95183234Ssimon } 96183234Ssimon cms->d.envelopedData->version = 0; 97183234Ssimon cms->d.envelopedData->encryptedContentInfo->contentType = 98183234Ssimon OBJ_nid2obj(NID_pkcs7_data); 99183234Ssimon ASN1_OBJECT_free(cms->contentType); 100183234Ssimon cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped); 101183234Ssimon return cms->d.envelopedData; 102183234Ssimon } 103183234Ssimon return cms_get0_enveloped(cms); 104183234Ssimon } 105183234Ssimon 106183234SsimonSTACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms) 107183234Ssimon { 108183234Ssimon CMS_EnvelopedData *env; 109183234Ssimon env = cms_get0_enveloped(cms); 110183234Ssimon if (!env) 111183234Ssimon return NULL; 112183234Ssimon return env->recipientInfos; 113183234Ssimon } 114183234Ssimon 115183234Ssimonint CMS_RecipientInfo_type(CMS_RecipientInfo *ri) 116183234Ssimon { 117183234Ssimon return ri->type; 118183234Ssimon } 119183234Ssimon 120183234SsimonCMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher) 121183234Ssimon { 122183234Ssimon CMS_ContentInfo *cms; 123183234Ssimon CMS_EnvelopedData *env; 124183234Ssimon cms = CMS_ContentInfo_new(); 125183234Ssimon if (!cms) 126183234Ssimon goto merr; 127183234Ssimon env = cms_enveloped_data_init(cms); 128183234Ssimon if (!env) 129183234Ssimon goto merr; 130183234Ssimon if (!cms_EncryptedContent_init(env->encryptedContentInfo, 131183234Ssimon cipher, NULL, 0)) 132183234Ssimon goto merr; 133183234Ssimon return cms; 134183234Ssimon merr: 135183234Ssimon if (cms) 136183234Ssimon CMS_ContentInfo_free(cms); 137183234Ssimon CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE); 138183234Ssimon return NULL; 139183234Ssimon } 140183234Ssimon 141183234Ssimon/* Key Transport Recipient Info (KTRI) routines */ 142183234Ssimon 143183234Ssimon/* Add a recipient certificate. For now only handle key transport. 144183234Ssimon * If we ever handle key agreement will need updating. 145183234Ssimon */ 146183234Ssimon 147183234SsimonCMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, 148183234Ssimon X509 *recip, unsigned int flags) 149183234Ssimon { 150183234Ssimon CMS_RecipientInfo *ri = NULL; 151183234Ssimon CMS_KeyTransRecipientInfo *ktri; 152183234Ssimon CMS_EnvelopedData *env; 153183234Ssimon EVP_PKEY *pk = NULL; 154238405Sjkim int i, type; 155183234Ssimon env = cms_get0_enveloped(cms); 156183234Ssimon if (!env) 157183234Ssimon goto err; 158183234Ssimon 159183234Ssimon /* Initialize recipient info */ 160183234Ssimon ri = M_ASN1_new_of(CMS_RecipientInfo); 161183234Ssimon if (!ri) 162183234Ssimon goto merr; 163183234Ssimon 164183234Ssimon /* Initialize and add key transport recipient info */ 165183234Ssimon 166183234Ssimon ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); 167183234Ssimon if (!ri->d.ktri) 168183234Ssimon goto merr; 169183234Ssimon ri->type = CMS_RECIPINFO_TRANS; 170183234Ssimon 171183234Ssimon ktri = ri->d.ktri; 172183234Ssimon 173183234Ssimon X509_check_purpose(recip, -1, -1); 174183234Ssimon pk = X509_get_pubkey(recip); 175183234Ssimon if (!pk) 176183234Ssimon { 177183234Ssimon CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, 178183234Ssimon CMS_R_ERROR_GETTING_PUBLIC_KEY); 179183234Ssimon goto err; 180183234Ssimon } 181183234Ssimon CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); 182183234Ssimon ktri->pkey = pk; 183183234Ssimon ktri->recip = recip; 184183234Ssimon 185183234Ssimon if (flags & CMS_USE_KEYID) 186183234Ssimon { 187183234Ssimon ktri->version = 2; 188279264Sdelphij if (env->version < 2) 189279264Sdelphij env->version = 2; 190183234Ssimon type = CMS_RECIPINFO_KEYIDENTIFIER; 191183234Ssimon } 192183234Ssimon else 193183234Ssimon { 194183234Ssimon ktri->version = 0; 195183234Ssimon type = CMS_RECIPINFO_ISSUER_SERIAL; 196183234Ssimon } 197183234Ssimon 198183234Ssimon /* Not a typo: RecipientIdentifier and SignerIdentifier are the 199183234Ssimon * same structure. 200183234Ssimon */ 201183234Ssimon 202183234Ssimon if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) 203183234Ssimon goto err; 204183234Ssimon 205238405Sjkim if (pk->ameth && pk->ameth->pkey_ctrl) 206183234Ssimon { 207238405Sjkim i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE, 208238405Sjkim 0, ri); 209238405Sjkim if (i == -2) 210238405Sjkim { 211238405Sjkim CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, 212183234Ssimon CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 213238405Sjkim goto err; 214238405Sjkim } 215238405Sjkim if (i <= 0) 216238405Sjkim { 217238405Sjkim CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, 218238405Sjkim CMS_R_CTRL_FAILURE); 219238405Sjkim goto err; 220238405Sjkim } 221183234Ssimon } 222183234Ssimon 223183234Ssimon if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) 224183234Ssimon goto merr; 225183234Ssimon 226183234Ssimon return ri; 227183234Ssimon 228183234Ssimon merr: 229183234Ssimon CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); 230183234Ssimon err: 231183234Ssimon if (ri) 232183234Ssimon M_ASN1_free_of(ri, CMS_RecipientInfo); 233183234Ssimon return NULL; 234183234Ssimon 235183234Ssimon } 236183234Ssimon 237183234Ssimonint CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, 238183234Ssimon EVP_PKEY **pk, X509 **recip, 239183234Ssimon X509_ALGOR **palg) 240183234Ssimon { 241183234Ssimon CMS_KeyTransRecipientInfo *ktri; 242183234Ssimon if (ri->type != CMS_RECIPINFO_TRANS) 243183234Ssimon { 244183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS, 245183234Ssimon CMS_R_NOT_KEY_TRANSPORT); 246183234Ssimon return 0; 247183234Ssimon } 248183234Ssimon 249183234Ssimon ktri = ri->d.ktri; 250183234Ssimon 251183234Ssimon if (pk) 252183234Ssimon *pk = ktri->pkey; 253183234Ssimon if (recip) 254183234Ssimon *recip = ktri->recip; 255183234Ssimon if (palg) 256183234Ssimon *palg = ktri->keyEncryptionAlgorithm; 257183234Ssimon return 1; 258183234Ssimon } 259183234Ssimon 260183234Ssimonint CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, 261183234Ssimon ASN1_OCTET_STRING **keyid, 262183234Ssimon X509_NAME **issuer, ASN1_INTEGER **sno) 263183234Ssimon { 264183234Ssimon CMS_KeyTransRecipientInfo *ktri; 265183234Ssimon if (ri->type != CMS_RECIPINFO_TRANS) 266183234Ssimon { 267183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID, 268183234Ssimon CMS_R_NOT_KEY_TRANSPORT); 269183234Ssimon return 0; 270183234Ssimon } 271183234Ssimon ktri = ri->d.ktri; 272183234Ssimon 273183234Ssimon return cms_SignerIdentifier_get0_signer_id(ktri->rid, 274183234Ssimon keyid, issuer, sno); 275183234Ssimon } 276183234Ssimon 277183234Ssimonint CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert) 278183234Ssimon { 279183234Ssimon if (ri->type != CMS_RECIPINFO_TRANS) 280183234Ssimon { 281183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP, 282183234Ssimon CMS_R_NOT_KEY_TRANSPORT); 283183234Ssimon return -2; 284183234Ssimon } 285183234Ssimon return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert); 286183234Ssimon } 287183234Ssimon 288183234Ssimonint CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey) 289183234Ssimon { 290183234Ssimon if (ri->type != CMS_RECIPINFO_TRANS) 291183234Ssimon { 292183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, 293183234Ssimon CMS_R_NOT_KEY_TRANSPORT); 294183234Ssimon return 0; 295183234Ssimon } 296183234Ssimon ri->d.ktri->pkey = pkey; 297183234Ssimon return 1; 298183234Ssimon } 299183234Ssimon 300183234Ssimon/* Encrypt content key in key transport recipient info */ 301183234Ssimon 302183234Ssimonstatic int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, 303183234Ssimon CMS_RecipientInfo *ri) 304183234Ssimon { 305183234Ssimon CMS_KeyTransRecipientInfo *ktri; 306183234Ssimon CMS_EncryptedContentInfo *ec; 307238405Sjkim EVP_PKEY_CTX *pctx = NULL; 308183234Ssimon unsigned char *ek = NULL; 309238405Sjkim size_t eklen; 310183234Ssimon 311183234Ssimon int ret = 0; 312183234Ssimon 313183234Ssimon if (ri->type != CMS_RECIPINFO_TRANS) 314183234Ssimon { 315183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, 316183234Ssimon CMS_R_NOT_KEY_TRANSPORT); 317183234Ssimon return 0; 318183234Ssimon } 319183234Ssimon ktri = ri->d.ktri; 320183234Ssimon ec = cms->d.envelopedData->encryptedContentInfo; 321183234Ssimon 322238405Sjkim pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); 323238405Sjkim if (!pctx) 324238405Sjkim return 0; 325183234Ssimon 326238405Sjkim if (EVP_PKEY_encrypt_init(pctx) <= 0) 327238405Sjkim goto err; 328238405Sjkim 329238405Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, 330238405Sjkim EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) 331238405Sjkim { 332238405Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR); 333238405Sjkim goto err; 334238405Sjkim } 335238405Sjkim 336238405Sjkim if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0) 337238405Sjkim goto err; 338238405Sjkim 339183234Ssimon ek = OPENSSL_malloc(eklen); 340183234Ssimon 341183234Ssimon if (ek == NULL) 342183234Ssimon { 343183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, 344183234Ssimon ERR_R_MALLOC_FAILURE); 345183234Ssimon goto err; 346183234Ssimon } 347183234Ssimon 348238405Sjkim if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0) 349183234Ssimon goto err; 350183234Ssimon 351183234Ssimon ASN1_STRING_set0(ktri->encryptedKey, ek, eklen); 352183234Ssimon ek = NULL; 353183234Ssimon 354183234Ssimon ret = 1; 355183234Ssimon 356183234Ssimon err: 357238405Sjkim if (pctx) 358238405Sjkim EVP_PKEY_CTX_free(pctx); 359183234Ssimon if (ek) 360183234Ssimon OPENSSL_free(ek); 361183234Ssimon return ret; 362183234Ssimon 363183234Ssimon } 364183234Ssimon 365183234Ssimon/* Decrypt content key from KTRI */ 366183234Ssimon 367183234Ssimonstatic int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, 368183234Ssimon CMS_RecipientInfo *ri) 369183234Ssimon { 370183234Ssimon CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; 371238405Sjkim EVP_PKEY_CTX *pctx = NULL; 372183234Ssimon unsigned char *ek = NULL; 373238405Sjkim size_t eklen; 374183234Ssimon int ret = 0; 375237657Sjkim CMS_EncryptedContentInfo *ec; 376237657Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 377183234Ssimon 378183234Ssimon if (ktri->pkey == NULL) 379183234Ssimon { 380183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, 381183234Ssimon CMS_R_NO_PRIVATE_KEY); 382183234Ssimon return 0; 383183234Ssimon } 384183234Ssimon 385238405Sjkim pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); 386238405Sjkim if (!pctx) 387238405Sjkim return 0; 388183234Ssimon 389238405Sjkim if (EVP_PKEY_decrypt_init(pctx) <= 0) 390238405Sjkim goto err; 391238405Sjkim 392238405Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, 393238405Sjkim EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) 394238405Sjkim { 395238405Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); 396238405Sjkim goto err; 397238405Sjkim } 398238405Sjkim 399238405Sjkim if (EVP_PKEY_decrypt(pctx, NULL, &eklen, 400238405Sjkim ktri->encryptedKey->data, 401238405Sjkim ktri->encryptedKey->length) <= 0) 402238405Sjkim goto err; 403238405Sjkim 404183234Ssimon ek = OPENSSL_malloc(eklen); 405183234Ssimon 406183234Ssimon if (ek == NULL) 407183234Ssimon { 408183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, 409183234Ssimon ERR_R_MALLOC_FAILURE); 410183234Ssimon goto err; 411183234Ssimon } 412183234Ssimon 413238405Sjkim if (EVP_PKEY_decrypt(pctx, ek, &eklen, 414183234Ssimon ktri->encryptedKey->data, 415238405Sjkim ktri->encryptedKey->length) <= 0) 416183234Ssimon { 417183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); 418183234Ssimon goto err; 419183234Ssimon } 420183234Ssimon 421183234Ssimon ret = 1; 422183234Ssimon 423237657Sjkim if (ec->key) 424237657Sjkim { 425237657Sjkim OPENSSL_cleanse(ec->key, ec->keylen); 426237657Sjkim OPENSSL_free(ec->key); 427237657Sjkim } 428183234Ssimon 429237657Sjkim ec->key = ek; 430237657Sjkim ec->keylen = eklen; 431237657Sjkim 432183234Ssimon err: 433238405Sjkim if (pctx) 434238405Sjkim EVP_PKEY_CTX_free(pctx); 435183234Ssimon if (!ret && ek) 436183234Ssimon OPENSSL_free(ek); 437183234Ssimon 438183234Ssimon return ret; 439183234Ssimon } 440183234Ssimon 441183234Ssimon/* Key Encrypted Key (KEK) RecipientInfo routines */ 442183234Ssimon 443183234Ssimonint CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, 444183234Ssimon const unsigned char *id, size_t idlen) 445183234Ssimon { 446183234Ssimon ASN1_OCTET_STRING tmp_os; 447183234Ssimon CMS_KEKRecipientInfo *kekri; 448183234Ssimon if (ri->type != CMS_RECIPINFO_KEK) 449183234Ssimon { 450183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK); 451183234Ssimon return -2; 452183234Ssimon } 453183234Ssimon kekri = ri->d.kekri; 454183234Ssimon tmp_os.type = V_ASN1_OCTET_STRING; 455183234Ssimon tmp_os.flags = 0; 456183234Ssimon tmp_os.data = (unsigned char *)id; 457183234Ssimon tmp_os.length = (int)idlen; 458183234Ssimon return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier); 459183234Ssimon } 460183234Ssimon 461183234Ssimon/* For now hard code AES key wrap info */ 462183234Ssimon 463183234Ssimonstatic size_t aes_wrap_keylen(int nid) 464183234Ssimon { 465183234Ssimon switch (nid) 466183234Ssimon { 467183234Ssimon case NID_id_aes128_wrap: 468183234Ssimon return 16; 469183234Ssimon 470183234Ssimon case NID_id_aes192_wrap: 471183234Ssimon return 24; 472183234Ssimon 473183234Ssimon case NID_id_aes256_wrap: 474183234Ssimon return 32; 475183234Ssimon 476183234Ssimon default: 477183234Ssimon return 0; 478183234Ssimon } 479183234Ssimon } 480183234Ssimon 481183234SsimonCMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, 482183234Ssimon unsigned char *key, size_t keylen, 483183234Ssimon unsigned char *id, size_t idlen, 484183234Ssimon ASN1_GENERALIZEDTIME *date, 485183234Ssimon ASN1_OBJECT *otherTypeId, 486183234Ssimon ASN1_TYPE *otherType) 487183234Ssimon { 488183234Ssimon CMS_RecipientInfo *ri = NULL; 489183234Ssimon CMS_EnvelopedData *env; 490183234Ssimon CMS_KEKRecipientInfo *kekri; 491183234Ssimon env = cms_get0_enveloped(cms); 492183234Ssimon if (!env) 493183234Ssimon goto err; 494183234Ssimon 495183234Ssimon if (nid == NID_undef) 496183234Ssimon { 497183234Ssimon switch (keylen) 498183234Ssimon { 499183234Ssimon case 16: 500183234Ssimon nid = NID_id_aes128_wrap; 501183234Ssimon break; 502183234Ssimon 503183234Ssimon case 24: 504183234Ssimon nid = NID_id_aes192_wrap; 505183234Ssimon break; 506183234Ssimon 507183234Ssimon case 32: 508183234Ssimon nid = NID_id_aes256_wrap; 509183234Ssimon break; 510183234Ssimon 511183234Ssimon default: 512183234Ssimon CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, 513183234Ssimon CMS_R_INVALID_KEY_LENGTH); 514183234Ssimon goto err; 515183234Ssimon } 516183234Ssimon 517183234Ssimon } 518183234Ssimon else 519183234Ssimon { 520183234Ssimon 521183234Ssimon size_t exp_keylen = aes_wrap_keylen(nid); 522183234Ssimon 523183234Ssimon if (!exp_keylen) 524183234Ssimon { 525183234Ssimon CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, 526183234Ssimon CMS_R_UNSUPPORTED_KEK_ALGORITHM); 527183234Ssimon goto err; 528183234Ssimon } 529183234Ssimon 530183234Ssimon if (keylen != exp_keylen) 531183234Ssimon { 532183234Ssimon CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, 533183234Ssimon CMS_R_INVALID_KEY_LENGTH); 534183234Ssimon goto err; 535183234Ssimon } 536183234Ssimon 537183234Ssimon } 538183234Ssimon 539183234Ssimon /* Initialize recipient info */ 540183234Ssimon ri = M_ASN1_new_of(CMS_RecipientInfo); 541183234Ssimon if (!ri) 542183234Ssimon goto merr; 543183234Ssimon 544183234Ssimon ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo); 545183234Ssimon if (!ri->d.kekri) 546183234Ssimon goto merr; 547183234Ssimon ri->type = CMS_RECIPINFO_KEK; 548183234Ssimon 549183234Ssimon kekri = ri->d.kekri; 550183234Ssimon 551183234Ssimon if (otherTypeId) 552183234Ssimon { 553183234Ssimon kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute); 554183234Ssimon if (kekri->kekid->other == NULL) 555183234Ssimon goto merr; 556183234Ssimon } 557183234Ssimon 558183234Ssimon if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) 559183234Ssimon goto merr; 560183234Ssimon 561183234Ssimon 562183234Ssimon /* After this point no calls can fail */ 563183234Ssimon 564183234Ssimon kekri->version = 4; 565183234Ssimon 566183234Ssimon kekri->key = key; 567183234Ssimon kekri->keylen = keylen; 568183234Ssimon 569183234Ssimon ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen); 570183234Ssimon 571183234Ssimon kekri->kekid->date = date; 572183234Ssimon 573183234Ssimon if (kekri->kekid->other) 574183234Ssimon { 575183234Ssimon kekri->kekid->other->keyAttrId = otherTypeId; 576183234Ssimon kekri->kekid->other->keyAttr = otherType; 577183234Ssimon } 578183234Ssimon 579183234Ssimon X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, 580183234Ssimon OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); 581183234Ssimon 582183234Ssimon return ri; 583183234Ssimon 584183234Ssimon merr: 585183234Ssimon CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE); 586183234Ssimon err: 587183234Ssimon if (ri) 588183234Ssimon M_ASN1_free_of(ri, CMS_RecipientInfo); 589183234Ssimon return NULL; 590183234Ssimon 591183234Ssimon } 592183234Ssimon 593183234Ssimonint CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, 594183234Ssimon X509_ALGOR **palg, 595183234Ssimon ASN1_OCTET_STRING **pid, 596183234Ssimon ASN1_GENERALIZEDTIME **pdate, 597183234Ssimon ASN1_OBJECT **potherid, 598183234Ssimon ASN1_TYPE **pothertype) 599183234Ssimon { 600183234Ssimon CMS_KEKIdentifier *rkid; 601183234Ssimon if (ri->type != CMS_RECIPINFO_KEK) 602183234Ssimon { 603183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK); 604183234Ssimon return 0; 605183234Ssimon } 606183234Ssimon rkid = ri->d.kekri->kekid; 607183234Ssimon if (palg) 608183234Ssimon *palg = ri->d.kekri->keyEncryptionAlgorithm; 609183234Ssimon if (pid) 610183234Ssimon *pid = rkid->keyIdentifier; 611183234Ssimon if (pdate) 612183234Ssimon *pdate = rkid->date; 613183234Ssimon if (potherid) 614183234Ssimon { 615183234Ssimon if (rkid->other) 616183234Ssimon *potherid = rkid->other->keyAttrId; 617183234Ssimon else 618183234Ssimon *potherid = NULL; 619183234Ssimon } 620183234Ssimon if (pothertype) 621183234Ssimon { 622183234Ssimon if (rkid->other) 623183234Ssimon *pothertype = rkid->other->keyAttr; 624183234Ssimon else 625183234Ssimon *pothertype = NULL; 626183234Ssimon } 627183234Ssimon return 1; 628183234Ssimon } 629183234Ssimon 630183234Ssimonint CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, 631183234Ssimon unsigned char *key, size_t keylen) 632183234Ssimon { 633183234Ssimon CMS_KEKRecipientInfo *kekri; 634183234Ssimon if (ri->type != CMS_RECIPINFO_KEK) 635183234Ssimon { 636183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK); 637183234Ssimon return 0; 638183234Ssimon } 639183234Ssimon 640183234Ssimon kekri = ri->d.kekri; 641183234Ssimon kekri->key = key; 642183234Ssimon kekri->keylen = keylen; 643183234Ssimon return 1; 644183234Ssimon } 645183234Ssimon 646183234Ssimon 647183234Ssimon/* Encrypt content key in KEK recipient info */ 648183234Ssimon 649183234Ssimonstatic int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, 650183234Ssimon CMS_RecipientInfo *ri) 651183234Ssimon { 652183234Ssimon CMS_EncryptedContentInfo *ec; 653183234Ssimon CMS_KEKRecipientInfo *kekri; 654183234Ssimon AES_KEY actx; 655183234Ssimon unsigned char *wkey = NULL; 656183234Ssimon int wkeylen; 657183234Ssimon int r = 0; 658183234Ssimon 659183234Ssimon ec = cms->d.envelopedData->encryptedContentInfo; 660183234Ssimon 661183234Ssimon kekri = ri->d.kekri; 662183234Ssimon 663183234Ssimon if (!kekri->key) 664183234Ssimon { 665183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY); 666183234Ssimon return 0; 667183234Ssimon } 668183234Ssimon 669183234Ssimon if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) 670183234Ssimon { 671183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, 672183234Ssimon CMS_R_ERROR_SETTING_KEY); 673183234Ssimon goto err; 674183234Ssimon } 675183234Ssimon 676183234Ssimon wkey = OPENSSL_malloc(ec->keylen + 8); 677183234Ssimon 678183234Ssimon if (!wkey) 679183234Ssimon { 680183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, 681183234Ssimon ERR_R_MALLOC_FAILURE); 682183234Ssimon goto err; 683183234Ssimon } 684183234Ssimon 685183234Ssimon wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen); 686183234Ssimon 687183234Ssimon if (wkeylen <= 0) 688183234Ssimon { 689183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR); 690183234Ssimon goto err; 691183234Ssimon } 692183234Ssimon 693183234Ssimon ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen); 694183234Ssimon 695183234Ssimon r = 1; 696183234Ssimon 697183234Ssimon err: 698183234Ssimon 699183234Ssimon if (!r && wkey) 700183234Ssimon OPENSSL_free(wkey); 701183234Ssimon OPENSSL_cleanse(&actx, sizeof(actx)); 702183234Ssimon 703183234Ssimon return r; 704183234Ssimon 705183234Ssimon } 706183234Ssimon 707183234Ssimon/* Decrypt content key in KEK recipient info */ 708183234Ssimon 709183234Ssimonstatic int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, 710183234Ssimon CMS_RecipientInfo *ri) 711183234Ssimon { 712183234Ssimon CMS_EncryptedContentInfo *ec; 713183234Ssimon CMS_KEKRecipientInfo *kekri; 714183234Ssimon AES_KEY actx; 715183234Ssimon unsigned char *ukey = NULL; 716183234Ssimon int ukeylen; 717183234Ssimon int r = 0, wrap_nid; 718183234Ssimon 719183234Ssimon ec = cms->d.envelopedData->encryptedContentInfo; 720183234Ssimon 721183234Ssimon kekri = ri->d.kekri; 722183234Ssimon 723183234Ssimon if (!kekri->key) 724183234Ssimon { 725183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY); 726183234Ssimon return 0; 727183234Ssimon } 728183234Ssimon 729183234Ssimon wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm); 730183234Ssimon if (aes_wrap_keylen(wrap_nid) != kekri->keylen) 731183234Ssimon { 732183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 733183234Ssimon CMS_R_INVALID_KEY_LENGTH); 734183234Ssimon return 0; 735183234Ssimon } 736183234Ssimon 737183234Ssimon /* If encrypted key length is invalid don't bother */ 738183234Ssimon 739183234Ssimon if (kekri->encryptedKey->length < 16) 740183234Ssimon { 741183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 742183234Ssimon CMS_R_INVALID_ENCRYPTED_KEY_LENGTH); 743183234Ssimon goto err; 744183234Ssimon } 745183234Ssimon 746183234Ssimon if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) 747183234Ssimon { 748183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 749183234Ssimon CMS_R_ERROR_SETTING_KEY); 750183234Ssimon goto err; 751183234Ssimon } 752183234Ssimon 753183234Ssimon ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); 754183234Ssimon 755183234Ssimon if (!ukey) 756183234Ssimon { 757183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 758183234Ssimon ERR_R_MALLOC_FAILURE); 759183234Ssimon goto err; 760183234Ssimon } 761183234Ssimon 762183234Ssimon ukeylen = AES_unwrap_key(&actx, NULL, ukey, 763183234Ssimon kekri->encryptedKey->data, 764183234Ssimon kekri->encryptedKey->length); 765183234Ssimon 766183234Ssimon if (ukeylen <= 0) 767183234Ssimon { 768183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 769183234Ssimon CMS_R_UNWRAP_ERROR); 770183234Ssimon goto err; 771183234Ssimon } 772183234Ssimon 773183234Ssimon ec->key = ukey; 774183234Ssimon ec->keylen = ukeylen; 775183234Ssimon 776183234Ssimon r = 1; 777183234Ssimon 778183234Ssimon err: 779183234Ssimon 780183234Ssimon if (!r && ukey) 781183234Ssimon OPENSSL_free(ukey); 782183234Ssimon OPENSSL_cleanse(&actx, sizeof(actx)); 783183234Ssimon 784183234Ssimon return r; 785183234Ssimon 786183234Ssimon } 787183234Ssimon 788183234Ssimonint CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) 789183234Ssimon { 790183234Ssimon switch(ri->type) 791183234Ssimon { 792183234Ssimon case CMS_RECIPINFO_TRANS: 793183234Ssimon return cms_RecipientInfo_ktri_decrypt(cms, ri); 794183234Ssimon 795183234Ssimon case CMS_RECIPINFO_KEK: 796183234Ssimon return cms_RecipientInfo_kekri_decrypt(cms, ri); 797183234Ssimon 798238405Sjkim case CMS_RECIPINFO_PASS: 799238405Sjkim return cms_RecipientInfo_pwri_crypt(cms, ri, 0); 800238405Sjkim 801183234Ssimon default: 802183234Ssimon CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, 803183234Ssimon CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE); 804183234Ssimon return 0; 805183234Ssimon } 806183234Ssimon } 807183234Ssimon 808183234SsimonBIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) 809183234Ssimon { 810183234Ssimon CMS_EncryptedContentInfo *ec; 811183234Ssimon STACK_OF(CMS_RecipientInfo) *rinfos; 812183234Ssimon CMS_RecipientInfo *ri; 813183234Ssimon int i, r, ok = 0; 814183234Ssimon BIO *ret; 815183234Ssimon 816183234Ssimon /* Get BIO first to set up key */ 817183234Ssimon 818183234Ssimon ec = cms->d.envelopedData->encryptedContentInfo; 819183234Ssimon ret = cms_EncryptedContent_init_bio(ec); 820183234Ssimon 821183234Ssimon /* If error or no cipher end of processing */ 822183234Ssimon 823183234Ssimon if (!ret || !ec->cipher) 824183234Ssimon return ret; 825183234Ssimon 826183234Ssimon /* Now encrypt content key according to each RecipientInfo type */ 827183234Ssimon 828183234Ssimon rinfos = cms->d.envelopedData->recipientInfos; 829183234Ssimon 830183234Ssimon for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) 831183234Ssimon { 832183234Ssimon ri = sk_CMS_RecipientInfo_value(rinfos, i); 833183234Ssimon 834183234Ssimon switch (ri->type) 835183234Ssimon { 836183234Ssimon case CMS_RECIPINFO_TRANS: 837183234Ssimon r = cms_RecipientInfo_ktri_encrypt(cms, ri); 838183234Ssimon break; 839183234Ssimon 840183234Ssimon case CMS_RECIPINFO_KEK: 841183234Ssimon r = cms_RecipientInfo_kekri_encrypt(cms, ri); 842183234Ssimon break; 843183234Ssimon 844238405Sjkim case CMS_RECIPINFO_PASS: 845238405Sjkim r = cms_RecipientInfo_pwri_crypt(cms, ri, 1); 846238405Sjkim break; 847238405Sjkim 848183234Ssimon default: 849183234Ssimon CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, 850183234Ssimon CMS_R_UNSUPPORTED_RECIPIENT_TYPE); 851183234Ssimon goto err; 852183234Ssimon } 853183234Ssimon 854183234Ssimon if (r <= 0) 855183234Ssimon { 856183234Ssimon CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, 857183234Ssimon CMS_R_ERROR_SETTING_RECIPIENTINFO); 858183234Ssimon goto err; 859183234Ssimon } 860183234Ssimon } 861183234Ssimon 862183234Ssimon ok = 1; 863183234Ssimon 864183234Ssimon err: 865183234Ssimon ec->cipher = NULL; 866183234Ssimon if (ec->key) 867183234Ssimon { 868183234Ssimon OPENSSL_cleanse(ec->key, ec->keylen); 869183234Ssimon OPENSSL_free(ec->key); 870183234Ssimon ec->key = NULL; 871183234Ssimon ec->keylen = 0; 872183234Ssimon } 873183234Ssimon if (ok) 874183234Ssimon return ret; 875183234Ssimon BIO_free(ret); 876183234Ssimon return NULL; 877183234Ssimon 878183234Ssimon } 879