1/* 2 * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include "internal/cryptlib.h" 11#include <openssl/asn1t.h> 12#include <openssl/pem.h> 13#include <openssl/x509v3.h> 14#include <openssl/err.h> 15#include <openssl/cms.h> 16#include <openssl/rand.h> 17#include "crypto/evp.h" 18#include "crypto/asn1.h" 19#include "cms_local.h" 20 21/* CMS EncryptedData Utilities */ 22 23/* Return BIO based on EncryptedContentInfo and key */ 24 25BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec, 26 const CMS_CTX *cms_ctx) 27{ 28 BIO *b; 29 EVP_CIPHER_CTX *ctx; 30 EVP_CIPHER *fetched_ciph = NULL; 31 const EVP_CIPHER *cipher = NULL; 32 X509_ALGOR *calg = ec->contentEncryptionAlgorithm; 33 evp_cipher_aead_asn1_params aparams; 34 unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; 35 unsigned char *tkey = NULL; 36 int len; 37 int ivlen = 0; 38 size_t tkeylen = 0; 39 int ok = 0; 40 int enc, keep_key = 0; 41 OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(cms_ctx); 42 const char *propq = ossl_cms_ctx_get0_propq(cms_ctx); 43 44 enc = ec->cipher ? 1 : 0; 45 46 b = BIO_new(BIO_f_cipher()); 47 if (b == NULL) { 48 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 49 return NULL; 50 } 51 52 BIO_get_cipher_ctx(b, &ctx); 53 54 (void)ERR_set_mark(); 55 if (enc) { 56 cipher = ec->cipher; 57 /* 58 * If not keeping key set cipher to NULL so subsequent calls decrypt. 59 */ 60 if (ec->key != NULL) 61 ec->cipher = NULL; 62 } else { 63 cipher = EVP_get_cipherbyobj(calg->algorithm); 64 } 65 if (cipher != NULL) { 66 fetched_ciph = EVP_CIPHER_fetch(libctx, EVP_CIPHER_get0_name(cipher), 67 propq); 68 if (fetched_ciph != NULL) 69 cipher = fetched_ciph; 70 } 71 if (cipher == NULL) { 72 (void)ERR_clear_last_mark(); 73 ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER); 74 goto err; 75 } 76 (void)ERR_pop_to_mark(); 77 78 if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc) <= 0) { 79 ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR); 80 goto err; 81 } 82 83 if (enc) { 84 calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx)); 85 if (calg->algorithm == NULL || calg->algorithm->nid == NID_undef) { 86 ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM); 87 goto err; 88 } 89 /* Generate a random IV if we need one */ 90 ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); 91 if (ivlen < 0) { 92 ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); 93 goto err; 94 } 95 96 if (ivlen > 0) { 97 if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0) 98 goto err; 99 piv = iv; 100 } 101 } else { 102 if (evp_cipher_asn1_to_param_ex(ctx, calg->parameter, &aparams) <= 0) { 103 ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 104 goto err; 105 } 106 if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) { 107 piv = aparams.iv; 108 if (ec->taglen > 0 109 && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 110 ec->taglen, ec->tag) <= 0) { 111 ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_AEAD_SET_TAG_ERROR); 112 goto err; 113 } 114 } 115 } 116 len = EVP_CIPHER_CTX_get_key_length(ctx); 117 if (len <= 0) 118 goto err; 119 tkeylen = (size_t)len; 120 121 /* Generate random session key */ 122 if (!enc || !ec->key) { 123 tkey = OPENSSL_malloc(tkeylen); 124 if (tkey == NULL) { 125 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 126 goto err; 127 } 128 if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) 129 goto err; 130 } 131 132 if (!ec->key) { 133 ec->key = tkey; 134 ec->keylen = tkeylen; 135 tkey = NULL; 136 if (enc) 137 keep_key = 1; 138 else 139 ERR_clear_error(); 140 141 } 142 143 if (ec->keylen != tkeylen) { 144 /* If necessary set key length */ 145 if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { 146 /* 147 * Only reveal failure if debugging so we don't leak information 148 * which may be useful in MMA. 149 */ 150 if (enc || ec->debug) { 151 ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH); 152 goto err; 153 } else { 154 /* Use random key */ 155 OPENSSL_clear_free(ec->key, ec->keylen); 156 ec->key = tkey; 157 ec->keylen = tkeylen; 158 tkey = NULL; 159 ERR_clear_error(); 160 } 161 } 162 } 163 164 if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) { 165 ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR); 166 goto err; 167 } 168 if (enc) { 169 calg->parameter = ASN1_TYPE_new(); 170 if (calg->parameter == NULL) { 171 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 172 goto err; 173 } 174 if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) { 175 memcpy(aparams.iv, piv, ivlen); 176 aparams.iv_len = ivlen; 177 aparams.tag_len = EVP_CIPHER_CTX_get_tag_length(ctx); 178 if (aparams.tag_len <= 0) 179 goto err; 180 } 181 182 if (evp_cipher_param_to_asn1_ex(ctx, calg->parameter, &aparams) <= 0) { 183 ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 184 goto err; 185 } 186 /* If parameter type not set omit parameter */ 187 if (calg->parameter->type == V_ASN1_UNDEF) { 188 ASN1_TYPE_free(calg->parameter); 189 calg->parameter = NULL; 190 } 191 } 192 ok = 1; 193 194 err: 195 EVP_CIPHER_free(fetched_ciph); 196 if (!keep_key || !ok) { 197 OPENSSL_clear_free(ec->key, ec->keylen); 198 ec->key = NULL; 199 } 200 OPENSSL_clear_free(tkey, tkeylen); 201 if (ok) 202 return b; 203 BIO_free(b); 204 return NULL; 205} 206 207int ossl_cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 208 const EVP_CIPHER *cipher, 209 const unsigned char *key, size_t keylen, 210 const CMS_CTX *cms_ctx) 211{ 212 ec->cipher = cipher; 213 if (key) { 214 if ((ec->key = OPENSSL_malloc(keylen)) == NULL) { 215 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 216 return 0; 217 } 218 memcpy(ec->key, key, keylen); 219 } 220 ec->keylen = keylen; 221 if (cipher != NULL) 222 ec->contentType = OBJ_nid2obj(NID_pkcs7_data); 223 return 1; 224} 225 226int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, 227 const unsigned char *key, size_t keylen) 228{ 229 CMS_EncryptedContentInfo *ec; 230 231 if (!key || !keylen) { 232 ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY); 233 return 0; 234 } 235 if (ciph) { 236 cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData); 237 if (!cms->d.encryptedData) { 238 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 239 return 0; 240 } 241 cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted); 242 cms->d.encryptedData->version = 0; 243 } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) { 244 ERR_raise(ERR_LIB_CMS, CMS_R_NOT_ENCRYPTED_DATA); 245 return 0; 246 } 247 ec = cms->d.encryptedData->encryptedContentInfo; 248 return ossl_cms_EncryptedContent_init(ec, ciph, key, keylen, 249 ossl_cms_get0_cmsctx(cms)); 250} 251 252BIO *ossl_cms_EncryptedData_init_bio(const CMS_ContentInfo *cms) 253{ 254 CMS_EncryptedData *enc = cms->d.encryptedData; 255 if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs) 256 enc->version = 2; 257 return ossl_cms_EncryptedContent_init_bio(enc->encryptedContentInfo, 258 ossl_cms_get0_cmsctx(cms)); 259} 260