1238384Sjkim/* crypto/cms/cms_pwri.c */ 2280297Sjkim/* 3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4238384Sjkim * project. 5238384Sjkim */ 6238384Sjkim/* ==================================================================== 7238384Sjkim * Copyright (c) 2009 The OpenSSL Project. All rights reserved. 8238384Sjkim * 9238384Sjkim * Redistribution and use in source and binary forms, with or without 10238384Sjkim * modification, are permitted provided that the following conditions 11238384Sjkim * are met: 12238384Sjkim * 13238384Sjkim * 1. Redistributions of source code must retain the above copyright 14280297Sjkim * notice, this list of conditions and the following disclaimer. 15238384Sjkim * 16238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 17238384Sjkim * notice, this list of conditions and the following disclaimer in 18238384Sjkim * the documentation and/or other materials provided with the 19238384Sjkim * distribution. 20238384Sjkim * 21238384Sjkim * 3. All advertising materials mentioning features or use of this 22238384Sjkim * software must display the following acknowledgment: 23238384Sjkim * "This product includes software developed by the OpenSSL Project 24238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25238384Sjkim * 26238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27238384Sjkim * endorse or promote products derived from this software without 28238384Sjkim * prior written permission. For written permission, please contact 29238384Sjkim * licensing@OpenSSL.org. 30238384Sjkim * 31238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 32238384Sjkim * nor may "OpenSSL" appear in their names without prior written 33238384Sjkim * permission of the OpenSSL Project. 34238384Sjkim * 35238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 36238384Sjkim * acknowledgment: 37238384Sjkim * "This product includes software developed by the OpenSSL Project 38238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39238384Sjkim * 40238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 52238384Sjkim * ==================================================================== 53238384Sjkim */ 54238384Sjkim 55238384Sjkim#include "cryptlib.h" 56238384Sjkim#include <openssl/asn1t.h> 57238384Sjkim#include <openssl/pem.h> 58238384Sjkim#include <openssl/x509v3.h> 59238384Sjkim#include <openssl/err.h> 60238384Sjkim#include <openssl/cms.h> 61238384Sjkim#include <openssl/rand.h> 62238384Sjkim#include <openssl/aes.h> 63238384Sjkim#include "cms_lcl.h" 64238384Sjkim#include "asn1_locl.h" 65238384Sjkim 66280297Sjkimint CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, 67280297Sjkim unsigned char *pass, ossl_ssize_t passlen) 68280297Sjkim{ 69280297Sjkim CMS_PasswordRecipientInfo *pwri; 70280297Sjkim if (ri->type != CMS_RECIPINFO_PASS) { 71280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI); 72280297Sjkim return 0; 73280297Sjkim } 74238384Sjkim 75280297Sjkim pwri = ri->d.pwri; 76280297Sjkim pwri->pass = pass; 77280297Sjkim if (pass && passlen < 0) 78280297Sjkim passlen = strlen((char *)pass); 79280297Sjkim pwri->passlen = passlen; 80280297Sjkim return 1; 81280297Sjkim} 82238384Sjkim 83238384SjkimCMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, 84280297Sjkim int iter, int wrap_nid, 85280297Sjkim int pbe_nid, 86280297Sjkim unsigned char *pass, 87280297Sjkim ossl_ssize_t passlen, 88280297Sjkim const EVP_CIPHER *kekciph) 89280297Sjkim{ 90280297Sjkim CMS_RecipientInfo *ri = NULL; 91280297Sjkim CMS_EnvelopedData *env; 92280297Sjkim CMS_PasswordRecipientInfo *pwri; 93280297Sjkim EVP_CIPHER_CTX ctx; 94280297Sjkim X509_ALGOR *encalg = NULL; 95280297Sjkim unsigned char iv[EVP_MAX_IV_LENGTH]; 96280297Sjkim int ivlen; 97269682Sjkim 98280297Sjkim env = cms_get0_enveloped(cms); 99280297Sjkim if (!env) 100280297Sjkim return NULL; 101238384Sjkim 102280297Sjkim if (wrap_nid <= 0) 103280297Sjkim wrap_nid = NID_id_alg_PWRI_KEK; 104238384Sjkim 105280297Sjkim if (pbe_nid <= 0) 106280297Sjkim pbe_nid = NID_id_pbkdf2; 107238384Sjkim 108280297Sjkim /* Get from enveloped data */ 109280297Sjkim if (kekciph == NULL) 110280297Sjkim kekciph = env->encryptedContentInfo->cipher; 111238384Sjkim 112280297Sjkim if (kekciph == NULL) { 113280297Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER); 114280297Sjkim return NULL; 115280297Sjkim } 116280297Sjkim if (wrap_nid != NID_id_alg_PWRI_KEK) { 117280297Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 118280297Sjkim CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); 119280297Sjkim return NULL; 120280297Sjkim } 121238384Sjkim 122280297Sjkim /* Setup algorithm identifier for cipher */ 123280297Sjkim encalg = X509_ALGOR_new(); 124291719Sjkim if (encalg == NULL) { 125291719Sjkim goto merr; 126291719Sjkim } 127280297Sjkim EVP_CIPHER_CTX_init(&ctx); 128238384Sjkim 129280297Sjkim if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0) { 130280297Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); 131280297Sjkim goto err; 132280297Sjkim } 133238384Sjkim 134280297Sjkim ivlen = EVP_CIPHER_CTX_iv_length(&ctx); 135238384Sjkim 136280297Sjkim if (ivlen > 0) { 137306195Sjkim if (RAND_bytes(iv, ivlen) <= 0) 138280297Sjkim goto err; 139280297Sjkim if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0) { 140280297Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); 141280297Sjkim goto err; 142280297Sjkim } 143280297Sjkim encalg->parameter = ASN1_TYPE_new(); 144280297Sjkim if (!encalg->parameter) { 145280297Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); 146280297Sjkim goto err; 147280297Sjkim } 148280297Sjkim if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0) { 149280297Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 150280297Sjkim CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 151280297Sjkim goto err; 152280297Sjkim } 153280297Sjkim } 154238384Sjkim 155280297Sjkim encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx)); 156238384Sjkim 157280297Sjkim EVP_CIPHER_CTX_cleanup(&ctx); 158238384Sjkim 159280297Sjkim /* Initialize recipient info */ 160280297Sjkim ri = M_ASN1_new_of(CMS_RecipientInfo); 161280297Sjkim if (!ri) 162280297Sjkim goto merr; 163238384Sjkim 164280297Sjkim ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); 165280297Sjkim if (!ri->d.pwri) 166280297Sjkim goto merr; 167280297Sjkim ri->type = CMS_RECIPINFO_PASS; 168238384Sjkim 169280297Sjkim pwri = ri->d.pwri; 170280297Sjkim /* Since this is overwritten, free up empty structure already there */ 171280297Sjkim X509_ALGOR_free(pwri->keyEncryptionAlgorithm); 172280297Sjkim pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); 173280297Sjkim if (!pwri->keyEncryptionAlgorithm) 174280297Sjkim goto merr; 175280297Sjkim pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); 176280297Sjkim pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); 177280297Sjkim if (!pwri->keyEncryptionAlgorithm->parameter) 178280297Sjkim goto merr; 179238384Sjkim 180280297Sjkim if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), 181280297Sjkim &pwri->keyEncryptionAlgorithm->parameter-> 182280297Sjkim value.sequence)) 183280297Sjkim goto merr; 184280297Sjkim pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; 185238384Sjkim 186280297Sjkim X509_ALGOR_free(encalg); 187280297Sjkim encalg = NULL; 188238384Sjkim 189280297Sjkim /* Setup PBE algorithm */ 190238384Sjkim 191280297Sjkim pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); 192238384Sjkim 193280297Sjkim if (!pwri->keyDerivationAlgorithm) 194280297Sjkim goto err; 195238384Sjkim 196280297Sjkim CMS_RecipientInfo_set0_password(ri, pass, passlen); 197280297Sjkim pwri->version = 0; 198238384Sjkim 199280297Sjkim if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) 200280297Sjkim goto merr; 201238384Sjkim 202280297Sjkim return ri; 203238384Sjkim 204280297Sjkim merr: 205280297Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); 206280297Sjkim err: 207280297Sjkim EVP_CIPHER_CTX_cleanup(&ctx); 208280297Sjkim if (ri) 209280297Sjkim M_ASN1_free_of(ri, CMS_RecipientInfo); 210280297Sjkim if (encalg) 211280297Sjkim X509_ALGOR_free(encalg); 212280297Sjkim return NULL; 213238384Sjkim 214280297Sjkim} 215238384Sjkim 216280297Sjkim/* 217280297Sjkim * This is an implementation of the key wrapping mechanism in RFC3211, at 218280297Sjkim * some point this should go into EVP. 219238384Sjkim */ 220238384Sjkim 221238384Sjkimstatic int kek_unwrap_key(unsigned char *out, size_t *outlen, 222280297Sjkim const unsigned char *in, size_t inlen, 223280297Sjkim EVP_CIPHER_CTX *ctx) 224280297Sjkim{ 225280297Sjkim size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); 226280297Sjkim unsigned char *tmp; 227280297Sjkim int outl, rv = 0; 228280297Sjkim if (inlen < 2 * blocklen) { 229280297Sjkim /* too small */ 230280297Sjkim return 0; 231280297Sjkim } 232280297Sjkim if (inlen % blocklen) { 233280297Sjkim /* Invalid size */ 234280297Sjkim return 0; 235280297Sjkim } 236280297Sjkim tmp = OPENSSL_malloc(inlen); 237284283Sjkim if (!tmp) 238280297Sjkim return 0; 239280297Sjkim /* setup IV by decrypting last two blocks */ 240280297Sjkim EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, 241280297Sjkim in + inlen - 2 * blocklen, blocklen * 2); 242280297Sjkim /* 243280297Sjkim * Do a decrypt of last decrypted block to set IV to correct value output 244280297Sjkim * it to start of buffer so we don't corrupt decrypted block this works 245280297Sjkim * because buffer is at least two block lengths long. 246280297Sjkim */ 247280297Sjkim EVP_DecryptUpdate(ctx, tmp, &outl, tmp + inlen - blocklen, blocklen); 248280297Sjkim /* Can now decrypt first n - 1 blocks */ 249280297Sjkim EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen); 250238384Sjkim 251280297Sjkim /* Reset IV to original value */ 252280297Sjkim EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL); 253280297Sjkim /* Decrypt again */ 254280297Sjkim EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen); 255280297Sjkim /* Check check bytes */ 256280297Sjkim if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) { 257280297Sjkim /* Check byte failure */ 258280297Sjkim goto err; 259280297Sjkim } 260280297Sjkim if (inlen < (size_t)(tmp[0] - 4)) { 261280297Sjkim /* Invalid length value */ 262280297Sjkim goto err; 263280297Sjkim } 264280297Sjkim *outlen = (size_t)tmp[0]; 265280297Sjkim memcpy(out, tmp + 4, *outlen); 266280297Sjkim rv = 1; 267280297Sjkim err: 268280297Sjkim OPENSSL_cleanse(tmp, inlen); 269280297Sjkim OPENSSL_free(tmp); 270280297Sjkim return rv; 271238384Sjkim 272280297Sjkim} 273238384Sjkim 274238384Sjkimstatic int kek_wrap_key(unsigned char *out, size_t *outlen, 275280297Sjkim const unsigned char *in, size_t inlen, 276280297Sjkim EVP_CIPHER_CTX *ctx) 277280297Sjkim{ 278280297Sjkim size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); 279280297Sjkim size_t olen; 280280297Sjkim int dummy; 281280297Sjkim /* 282280297Sjkim * First decide length of output buffer: need header and round up to 283280297Sjkim * multiple of block length. 284280297Sjkim */ 285280297Sjkim olen = (inlen + 4 + blocklen - 1) / blocklen; 286280297Sjkim olen *= blocklen; 287280297Sjkim if (olen < 2 * blocklen) { 288280297Sjkim /* Key too small */ 289280297Sjkim return 0; 290280297Sjkim } 291280297Sjkim if (inlen > 0xFF) { 292280297Sjkim /* Key too large */ 293280297Sjkim return 0; 294280297Sjkim } 295280297Sjkim if (out) { 296280297Sjkim /* Set header */ 297280297Sjkim out[0] = (unsigned char)inlen; 298280297Sjkim out[1] = in[0] ^ 0xFF; 299280297Sjkim out[2] = in[1] ^ 0xFF; 300280297Sjkim out[3] = in[2] ^ 0xFF; 301280297Sjkim memcpy(out + 4, in, inlen); 302280297Sjkim /* Add random padding to end */ 303284283Sjkim if (olen > inlen + 4 304306195Sjkim && RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0) 305284283Sjkim return 0; 306280297Sjkim /* Encrypt twice */ 307280297Sjkim EVP_EncryptUpdate(ctx, out, &dummy, out, olen); 308280297Sjkim EVP_EncryptUpdate(ctx, out, &dummy, out, olen); 309280297Sjkim } 310238384Sjkim 311280297Sjkim *outlen = olen; 312238384Sjkim 313280297Sjkim return 1; 314280297Sjkim} 315238384Sjkim 316238384Sjkim/* Encrypt/Decrypt content key in PWRI recipient info */ 317238384Sjkim 318238384Sjkimint cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, 319280297Sjkim int en_de) 320280297Sjkim{ 321280297Sjkim CMS_EncryptedContentInfo *ec; 322280297Sjkim CMS_PasswordRecipientInfo *pwri; 323280297Sjkim const unsigned char *p = NULL; 324280297Sjkim int plen; 325280297Sjkim int r = 0; 326280297Sjkim X509_ALGOR *algtmp, *kekalg = NULL; 327280297Sjkim EVP_CIPHER_CTX kekctx; 328280297Sjkim const EVP_CIPHER *kekcipher; 329280297Sjkim unsigned char *key = NULL; 330280297Sjkim size_t keylen; 331238384Sjkim 332280297Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 333238384Sjkim 334280297Sjkim pwri = ri->d.pwri; 335280297Sjkim EVP_CIPHER_CTX_init(&kekctx); 336238384Sjkim 337280297Sjkim if (!pwri->pass) { 338280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD); 339280297Sjkim return 0; 340280297Sjkim } 341280297Sjkim algtmp = pwri->keyEncryptionAlgorithm; 342238384Sjkim 343280297Sjkim if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) { 344280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 345280297Sjkim CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); 346280297Sjkim return 0; 347280297Sjkim } 348238384Sjkim 349280297Sjkim if (algtmp->parameter->type == V_ASN1_SEQUENCE) { 350280297Sjkim p = algtmp->parameter->value.sequence->data; 351280297Sjkim plen = algtmp->parameter->value.sequence->length; 352280297Sjkim kekalg = d2i_X509_ALGOR(NULL, &p, plen); 353280297Sjkim } 354280297Sjkim if (kekalg == NULL) { 355280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 356280297Sjkim CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); 357280297Sjkim return 0; 358280297Sjkim } 359238384Sjkim 360280297Sjkim kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); 361238384Sjkim 362280297Sjkim if (!kekcipher) { 363280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER); 364280297Sjkim goto err; 365280297Sjkim } 366238384Sjkim 367280297Sjkim /* Fixup cipher based on AlgorithmIdentifier to set IV etc */ 368280297Sjkim if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de)) 369280297Sjkim goto err; 370280297Sjkim EVP_CIPHER_CTX_set_padding(&kekctx, 0); 371280297Sjkim if (EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0) { 372280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 373280297Sjkim CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 374280297Sjkim goto err; 375280297Sjkim } 376238384Sjkim 377280297Sjkim algtmp = pwri->keyDerivationAlgorithm; 378238384Sjkim 379280297Sjkim /* Finish password based key derivation to setup key in "ctx" */ 380238384Sjkim 381280297Sjkim if (EVP_PBE_CipherInit(algtmp->algorithm, 382280297Sjkim (char *)pwri->pass, pwri->passlen, 383280297Sjkim algtmp->parameter, &kekctx, en_de) < 0) { 384280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB); 385280297Sjkim goto err; 386280297Sjkim } 387238384Sjkim 388280297Sjkim /* Finally wrap/unwrap the key */ 389238384Sjkim 390280297Sjkim if (en_de) { 391238384Sjkim 392280297Sjkim if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx)) 393280297Sjkim goto err; 394238384Sjkim 395280297Sjkim key = OPENSSL_malloc(keylen); 396238384Sjkim 397280297Sjkim if (!key) 398280297Sjkim goto err; 399238384Sjkim 400280297Sjkim if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx)) 401280297Sjkim goto err; 402280297Sjkim pwri->encryptedKey->data = key; 403280297Sjkim pwri->encryptedKey->length = keylen; 404280297Sjkim } else { 405280297Sjkim key = OPENSSL_malloc(pwri->encryptedKey->length); 406238384Sjkim 407280297Sjkim if (!key) { 408280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE); 409280297Sjkim goto err; 410280297Sjkim } 411280297Sjkim if (!kek_unwrap_key(key, &keylen, 412280297Sjkim pwri->encryptedKey->data, 413280297Sjkim pwri->encryptedKey->length, &kekctx)) { 414280297Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE); 415280297Sjkim goto err; 416280297Sjkim } 417238384Sjkim 418280297Sjkim ec->key = key; 419280297Sjkim ec->keylen = keylen; 420238384Sjkim 421280297Sjkim } 422238384Sjkim 423280297Sjkim r = 1; 424238384Sjkim 425280297Sjkim err: 426238384Sjkim 427280297Sjkim EVP_CIPHER_CTX_cleanup(&kekctx); 428238384Sjkim 429280297Sjkim if (!r && key) 430280297Sjkim OPENSSL_free(key); 431280297Sjkim X509_ALGOR_free(kekalg); 432238384Sjkim 433280297Sjkim return r; 434280297Sjkim 435280297Sjkim} 436