1183234Ssimon/* crypto/cms/cms_env.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 <openssl/rand.h> 62183234Ssimon#include <openssl/aes.h> 63183234Ssimon#include "cms_lcl.h" 64238405Sjkim#include "asn1_locl.h" 65183234Ssimon 66183234Ssimon/* CMS EnvelopedData Utilities */ 67183234Ssimon 68183234SsimonDECLARE_ASN1_ITEM(CMS_EnvelopedData) 69183234SsimonDECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo) 70183234SsimonDECLARE_ASN1_ITEM(CMS_KEKRecipientInfo) 71183234SsimonDECLARE_ASN1_ITEM(CMS_OtherKeyAttribute) 72183234Ssimon 73183234SsimonDECLARE_STACK_OF(CMS_RecipientInfo) 74183234Ssimon 75238405SjkimCMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms) 76280304Sjkim{ 77280304Sjkim if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) { 78280304Sjkim CMSerr(CMS_F_CMS_GET0_ENVELOPED, 79280304Sjkim CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA); 80280304Sjkim return NULL; 81280304Sjkim } 82280304Sjkim return cms->d.envelopedData; 83280304Sjkim} 84183234Ssimon 85183234Ssimonstatic CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms) 86280304Sjkim{ 87280304Sjkim if (cms->d.other == NULL) { 88280304Sjkim cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData); 89280304Sjkim if (!cms->d.envelopedData) { 90280304Sjkim CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, ERR_R_MALLOC_FAILURE); 91280304Sjkim return NULL; 92280304Sjkim } 93280304Sjkim cms->d.envelopedData->version = 0; 94280304Sjkim cms->d.envelopedData->encryptedContentInfo->contentType = 95280304Sjkim OBJ_nid2obj(NID_pkcs7_data); 96280304Sjkim ASN1_OBJECT_free(cms->contentType); 97280304Sjkim cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped); 98280304Sjkim return cms->d.envelopedData; 99280304Sjkim } 100280304Sjkim return cms_get0_enveloped(cms); 101280304Sjkim} 102183234Ssimon 103183234SsimonSTACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms) 104280304Sjkim{ 105280304Sjkim CMS_EnvelopedData *env; 106280304Sjkim env = cms_get0_enveloped(cms); 107280304Sjkim if (!env) 108280304Sjkim return NULL; 109280304Sjkim return env->recipientInfos; 110280304Sjkim} 111183234Ssimon 112183234Ssimonint CMS_RecipientInfo_type(CMS_RecipientInfo *ri) 113280304Sjkim{ 114280304Sjkim return ri->type; 115280304Sjkim} 116183234Ssimon 117183234SsimonCMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher) 118280304Sjkim{ 119280304Sjkim CMS_ContentInfo *cms; 120280304Sjkim CMS_EnvelopedData *env; 121280304Sjkim cms = CMS_ContentInfo_new(); 122280304Sjkim if (!cms) 123280304Sjkim goto merr; 124280304Sjkim env = cms_enveloped_data_init(cms); 125280304Sjkim if (!env) 126280304Sjkim goto merr; 127280304Sjkim if (!cms_EncryptedContent_init(env->encryptedContentInfo, 128280304Sjkim cipher, NULL, 0)) 129280304Sjkim goto merr; 130280304Sjkim return cms; 131280304Sjkim merr: 132280304Sjkim if (cms) 133280304Sjkim CMS_ContentInfo_free(cms); 134280304Sjkim CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE); 135280304Sjkim return NULL; 136280304Sjkim} 137183234Ssimon 138183234Ssimon/* Key Transport Recipient Info (KTRI) routines */ 139183234Ssimon 140280304Sjkim/* 141280304Sjkim * Add a recipient certificate. For now only handle key transport. If we ever 142280304Sjkim * handle key agreement will need updating. 143183234Ssimon */ 144183234Ssimon 145183234SsimonCMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, 146280304Sjkim X509 *recip, unsigned int flags) 147280304Sjkim{ 148280304Sjkim CMS_RecipientInfo *ri = NULL; 149280304Sjkim CMS_KeyTransRecipientInfo *ktri; 150280304Sjkim CMS_EnvelopedData *env; 151280304Sjkim EVP_PKEY *pk = NULL; 152280304Sjkim int i, type; 153280304Sjkim env = cms_get0_enveloped(cms); 154280304Sjkim if (!env) 155280304Sjkim goto err; 156183234Ssimon 157280304Sjkim /* Initialize recipient info */ 158280304Sjkim ri = M_ASN1_new_of(CMS_RecipientInfo); 159280304Sjkim if (!ri) 160280304Sjkim goto merr; 161183234Ssimon 162280304Sjkim /* Initialize and add key transport recipient info */ 163183234Ssimon 164280304Sjkim ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); 165280304Sjkim if (!ri->d.ktri) 166280304Sjkim goto merr; 167280304Sjkim ri->type = CMS_RECIPINFO_TRANS; 168183234Ssimon 169280304Sjkim ktri = ri->d.ktri; 170183234Ssimon 171280304Sjkim X509_check_purpose(recip, -1, -1); 172280304Sjkim pk = X509_get_pubkey(recip); 173280304Sjkim if (!pk) { 174280304Sjkim CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); 175280304Sjkim goto err; 176280304Sjkim } 177280304Sjkim CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); 178280304Sjkim ktri->pkey = pk; 179280304Sjkim ktri->recip = recip; 180183234Ssimon 181280304Sjkim if (flags & CMS_USE_KEYID) { 182280304Sjkim ktri->version = 2; 183280304Sjkim if (env->version < 2) 184280304Sjkim env->version = 2; 185280304Sjkim type = CMS_RECIPINFO_KEYIDENTIFIER; 186280304Sjkim } else { 187280304Sjkim ktri->version = 0; 188280304Sjkim type = CMS_RECIPINFO_ISSUER_SERIAL; 189280304Sjkim } 190183234Ssimon 191280304Sjkim /* 192280304Sjkim * Not a typo: RecipientIdentifier and SignerIdentifier are the same 193280304Sjkim * structure. 194280304Sjkim */ 195183234Ssimon 196280304Sjkim if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) 197280304Sjkim goto err; 198183234Ssimon 199280304Sjkim if (pk->ameth && pk->ameth->pkey_ctrl) { 200280304Sjkim i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE, 0, ri); 201280304Sjkim if (i == -2) { 202280304Sjkim CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, 203280304Sjkim CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 204280304Sjkim goto err; 205280304Sjkim } 206280304Sjkim if (i <= 0) { 207280304Sjkim CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_CTRL_FAILURE); 208280304Sjkim goto err; 209280304Sjkim } 210280304Sjkim } 211183234Ssimon 212280304Sjkim if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) 213280304Sjkim goto merr; 214183234Ssimon 215280304Sjkim return ri; 216183234Ssimon 217280304Sjkim merr: 218280304Sjkim CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); 219280304Sjkim err: 220280304Sjkim if (ri) 221280304Sjkim M_ASN1_free_of(ri, CMS_RecipientInfo); 222280304Sjkim return NULL; 223183234Ssimon 224280304Sjkim} 225183234Ssimon 226183234Ssimonint CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, 227280304Sjkim EVP_PKEY **pk, X509 **recip, 228280304Sjkim X509_ALGOR **palg) 229280304Sjkim{ 230280304Sjkim CMS_KeyTransRecipientInfo *ktri; 231280304Sjkim if (ri->type != CMS_RECIPINFO_TRANS) { 232280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS, 233280304Sjkim CMS_R_NOT_KEY_TRANSPORT); 234280304Sjkim return 0; 235280304Sjkim } 236183234Ssimon 237280304Sjkim ktri = ri->d.ktri; 238183234Ssimon 239280304Sjkim if (pk) 240280304Sjkim *pk = ktri->pkey; 241280304Sjkim if (recip) 242280304Sjkim *recip = ktri->recip; 243280304Sjkim if (palg) 244280304Sjkim *palg = ktri->keyEncryptionAlgorithm; 245280304Sjkim return 1; 246280304Sjkim} 247183234Ssimon 248183234Ssimonint CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, 249280304Sjkim ASN1_OCTET_STRING **keyid, 250280304Sjkim X509_NAME **issuer, 251280304Sjkim ASN1_INTEGER **sno) 252280304Sjkim{ 253280304Sjkim CMS_KeyTransRecipientInfo *ktri; 254280304Sjkim if (ri->type != CMS_RECIPINFO_TRANS) { 255280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID, 256280304Sjkim CMS_R_NOT_KEY_TRANSPORT); 257280304Sjkim return 0; 258280304Sjkim } 259280304Sjkim ktri = ri->d.ktri; 260183234Ssimon 261280304Sjkim return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno); 262280304Sjkim} 263183234Ssimon 264183234Ssimonint CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert) 265280304Sjkim{ 266280304Sjkim if (ri->type != CMS_RECIPINFO_TRANS) { 267280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP, 268280304Sjkim CMS_R_NOT_KEY_TRANSPORT); 269280304Sjkim return -2; 270280304Sjkim } 271280304Sjkim return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert); 272280304Sjkim} 273183234Ssimon 274183234Ssimonint CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey) 275280304Sjkim{ 276280304Sjkim if (ri->type != CMS_RECIPINFO_TRANS) { 277280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, CMS_R_NOT_KEY_TRANSPORT); 278280304Sjkim return 0; 279280304Sjkim } 280280304Sjkim ri->d.ktri->pkey = pkey; 281280304Sjkim return 1; 282280304Sjkim} 283183234Ssimon 284183234Ssimon/* Encrypt content key in key transport recipient info */ 285183234Ssimon 286183234Ssimonstatic int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, 287280304Sjkim CMS_RecipientInfo *ri) 288280304Sjkim{ 289280304Sjkim CMS_KeyTransRecipientInfo *ktri; 290280304Sjkim CMS_EncryptedContentInfo *ec; 291280304Sjkim EVP_PKEY_CTX *pctx = NULL; 292280304Sjkim unsigned char *ek = NULL; 293280304Sjkim size_t eklen; 294183234Ssimon 295280304Sjkim int ret = 0; 296183234Ssimon 297280304Sjkim if (ri->type != CMS_RECIPINFO_TRANS) { 298280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_NOT_KEY_TRANSPORT); 299280304Sjkim return 0; 300280304Sjkim } 301280304Sjkim ktri = ri->d.ktri; 302280304Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 303183234Ssimon 304280304Sjkim pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); 305280304Sjkim if (!pctx) 306280304Sjkim return 0; 307183234Ssimon 308280304Sjkim if (EVP_PKEY_encrypt_init(pctx) <= 0) 309280304Sjkim goto err; 310238405Sjkim 311280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, 312280304Sjkim EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) { 313280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR); 314280304Sjkim goto err; 315280304Sjkim } 316238405Sjkim 317280304Sjkim if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0) 318280304Sjkim goto err; 319238405Sjkim 320280304Sjkim ek = OPENSSL_malloc(eklen); 321183234Ssimon 322280304Sjkim if (ek == NULL) { 323280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, ERR_R_MALLOC_FAILURE); 324280304Sjkim goto err; 325280304Sjkim } 326183234Ssimon 327280304Sjkim if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0) 328280304Sjkim goto err; 329183234Ssimon 330280304Sjkim ASN1_STRING_set0(ktri->encryptedKey, ek, eklen); 331280304Sjkim ek = NULL; 332183234Ssimon 333280304Sjkim ret = 1; 334183234Ssimon 335280304Sjkim err: 336280304Sjkim if (pctx) 337280304Sjkim EVP_PKEY_CTX_free(pctx); 338280304Sjkim if (ek) 339280304Sjkim OPENSSL_free(ek); 340280304Sjkim return ret; 341183234Ssimon 342280304Sjkim} 343183234Ssimon 344183234Ssimon/* Decrypt content key from KTRI */ 345183234Ssimon 346183234Ssimonstatic int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, 347280304Sjkim CMS_RecipientInfo *ri) 348280304Sjkim{ 349280304Sjkim CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; 350280304Sjkim EVP_PKEY_CTX *pctx = NULL; 351280304Sjkim unsigned char *ek = NULL; 352280304Sjkim size_t eklen; 353280304Sjkim int ret = 0; 354280304Sjkim CMS_EncryptedContentInfo *ec; 355280304Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 356183234Ssimon 357280304Sjkim if (ktri->pkey == NULL) { 358280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY); 359280304Sjkim return 0; 360280304Sjkim } 361183234Ssimon 362280304Sjkim pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); 363280304Sjkim if (!pctx) 364280304Sjkim return 0; 365183234Ssimon 366280304Sjkim if (EVP_PKEY_decrypt_init(pctx) <= 0) 367280304Sjkim goto err; 368238405Sjkim 369280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, 370280304Sjkim EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) { 371280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); 372280304Sjkim goto err; 373280304Sjkim } 374238405Sjkim 375280304Sjkim if (EVP_PKEY_decrypt(pctx, NULL, &eklen, 376280304Sjkim ktri->encryptedKey->data, 377280304Sjkim ktri->encryptedKey->length) <= 0) 378280304Sjkim goto err; 379238405Sjkim 380280304Sjkim ek = OPENSSL_malloc(eklen); 381183234Ssimon 382280304Sjkim if (ek == NULL) { 383280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE); 384280304Sjkim goto err; 385280304Sjkim } 386183234Ssimon 387280304Sjkim if (EVP_PKEY_decrypt(pctx, ek, &eklen, 388280304Sjkim ktri->encryptedKey->data, 389280304Sjkim ktri->encryptedKey->length) <= 0) { 390280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); 391280304Sjkim goto err; 392280304Sjkim } 393183234Ssimon 394280304Sjkim ret = 1; 395183234Ssimon 396280304Sjkim if (ec->key) { 397280304Sjkim OPENSSL_cleanse(ec->key, ec->keylen); 398280304Sjkim OPENSSL_free(ec->key); 399280304Sjkim } 400183234Ssimon 401280304Sjkim ec->key = ek; 402280304Sjkim ec->keylen = eklen; 403237657Sjkim 404280304Sjkim err: 405280304Sjkim if (pctx) 406280304Sjkim EVP_PKEY_CTX_free(pctx); 407280304Sjkim if (!ret && ek) 408280304Sjkim OPENSSL_free(ek); 409183234Ssimon 410280304Sjkim return ret; 411280304Sjkim} 412183234Ssimon 413183234Ssimon/* Key Encrypted Key (KEK) RecipientInfo routines */ 414183234Ssimon 415280304Sjkimint CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, 416280304Sjkim const unsigned char *id, size_t idlen) 417280304Sjkim{ 418280304Sjkim ASN1_OCTET_STRING tmp_os; 419280304Sjkim CMS_KEKRecipientInfo *kekri; 420280304Sjkim if (ri->type != CMS_RECIPINFO_KEK) { 421280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK); 422280304Sjkim return -2; 423280304Sjkim } 424280304Sjkim kekri = ri->d.kekri; 425280304Sjkim tmp_os.type = V_ASN1_OCTET_STRING; 426280304Sjkim tmp_os.flags = 0; 427280304Sjkim tmp_os.data = (unsigned char *)id; 428280304Sjkim tmp_os.length = (int)idlen; 429280304Sjkim return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier); 430280304Sjkim} 431183234Ssimon 432183234Ssimon/* For now hard code AES key wrap info */ 433183234Ssimon 434183234Ssimonstatic size_t aes_wrap_keylen(int nid) 435280304Sjkim{ 436280304Sjkim switch (nid) { 437280304Sjkim case NID_id_aes128_wrap: 438280304Sjkim return 16; 439183234Ssimon 440280304Sjkim case NID_id_aes192_wrap: 441280304Sjkim return 24; 442183234Ssimon 443280304Sjkim case NID_id_aes256_wrap: 444280304Sjkim return 32; 445183234Ssimon 446280304Sjkim default: 447280304Sjkim return 0; 448280304Sjkim } 449280304Sjkim} 450183234Ssimon 451183234SsimonCMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, 452280304Sjkim unsigned char *key, size_t keylen, 453280304Sjkim unsigned char *id, size_t idlen, 454280304Sjkim ASN1_GENERALIZEDTIME *date, 455280304Sjkim ASN1_OBJECT *otherTypeId, 456280304Sjkim ASN1_TYPE *otherType) 457280304Sjkim{ 458280304Sjkim CMS_RecipientInfo *ri = NULL; 459280304Sjkim CMS_EnvelopedData *env; 460280304Sjkim CMS_KEKRecipientInfo *kekri; 461280304Sjkim env = cms_get0_enveloped(cms); 462280304Sjkim if (!env) 463280304Sjkim goto err; 464183234Ssimon 465280304Sjkim if (nid == NID_undef) { 466280304Sjkim switch (keylen) { 467280304Sjkim case 16: 468280304Sjkim nid = NID_id_aes128_wrap; 469280304Sjkim break; 470183234Ssimon 471280304Sjkim case 24: 472280304Sjkim nid = NID_id_aes192_wrap; 473280304Sjkim break; 474183234Ssimon 475280304Sjkim case 32: 476280304Sjkim nid = NID_id_aes256_wrap; 477280304Sjkim break; 478183234Ssimon 479280304Sjkim default: 480280304Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH); 481280304Sjkim goto err; 482280304Sjkim } 483183234Ssimon 484280304Sjkim } else { 485183234Ssimon 486280304Sjkim size_t exp_keylen = aes_wrap_keylen(nid); 487183234Ssimon 488280304Sjkim if (!exp_keylen) { 489280304Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, 490280304Sjkim CMS_R_UNSUPPORTED_KEK_ALGORITHM); 491280304Sjkim goto err; 492280304Sjkim } 493183234Ssimon 494280304Sjkim if (keylen != exp_keylen) { 495280304Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH); 496280304Sjkim goto err; 497280304Sjkim } 498183234Ssimon 499280304Sjkim } 500183234Ssimon 501280304Sjkim /* Initialize recipient info */ 502280304Sjkim ri = M_ASN1_new_of(CMS_RecipientInfo); 503280304Sjkim if (!ri) 504280304Sjkim goto merr; 505183234Ssimon 506280304Sjkim ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo); 507280304Sjkim if (!ri->d.kekri) 508280304Sjkim goto merr; 509280304Sjkim ri->type = CMS_RECIPINFO_KEK; 510183234Ssimon 511280304Sjkim kekri = ri->d.kekri; 512183234Ssimon 513280304Sjkim if (otherTypeId) { 514280304Sjkim kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute); 515280304Sjkim if (kekri->kekid->other == NULL) 516280304Sjkim goto merr; 517280304Sjkim } 518183234Ssimon 519280304Sjkim if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) 520280304Sjkim goto merr; 521183234Ssimon 522280304Sjkim /* After this point no calls can fail */ 523183234Ssimon 524280304Sjkim kekri->version = 4; 525183234Ssimon 526280304Sjkim kekri->key = key; 527280304Sjkim kekri->keylen = keylen; 528183234Ssimon 529280304Sjkim ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen); 530183234Ssimon 531280304Sjkim kekri->kekid->date = date; 532183234Ssimon 533280304Sjkim if (kekri->kekid->other) { 534280304Sjkim kekri->kekid->other->keyAttrId = otherTypeId; 535280304Sjkim kekri->kekid->other->keyAttr = otherType; 536280304Sjkim } 537183234Ssimon 538280304Sjkim X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, 539280304Sjkim OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); 540183234Ssimon 541280304Sjkim return ri; 542183234Ssimon 543280304Sjkim merr: 544280304Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE); 545280304Sjkim err: 546280304Sjkim if (ri) 547280304Sjkim M_ASN1_free_of(ri, CMS_RecipientInfo); 548280304Sjkim return NULL; 549183234Ssimon 550280304Sjkim} 551183234Ssimon 552183234Ssimonint CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, 553280304Sjkim X509_ALGOR **palg, 554280304Sjkim ASN1_OCTET_STRING **pid, 555280304Sjkim ASN1_GENERALIZEDTIME **pdate, 556280304Sjkim ASN1_OBJECT **potherid, 557280304Sjkim ASN1_TYPE **pothertype) 558280304Sjkim{ 559280304Sjkim CMS_KEKIdentifier *rkid; 560280304Sjkim if (ri->type != CMS_RECIPINFO_KEK) { 561280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK); 562280304Sjkim return 0; 563280304Sjkim } 564280304Sjkim rkid = ri->d.kekri->kekid; 565280304Sjkim if (palg) 566280304Sjkim *palg = ri->d.kekri->keyEncryptionAlgorithm; 567280304Sjkim if (pid) 568280304Sjkim *pid = rkid->keyIdentifier; 569280304Sjkim if (pdate) 570280304Sjkim *pdate = rkid->date; 571280304Sjkim if (potherid) { 572280304Sjkim if (rkid->other) 573280304Sjkim *potherid = rkid->other->keyAttrId; 574280304Sjkim else 575280304Sjkim *potherid = NULL; 576280304Sjkim } 577280304Sjkim if (pothertype) { 578280304Sjkim if (rkid->other) 579280304Sjkim *pothertype = rkid->other->keyAttr; 580280304Sjkim else 581280304Sjkim *pothertype = NULL; 582280304Sjkim } 583280304Sjkim return 1; 584280304Sjkim} 585183234Ssimon 586280304Sjkimint CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, 587280304Sjkim unsigned char *key, size_t keylen) 588280304Sjkim{ 589280304Sjkim CMS_KEKRecipientInfo *kekri; 590280304Sjkim if (ri->type != CMS_RECIPINFO_KEK) { 591280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK); 592280304Sjkim return 0; 593280304Sjkim } 594183234Ssimon 595280304Sjkim kekri = ri->d.kekri; 596280304Sjkim kekri->key = key; 597280304Sjkim kekri->keylen = keylen; 598280304Sjkim return 1; 599280304Sjkim} 600183234Ssimon 601183234Ssimon/* Encrypt content key in KEK recipient info */ 602183234Ssimon 603183234Ssimonstatic int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, 604280304Sjkim CMS_RecipientInfo *ri) 605280304Sjkim{ 606280304Sjkim CMS_EncryptedContentInfo *ec; 607280304Sjkim CMS_KEKRecipientInfo *kekri; 608280304Sjkim AES_KEY actx; 609280304Sjkim unsigned char *wkey = NULL; 610280304Sjkim int wkeylen; 611280304Sjkim int r = 0; 612183234Ssimon 613280304Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 614183234Ssimon 615280304Sjkim kekri = ri->d.kekri; 616183234Ssimon 617280304Sjkim if (!kekri->key) { 618280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY); 619280304Sjkim return 0; 620280304Sjkim } 621183234Ssimon 622280304Sjkim if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) { 623280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, 624280304Sjkim CMS_R_ERROR_SETTING_KEY); 625280304Sjkim goto err; 626280304Sjkim } 627183234Ssimon 628280304Sjkim wkey = OPENSSL_malloc(ec->keylen + 8); 629183234Ssimon 630280304Sjkim if (!wkey) { 631280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, ERR_R_MALLOC_FAILURE); 632280304Sjkim goto err; 633280304Sjkim } 634183234Ssimon 635280304Sjkim wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen); 636183234Ssimon 637280304Sjkim if (wkeylen <= 0) { 638280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR); 639280304Sjkim goto err; 640280304Sjkim } 641183234Ssimon 642280304Sjkim ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen); 643183234Ssimon 644280304Sjkim r = 1; 645183234Ssimon 646280304Sjkim err: 647183234Ssimon 648280304Sjkim if (!r && wkey) 649280304Sjkim OPENSSL_free(wkey); 650280304Sjkim OPENSSL_cleanse(&actx, sizeof(actx)); 651183234Ssimon 652280304Sjkim return r; 653183234Ssimon 654280304Sjkim} 655183234Ssimon 656183234Ssimon/* Decrypt content key in KEK recipient info */ 657183234Ssimon 658183234Ssimonstatic int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, 659280304Sjkim CMS_RecipientInfo *ri) 660280304Sjkim{ 661280304Sjkim CMS_EncryptedContentInfo *ec; 662280304Sjkim CMS_KEKRecipientInfo *kekri; 663280304Sjkim AES_KEY actx; 664280304Sjkim unsigned char *ukey = NULL; 665280304Sjkim int ukeylen; 666280304Sjkim int r = 0, wrap_nid; 667183234Ssimon 668280304Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 669183234Ssimon 670280304Sjkim kekri = ri->d.kekri; 671183234Ssimon 672280304Sjkim if (!kekri->key) { 673280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY); 674280304Sjkim return 0; 675280304Sjkim } 676183234Ssimon 677280304Sjkim wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm); 678280304Sjkim if (aes_wrap_keylen(wrap_nid) != kekri->keylen) { 679280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 680280304Sjkim CMS_R_INVALID_KEY_LENGTH); 681280304Sjkim return 0; 682280304Sjkim } 683183234Ssimon 684280304Sjkim /* If encrypted key length is invalid don't bother */ 685183234Ssimon 686280304Sjkim if (kekri->encryptedKey->length < 16) { 687280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 688280304Sjkim CMS_R_INVALID_ENCRYPTED_KEY_LENGTH); 689280304Sjkim goto err; 690280304Sjkim } 691183234Ssimon 692280304Sjkim if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) { 693280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, 694280304Sjkim CMS_R_ERROR_SETTING_KEY); 695280304Sjkim goto err; 696280304Sjkim } 697183234Ssimon 698280304Sjkim ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); 699183234Ssimon 700280304Sjkim if (!ukey) { 701280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, ERR_R_MALLOC_FAILURE); 702280304Sjkim goto err; 703280304Sjkim } 704183234Ssimon 705280304Sjkim ukeylen = AES_unwrap_key(&actx, NULL, ukey, 706280304Sjkim kekri->encryptedKey->data, 707280304Sjkim kekri->encryptedKey->length); 708183234Ssimon 709280304Sjkim if (ukeylen <= 0) { 710280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_UNWRAP_ERROR); 711280304Sjkim goto err; 712280304Sjkim } 713183234Ssimon 714280304Sjkim ec->key = ukey; 715280304Sjkim ec->keylen = ukeylen; 716183234Ssimon 717280304Sjkim r = 1; 718183234Ssimon 719280304Sjkim err: 720183234Ssimon 721280304Sjkim if (!r && ukey) 722280304Sjkim OPENSSL_free(ukey); 723280304Sjkim OPENSSL_cleanse(&actx, sizeof(actx)); 724183234Ssimon 725280304Sjkim return r; 726183234Ssimon 727280304Sjkim} 728183234Ssimon 729183234Ssimonint CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) 730280304Sjkim{ 731280304Sjkim switch (ri->type) { 732280304Sjkim case CMS_RECIPINFO_TRANS: 733280304Sjkim return cms_RecipientInfo_ktri_decrypt(cms, ri); 734183234Ssimon 735280304Sjkim case CMS_RECIPINFO_KEK: 736280304Sjkim return cms_RecipientInfo_kekri_decrypt(cms, ri); 737183234Ssimon 738280304Sjkim case CMS_RECIPINFO_PASS: 739280304Sjkim return cms_RecipientInfo_pwri_crypt(cms, ri, 0); 740238405Sjkim 741280304Sjkim default: 742280304Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, 743280304Sjkim CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE); 744280304Sjkim return 0; 745280304Sjkim } 746280304Sjkim} 747183234Ssimon 748183234SsimonBIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) 749280304Sjkim{ 750280304Sjkim CMS_EncryptedContentInfo *ec; 751280304Sjkim STACK_OF(CMS_RecipientInfo) *rinfos; 752280304Sjkim CMS_RecipientInfo *ri; 753280304Sjkim int i, r, ok = 0; 754280304Sjkim BIO *ret; 755183234Ssimon 756280304Sjkim /* Get BIO first to set up key */ 757183234Ssimon 758280304Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 759280304Sjkim ret = cms_EncryptedContent_init_bio(ec); 760183234Ssimon 761280304Sjkim /* If error or no cipher end of processing */ 762183234Ssimon 763280304Sjkim if (!ret || !ec->cipher) 764280304Sjkim return ret; 765183234Ssimon 766280304Sjkim /* Now encrypt content key according to each RecipientInfo type */ 767183234Ssimon 768280304Sjkim rinfos = cms->d.envelopedData->recipientInfos; 769183234Ssimon 770280304Sjkim for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) { 771280304Sjkim ri = sk_CMS_RecipientInfo_value(rinfos, i); 772183234Ssimon 773280304Sjkim switch (ri->type) { 774280304Sjkim case CMS_RECIPINFO_TRANS: 775280304Sjkim r = cms_RecipientInfo_ktri_encrypt(cms, ri); 776280304Sjkim break; 777183234Ssimon 778280304Sjkim case CMS_RECIPINFO_KEK: 779280304Sjkim r = cms_RecipientInfo_kekri_encrypt(cms, ri); 780280304Sjkim break; 781183234Ssimon 782280304Sjkim case CMS_RECIPINFO_PASS: 783280304Sjkim r = cms_RecipientInfo_pwri_crypt(cms, ri, 1); 784280304Sjkim break; 785238405Sjkim 786280304Sjkim default: 787280304Sjkim CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, 788280304Sjkim CMS_R_UNSUPPORTED_RECIPIENT_TYPE); 789280304Sjkim goto err; 790280304Sjkim } 791183234Ssimon 792280304Sjkim if (r <= 0) { 793280304Sjkim CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, 794280304Sjkim CMS_R_ERROR_SETTING_RECIPIENTINFO); 795280304Sjkim goto err; 796280304Sjkim } 797280304Sjkim } 798183234Ssimon 799280304Sjkim ok = 1; 800183234Ssimon 801280304Sjkim err: 802280304Sjkim ec->cipher = NULL; 803280304Sjkim if (ec->key) { 804280304Sjkim OPENSSL_cleanse(ec->key, ec->keylen); 805280304Sjkim OPENSSL_free(ec->key); 806280304Sjkim ec->key = NULL; 807280304Sjkim ec->keylen = 0; 808280304Sjkim } 809280304Sjkim if (ok) 810280304Sjkim return ret; 811280304Sjkim BIO_free(ret); 812280304Sjkim return NULL; 813183234Ssimon 814280304Sjkim} 815