1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 11e1051a39Sopenharmony_ci#include <openssl/asn1t.h> 12e1051a39Sopenharmony_ci#include <openssl/pem.h> 13e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 14e1051a39Sopenharmony_ci#include <openssl/err.h> 15e1051a39Sopenharmony_ci#include <openssl/cms.h> 16e1051a39Sopenharmony_ci#include <openssl/rand.h> 17e1051a39Sopenharmony_ci#include <openssl/aes.h> 18e1051a39Sopenharmony_ci#include "internal/sizes.h" 19e1051a39Sopenharmony_ci#include "crypto/asn1.h" 20e1051a39Sopenharmony_ci#include "cms_local.h" 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ciint CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, 23e1051a39Sopenharmony_ci unsigned char *pass, ossl_ssize_t passlen) 24e1051a39Sopenharmony_ci{ 25e1051a39Sopenharmony_ci CMS_PasswordRecipientInfo *pwri; 26e1051a39Sopenharmony_ci if (ri->type != CMS_RECIPINFO_PASS) { 27e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_PWRI); 28e1051a39Sopenharmony_ci return 0; 29e1051a39Sopenharmony_ci } 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ci pwri = ri->d.pwri; 32e1051a39Sopenharmony_ci pwri->pass = pass; 33e1051a39Sopenharmony_ci if (pass && passlen < 0) 34e1051a39Sopenharmony_ci passlen = strlen((char *)pass); 35e1051a39Sopenharmony_ci pwri->passlen = passlen; 36e1051a39Sopenharmony_ci return 1; 37e1051a39Sopenharmony_ci} 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ciCMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, 40e1051a39Sopenharmony_ci int iter, int wrap_nid, 41e1051a39Sopenharmony_ci int pbe_nid, 42e1051a39Sopenharmony_ci unsigned char *pass, 43e1051a39Sopenharmony_ci ossl_ssize_t passlen, 44e1051a39Sopenharmony_ci const EVP_CIPHER *kekciph) 45e1051a39Sopenharmony_ci{ 46e1051a39Sopenharmony_ci STACK_OF(CMS_RecipientInfo) *ris; 47e1051a39Sopenharmony_ci CMS_RecipientInfo *ri = NULL; 48e1051a39Sopenharmony_ci CMS_EncryptedContentInfo *ec; 49e1051a39Sopenharmony_ci CMS_PasswordRecipientInfo *pwri; 50e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx = NULL; 51e1051a39Sopenharmony_ci X509_ALGOR *encalg = NULL; 52e1051a39Sopenharmony_ci unsigned char iv[EVP_MAX_IV_LENGTH]; 53e1051a39Sopenharmony_ci int ivlen; 54e1051a39Sopenharmony_ci const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms); 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci ec = ossl_cms_get0_env_enc_content(cms); 57e1051a39Sopenharmony_ci if (ec == NULL) 58e1051a39Sopenharmony_ci return NULL; 59e1051a39Sopenharmony_ci ris = CMS_get0_RecipientInfos(cms); 60e1051a39Sopenharmony_ci if (ris == NULL) 61e1051a39Sopenharmony_ci return NULL; 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ci if (wrap_nid <= 0) 64e1051a39Sopenharmony_ci wrap_nid = NID_id_alg_PWRI_KEK; 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ci if (pbe_nid <= 0) 67e1051a39Sopenharmony_ci pbe_nid = NID_id_pbkdf2; 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ci /* Get from enveloped data */ 70e1051a39Sopenharmony_ci if (kekciph == NULL) 71e1051a39Sopenharmony_ci kekciph = ec->cipher; 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci if (kekciph == NULL) { 74e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER); 75e1051a39Sopenharmony_ci return NULL; 76e1051a39Sopenharmony_ci } 77e1051a39Sopenharmony_ci if (wrap_nid != NID_id_alg_PWRI_KEK) { 78e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); 79e1051a39Sopenharmony_ci return NULL; 80e1051a39Sopenharmony_ci } 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci /* Setup algorithm identifier for cipher */ 83e1051a39Sopenharmony_ci encalg = X509_ALGOR_new(); 84e1051a39Sopenharmony_ci if (encalg == NULL) { 85e1051a39Sopenharmony_ci goto merr; 86e1051a39Sopenharmony_ci } 87e1051a39Sopenharmony_ci ctx = EVP_CIPHER_CTX_new(); 88e1051a39Sopenharmony_ci if (ctx == NULL) { 89e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 90e1051a39Sopenharmony_ci goto err; 91e1051a39Sopenharmony_ci } 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) { 94e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); 95e1051a39Sopenharmony_ci goto err; 96e1051a39Sopenharmony_ci } 97e1051a39Sopenharmony_ci 98e1051a39Sopenharmony_ci ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); 99e1051a39Sopenharmony_ci if (ivlen < 0) { 100e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); 101e1051a39Sopenharmony_ci goto err; 102e1051a39Sopenharmony_ci } 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci if (ivlen > 0) { 105e1051a39Sopenharmony_ci if (RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx), iv, ivlen, 0) <= 0) 106e1051a39Sopenharmony_ci goto err; 107e1051a39Sopenharmony_ci if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) { 108e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); 109e1051a39Sopenharmony_ci goto err; 110e1051a39Sopenharmony_ci } 111e1051a39Sopenharmony_ci encalg->parameter = ASN1_TYPE_new(); 112e1051a39Sopenharmony_ci if (!encalg->parameter) { 113e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 114e1051a39Sopenharmony_ci goto err; 115e1051a39Sopenharmony_ci } 116e1051a39Sopenharmony_ci if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) { 117e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 118e1051a39Sopenharmony_ci goto err; 119e1051a39Sopenharmony_ci } 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx)); 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(ctx); 125e1051a39Sopenharmony_ci ctx = NULL; 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ci /* Initialize recipient info */ 128e1051a39Sopenharmony_ci ri = M_ASN1_new_of(CMS_RecipientInfo); 129e1051a39Sopenharmony_ci if (ri == NULL) 130e1051a39Sopenharmony_ci goto merr; 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_ci ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); 133e1051a39Sopenharmony_ci if (ri->d.pwri == NULL) 134e1051a39Sopenharmony_ci goto merr; 135e1051a39Sopenharmony_ci ri->type = CMS_RECIPINFO_PASS; 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci pwri = ri->d.pwri; 138e1051a39Sopenharmony_ci pwri->cms_ctx = cms_ctx; 139e1051a39Sopenharmony_ci /* Since this is overwritten, free up empty structure already there */ 140e1051a39Sopenharmony_ci X509_ALGOR_free(pwri->keyEncryptionAlgorithm); 141e1051a39Sopenharmony_ci pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); 142e1051a39Sopenharmony_ci if (pwri->keyEncryptionAlgorithm == NULL) 143e1051a39Sopenharmony_ci goto merr; 144e1051a39Sopenharmony_ci pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); 145e1051a39Sopenharmony_ci pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); 146e1051a39Sopenharmony_ci if (pwri->keyEncryptionAlgorithm->parameter == NULL) 147e1051a39Sopenharmony_ci goto merr; 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), 150e1051a39Sopenharmony_ci &pwri->keyEncryptionAlgorithm->parameter-> 151e1051a39Sopenharmony_ci value.sequence)) 152e1051a39Sopenharmony_ci goto merr; 153e1051a39Sopenharmony_ci pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci X509_ALGOR_free(encalg); 156e1051a39Sopenharmony_ci encalg = NULL; 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci /* Setup PBE algorithm */ 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci if (pwri->keyDerivationAlgorithm == NULL) 163e1051a39Sopenharmony_ci goto err; 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci CMS_RecipientInfo_set0_password(ri, pass, passlen); 166e1051a39Sopenharmony_ci pwri->version = 0; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci if (!sk_CMS_RecipientInfo_push(ris, ri)) 169e1051a39Sopenharmony_ci goto merr; 170e1051a39Sopenharmony_ci 171e1051a39Sopenharmony_ci return ri; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci merr: 174e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 175e1051a39Sopenharmony_ci err: 176e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(ctx); 177e1051a39Sopenharmony_ci if (ri) 178e1051a39Sopenharmony_ci M_ASN1_free_of(ri, CMS_RecipientInfo); 179e1051a39Sopenharmony_ci X509_ALGOR_free(encalg); 180e1051a39Sopenharmony_ci return NULL; 181e1051a39Sopenharmony_ci 182e1051a39Sopenharmony_ci} 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ci/* 185e1051a39Sopenharmony_ci * This is an implementation of the key wrapping mechanism in RFC3211, at 186e1051a39Sopenharmony_ci * some point this should go into EVP. 187e1051a39Sopenharmony_ci */ 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_cistatic int kek_unwrap_key(unsigned char *out, size_t *outlen, 190e1051a39Sopenharmony_ci const unsigned char *in, size_t inlen, 191e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx) 192e1051a39Sopenharmony_ci{ 193e1051a39Sopenharmony_ci size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx); 194e1051a39Sopenharmony_ci unsigned char *tmp; 195e1051a39Sopenharmony_ci int outl, rv = 0; 196e1051a39Sopenharmony_ci if (inlen < 2 * blocklen) { 197e1051a39Sopenharmony_ci /* too small */ 198e1051a39Sopenharmony_ci return 0; 199e1051a39Sopenharmony_ci } 200e1051a39Sopenharmony_ci if (inlen % blocklen) { 201e1051a39Sopenharmony_ci /* Invalid size */ 202e1051a39Sopenharmony_ci return 0; 203e1051a39Sopenharmony_ci } 204e1051a39Sopenharmony_ci if ((tmp = OPENSSL_malloc(inlen)) == NULL) { 205e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 206e1051a39Sopenharmony_ci return 0; 207e1051a39Sopenharmony_ci } 208e1051a39Sopenharmony_ci /* setup IV by decrypting last two blocks */ 209e1051a39Sopenharmony_ci if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, 210e1051a39Sopenharmony_ci in + inlen - 2 * blocklen, blocklen * 2) 211e1051a39Sopenharmony_ci /* 212e1051a39Sopenharmony_ci * Do a decrypt of last decrypted block to set IV to correct value 213e1051a39Sopenharmony_ci * output it to start of buffer so we don't corrupt decrypted block 214e1051a39Sopenharmony_ci * this works because buffer is at least two block lengths long. 215e1051a39Sopenharmony_ci */ 216e1051a39Sopenharmony_ci || !EVP_DecryptUpdate(ctx, tmp, &outl, 217e1051a39Sopenharmony_ci tmp + inlen - blocklen, blocklen) 218e1051a39Sopenharmony_ci /* Can now decrypt first n - 1 blocks */ 219e1051a39Sopenharmony_ci || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen) 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci /* Reset IV to original value */ 222e1051a39Sopenharmony_ci || !EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL) 223e1051a39Sopenharmony_ci /* Decrypt again */ 224e1051a39Sopenharmony_ci || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen)) 225e1051a39Sopenharmony_ci goto err; 226e1051a39Sopenharmony_ci /* Check check bytes */ 227e1051a39Sopenharmony_ci if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) { 228e1051a39Sopenharmony_ci /* Check byte failure */ 229e1051a39Sopenharmony_ci goto err; 230e1051a39Sopenharmony_ci } 231e1051a39Sopenharmony_ci if (inlen < (size_t)(tmp[0] - 4)) { 232e1051a39Sopenharmony_ci /* Invalid length value */ 233e1051a39Sopenharmony_ci goto err; 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci *outlen = (size_t)tmp[0]; 236e1051a39Sopenharmony_ci memcpy(out, tmp + 4, *outlen); 237e1051a39Sopenharmony_ci rv = 1; 238e1051a39Sopenharmony_ci err: 239e1051a39Sopenharmony_ci OPENSSL_clear_free(tmp, inlen); 240e1051a39Sopenharmony_ci return rv; 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci} 243e1051a39Sopenharmony_ci 244e1051a39Sopenharmony_cistatic int kek_wrap_key(unsigned char *out, size_t *outlen, 245e1051a39Sopenharmony_ci const unsigned char *in, size_t inlen, 246e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx, const CMS_CTX *cms_ctx) 247e1051a39Sopenharmony_ci{ 248e1051a39Sopenharmony_ci size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx); 249e1051a39Sopenharmony_ci size_t olen; 250e1051a39Sopenharmony_ci int dummy; 251e1051a39Sopenharmony_ci /* 252e1051a39Sopenharmony_ci * First decide length of output buffer: need header and round up to 253e1051a39Sopenharmony_ci * multiple of block length. 254e1051a39Sopenharmony_ci */ 255e1051a39Sopenharmony_ci olen = (inlen + 4 + blocklen - 1) / blocklen; 256e1051a39Sopenharmony_ci olen *= blocklen; 257e1051a39Sopenharmony_ci if (olen < 2 * blocklen) { 258e1051a39Sopenharmony_ci /* Key too small */ 259e1051a39Sopenharmony_ci return 0; 260e1051a39Sopenharmony_ci } 261e1051a39Sopenharmony_ci if (inlen > 0xFF) { 262e1051a39Sopenharmony_ci /* Key too large */ 263e1051a39Sopenharmony_ci return 0; 264e1051a39Sopenharmony_ci } 265e1051a39Sopenharmony_ci if (out) { 266e1051a39Sopenharmony_ci /* Set header */ 267e1051a39Sopenharmony_ci out[0] = (unsigned char)inlen; 268e1051a39Sopenharmony_ci out[1] = in[0] ^ 0xFF; 269e1051a39Sopenharmony_ci out[2] = in[1] ^ 0xFF; 270e1051a39Sopenharmony_ci out[3] = in[2] ^ 0xFF; 271e1051a39Sopenharmony_ci memcpy(out + 4, in, inlen); 272e1051a39Sopenharmony_ci /* Add random padding to end */ 273e1051a39Sopenharmony_ci if (olen > inlen + 4 274e1051a39Sopenharmony_ci && RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx), out + 4 + inlen, 275e1051a39Sopenharmony_ci olen - 4 - inlen, 0) <= 0) 276e1051a39Sopenharmony_ci return 0; 277e1051a39Sopenharmony_ci /* Encrypt twice */ 278e1051a39Sopenharmony_ci if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen) 279e1051a39Sopenharmony_ci || !EVP_EncryptUpdate(ctx, out, &dummy, out, olen)) 280e1051a39Sopenharmony_ci return 0; 281e1051a39Sopenharmony_ci } 282e1051a39Sopenharmony_ci 283e1051a39Sopenharmony_ci *outlen = olen; 284e1051a39Sopenharmony_ci 285e1051a39Sopenharmony_ci return 1; 286e1051a39Sopenharmony_ci} 287e1051a39Sopenharmony_ci 288e1051a39Sopenharmony_ci/* Encrypt/Decrypt content key in PWRI recipient info */ 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ciint ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, 291e1051a39Sopenharmony_ci CMS_RecipientInfo *ri, int en_de) 292e1051a39Sopenharmony_ci{ 293e1051a39Sopenharmony_ci CMS_EncryptedContentInfo *ec; 294e1051a39Sopenharmony_ci CMS_PasswordRecipientInfo *pwri; 295e1051a39Sopenharmony_ci int r = 0; 296e1051a39Sopenharmony_ci X509_ALGOR *algtmp, *kekalg = NULL; 297e1051a39Sopenharmony_ci EVP_CIPHER_CTX *kekctx = NULL; 298e1051a39Sopenharmony_ci char name[OSSL_MAX_NAME_SIZE]; 299e1051a39Sopenharmony_ci EVP_CIPHER *kekcipher; 300e1051a39Sopenharmony_ci unsigned char *key = NULL; 301e1051a39Sopenharmony_ci size_t keylen; 302e1051a39Sopenharmony_ci const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms); 303e1051a39Sopenharmony_ci 304e1051a39Sopenharmony_ci ec = ossl_cms_get0_env_enc_content(cms); 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_ci pwri = ri->d.pwri; 307e1051a39Sopenharmony_ci 308e1051a39Sopenharmony_ci if (pwri->pass == NULL) { 309e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NO_PASSWORD); 310e1051a39Sopenharmony_ci return 0; 311e1051a39Sopenharmony_ci } 312e1051a39Sopenharmony_ci algtmp = pwri->keyEncryptionAlgorithm; 313e1051a39Sopenharmony_ci 314e1051a39Sopenharmony_ci if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) { 315e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); 316e1051a39Sopenharmony_ci return 0; 317e1051a39Sopenharmony_ci } 318e1051a39Sopenharmony_ci 319e1051a39Sopenharmony_ci kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR), 320e1051a39Sopenharmony_ci algtmp->parameter); 321e1051a39Sopenharmony_ci 322e1051a39Sopenharmony_ci if (kekalg == NULL) { 323e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); 324e1051a39Sopenharmony_ci return 0; 325e1051a39Sopenharmony_ci } 326e1051a39Sopenharmony_ci 327e1051a39Sopenharmony_ci OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0); 328e1051a39Sopenharmony_ci kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx), name, 329e1051a39Sopenharmony_ci ossl_cms_ctx_get0_propq(cms_ctx)); 330e1051a39Sopenharmony_ci 331e1051a39Sopenharmony_ci if (kekcipher == NULL) { 332e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER); 333e1051a39Sopenharmony_ci goto err; 334e1051a39Sopenharmony_ci } 335e1051a39Sopenharmony_ci 336e1051a39Sopenharmony_ci kekctx = EVP_CIPHER_CTX_new(); 337e1051a39Sopenharmony_ci if (kekctx == NULL) { 338e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 339e1051a39Sopenharmony_ci goto err; 340e1051a39Sopenharmony_ci } 341e1051a39Sopenharmony_ci /* Fixup cipher based on AlgorithmIdentifier to set IV etc */ 342e1051a39Sopenharmony_ci if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de)) 343e1051a39Sopenharmony_ci goto err; 344e1051a39Sopenharmony_ci EVP_CIPHER_CTX_set_padding(kekctx, 0); 345e1051a39Sopenharmony_ci if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) { 346e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 347e1051a39Sopenharmony_ci goto err; 348e1051a39Sopenharmony_ci } 349e1051a39Sopenharmony_ci 350e1051a39Sopenharmony_ci algtmp = pwri->keyDerivationAlgorithm; 351e1051a39Sopenharmony_ci 352e1051a39Sopenharmony_ci /* Finish password based key derivation to setup key in "ctx" */ 353e1051a39Sopenharmony_ci 354e1051a39Sopenharmony_ci if (EVP_PBE_CipherInit(algtmp->algorithm, 355e1051a39Sopenharmony_ci (char *)pwri->pass, pwri->passlen, 356e1051a39Sopenharmony_ci algtmp->parameter, kekctx, en_de) < 0) { 357e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); 358e1051a39Sopenharmony_ci goto err; 359e1051a39Sopenharmony_ci } 360e1051a39Sopenharmony_ci 361e1051a39Sopenharmony_ci /* Finally wrap/unwrap the key */ 362e1051a39Sopenharmony_ci 363e1051a39Sopenharmony_ci if (en_de) { 364e1051a39Sopenharmony_ci 365e1051a39Sopenharmony_ci if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx, cms_ctx)) 366e1051a39Sopenharmony_ci goto err; 367e1051a39Sopenharmony_ci 368e1051a39Sopenharmony_ci key = OPENSSL_malloc(keylen); 369e1051a39Sopenharmony_ci 370e1051a39Sopenharmony_ci if (key == NULL) 371e1051a39Sopenharmony_ci goto err; 372e1051a39Sopenharmony_ci 373e1051a39Sopenharmony_ci if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx)) 374e1051a39Sopenharmony_ci goto err; 375e1051a39Sopenharmony_ci pwri->encryptedKey->data = key; 376e1051a39Sopenharmony_ci pwri->encryptedKey->length = keylen; 377e1051a39Sopenharmony_ci } else { 378e1051a39Sopenharmony_ci key = OPENSSL_malloc(pwri->encryptedKey->length); 379e1051a39Sopenharmony_ci 380e1051a39Sopenharmony_ci if (key == NULL) { 381e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 382e1051a39Sopenharmony_ci goto err; 383e1051a39Sopenharmony_ci } 384e1051a39Sopenharmony_ci if (!kek_unwrap_key(key, &keylen, 385e1051a39Sopenharmony_ci pwri->encryptedKey->data, 386e1051a39Sopenharmony_ci pwri->encryptedKey->length, kekctx)) { 387e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNWRAP_FAILURE); 388e1051a39Sopenharmony_ci goto err; 389e1051a39Sopenharmony_ci } 390e1051a39Sopenharmony_ci 391e1051a39Sopenharmony_ci OPENSSL_clear_free(ec->key, ec->keylen); 392e1051a39Sopenharmony_ci ec->key = key; 393e1051a39Sopenharmony_ci ec->keylen = keylen; 394e1051a39Sopenharmony_ci 395e1051a39Sopenharmony_ci } 396e1051a39Sopenharmony_ci 397e1051a39Sopenharmony_ci r = 1; 398e1051a39Sopenharmony_ci 399e1051a39Sopenharmony_ci err: 400e1051a39Sopenharmony_ci EVP_CIPHER_free(kekcipher); 401e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(kekctx); 402e1051a39Sopenharmony_ci 403e1051a39Sopenharmony_ci if (!r) 404e1051a39Sopenharmony_ci OPENSSL_free(key); 405e1051a39Sopenharmony_ci X509_ALGOR_free(kekalg); 406e1051a39Sopenharmony_ci 407e1051a39Sopenharmony_ci return r; 408e1051a39Sopenharmony_ci 409e1051a39Sopenharmony_ci} 410