11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 111cb0ef41Sopenharmony_ci#include <openssl/asn1t.h> 121cb0ef41Sopenharmony_ci#include <openssl/pem.h> 131cb0ef41Sopenharmony_ci#include <openssl/x509v3.h> 141cb0ef41Sopenharmony_ci#include <openssl/err.h> 151cb0ef41Sopenharmony_ci#include <openssl/cms.h> 161cb0ef41Sopenharmony_ci#include <openssl/rand.h> 171cb0ef41Sopenharmony_ci#include "crypto/evp.h" 181cb0ef41Sopenharmony_ci#include "crypto/asn1.h" 191cb0ef41Sopenharmony_ci#include "cms_local.h" 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci/* CMS EncryptedData Utilities */ 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci/* Return BIO based on EncryptedContentInfo and key */ 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ciBIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec, 261cb0ef41Sopenharmony_ci const CMS_CTX *cms_ctx) 271cb0ef41Sopenharmony_ci{ 281cb0ef41Sopenharmony_ci BIO *b; 291cb0ef41Sopenharmony_ci EVP_CIPHER_CTX *ctx; 301cb0ef41Sopenharmony_ci EVP_CIPHER *fetched_ciph = NULL; 311cb0ef41Sopenharmony_ci const EVP_CIPHER *cipher = NULL; 321cb0ef41Sopenharmony_ci X509_ALGOR *calg = ec->contentEncryptionAlgorithm; 331cb0ef41Sopenharmony_ci evp_cipher_aead_asn1_params aparams; 341cb0ef41Sopenharmony_ci unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; 351cb0ef41Sopenharmony_ci unsigned char *tkey = NULL; 361cb0ef41Sopenharmony_ci int len; 371cb0ef41Sopenharmony_ci int ivlen = 0; 381cb0ef41Sopenharmony_ci size_t tkeylen = 0; 391cb0ef41Sopenharmony_ci int ok = 0; 401cb0ef41Sopenharmony_ci int enc, keep_key = 0; 411cb0ef41Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(cms_ctx); 421cb0ef41Sopenharmony_ci const char *propq = ossl_cms_ctx_get0_propq(cms_ctx); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci enc = ec->cipher ? 1 : 0; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci b = BIO_new(BIO_f_cipher()); 471cb0ef41Sopenharmony_ci if (b == NULL) { 481cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 491cb0ef41Sopenharmony_ci return NULL; 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci BIO_get_cipher_ctx(b, &ctx); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci (void)ERR_set_mark(); 551cb0ef41Sopenharmony_ci if (enc) { 561cb0ef41Sopenharmony_ci cipher = ec->cipher; 571cb0ef41Sopenharmony_ci /* 581cb0ef41Sopenharmony_ci * If not keeping key set cipher to NULL so subsequent calls decrypt. 591cb0ef41Sopenharmony_ci */ 601cb0ef41Sopenharmony_ci if (ec->key != NULL) 611cb0ef41Sopenharmony_ci ec->cipher = NULL; 621cb0ef41Sopenharmony_ci } else { 631cb0ef41Sopenharmony_ci cipher = EVP_get_cipherbyobj(calg->algorithm); 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci if (cipher != NULL) { 661cb0ef41Sopenharmony_ci fetched_ciph = EVP_CIPHER_fetch(libctx, EVP_CIPHER_get0_name(cipher), 671cb0ef41Sopenharmony_ci propq); 681cb0ef41Sopenharmony_ci if (fetched_ciph != NULL) 691cb0ef41Sopenharmony_ci cipher = fetched_ciph; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci if (cipher == NULL) { 721cb0ef41Sopenharmony_ci (void)ERR_clear_last_mark(); 731cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER); 741cb0ef41Sopenharmony_ci goto err; 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci (void)ERR_pop_to_mark(); 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc) <= 0) { 791cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR); 801cb0ef41Sopenharmony_ci goto err; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci if (enc) { 841cb0ef41Sopenharmony_ci calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx)); 851cb0ef41Sopenharmony_ci if (calg->algorithm == NULL || calg->algorithm->nid == NID_undef) { 861cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM); 871cb0ef41Sopenharmony_ci goto err; 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci /* Generate a random IV if we need one */ 901cb0ef41Sopenharmony_ci ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); 911cb0ef41Sopenharmony_ci if (ivlen < 0) { 921cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); 931cb0ef41Sopenharmony_ci goto err; 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci if (ivlen > 0) { 971cb0ef41Sopenharmony_ci if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0) 981cb0ef41Sopenharmony_ci goto err; 991cb0ef41Sopenharmony_ci piv = iv; 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci } else { 1021cb0ef41Sopenharmony_ci if (evp_cipher_asn1_to_param_ex(ctx, calg->parameter, &aparams) <= 0) { 1031cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 1041cb0ef41Sopenharmony_ci goto err; 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) { 1071cb0ef41Sopenharmony_ci piv = aparams.iv; 1081cb0ef41Sopenharmony_ci if (ec->taglen > 0 1091cb0ef41Sopenharmony_ci && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 1101cb0ef41Sopenharmony_ci ec->taglen, ec->tag) <= 0) { 1111cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_AEAD_SET_TAG_ERROR); 1121cb0ef41Sopenharmony_ci goto err; 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci len = EVP_CIPHER_CTX_get_key_length(ctx); 1171cb0ef41Sopenharmony_ci if (len <= 0) 1181cb0ef41Sopenharmony_ci goto err; 1191cb0ef41Sopenharmony_ci tkeylen = (size_t)len; 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci /* Generate random session key */ 1221cb0ef41Sopenharmony_ci if (!enc || !ec->key) { 1231cb0ef41Sopenharmony_ci tkey = OPENSSL_malloc(tkeylen); 1241cb0ef41Sopenharmony_ci if (tkey == NULL) { 1251cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 1261cb0ef41Sopenharmony_ci goto err; 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) 1291cb0ef41Sopenharmony_ci goto err; 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci if (!ec->key) { 1331cb0ef41Sopenharmony_ci ec->key = tkey; 1341cb0ef41Sopenharmony_ci ec->keylen = tkeylen; 1351cb0ef41Sopenharmony_ci tkey = NULL; 1361cb0ef41Sopenharmony_ci if (enc) 1371cb0ef41Sopenharmony_ci keep_key = 1; 1381cb0ef41Sopenharmony_ci else 1391cb0ef41Sopenharmony_ci ERR_clear_error(); 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci if (ec->keylen != tkeylen) { 1441cb0ef41Sopenharmony_ci /* If necessary set key length */ 1451cb0ef41Sopenharmony_ci if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { 1461cb0ef41Sopenharmony_ci /* 1471cb0ef41Sopenharmony_ci * Only reveal failure if debugging so we don't leak information 1481cb0ef41Sopenharmony_ci * which may be useful in MMA. 1491cb0ef41Sopenharmony_ci */ 1501cb0ef41Sopenharmony_ci if (enc || ec->debug) { 1511cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH); 1521cb0ef41Sopenharmony_ci goto err; 1531cb0ef41Sopenharmony_ci } else { 1541cb0ef41Sopenharmony_ci /* Use random key */ 1551cb0ef41Sopenharmony_ci OPENSSL_clear_free(ec->key, ec->keylen); 1561cb0ef41Sopenharmony_ci ec->key = tkey; 1571cb0ef41Sopenharmony_ci ec->keylen = tkeylen; 1581cb0ef41Sopenharmony_ci tkey = NULL; 1591cb0ef41Sopenharmony_ci ERR_clear_error(); 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) { 1651cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR); 1661cb0ef41Sopenharmony_ci goto err; 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci if (enc) { 1691cb0ef41Sopenharmony_ci calg->parameter = ASN1_TYPE_new(); 1701cb0ef41Sopenharmony_ci if (calg->parameter == NULL) { 1711cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 1721cb0ef41Sopenharmony_ci goto err; 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) { 1751cb0ef41Sopenharmony_ci memcpy(aparams.iv, piv, ivlen); 1761cb0ef41Sopenharmony_ci aparams.iv_len = ivlen; 1771cb0ef41Sopenharmony_ci aparams.tag_len = EVP_CIPHER_CTX_get_tag_length(ctx); 1781cb0ef41Sopenharmony_ci if (aparams.tag_len <= 0) 1791cb0ef41Sopenharmony_ci goto err; 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci if (evp_cipher_param_to_asn1_ex(ctx, calg->parameter, &aparams) <= 0) { 1831cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 1841cb0ef41Sopenharmony_ci goto err; 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci /* If parameter type not set omit parameter */ 1871cb0ef41Sopenharmony_ci if (calg->parameter->type == V_ASN1_UNDEF) { 1881cb0ef41Sopenharmony_ci ASN1_TYPE_free(calg->parameter); 1891cb0ef41Sopenharmony_ci calg->parameter = NULL; 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci ok = 1; 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci err: 1951cb0ef41Sopenharmony_ci EVP_CIPHER_free(fetched_ciph); 1961cb0ef41Sopenharmony_ci if (!keep_key || !ok) { 1971cb0ef41Sopenharmony_ci OPENSSL_clear_free(ec->key, ec->keylen); 1981cb0ef41Sopenharmony_ci ec->key = NULL; 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci OPENSSL_clear_free(tkey, tkeylen); 2011cb0ef41Sopenharmony_ci if (ok) 2021cb0ef41Sopenharmony_ci return b; 2031cb0ef41Sopenharmony_ci BIO_free(b); 2041cb0ef41Sopenharmony_ci return NULL; 2051cb0ef41Sopenharmony_ci} 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ciint ossl_cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 2081cb0ef41Sopenharmony_ci const EVP_CIPHER *cipher, 2091cb0ef41Sopenharmony_ci const unsigned char *key, size_t keylen, 2101cb0ef41Sopenharmony_ci const CMS_CTX *cms_ctx) 2111cb0ef41Sopenharmony_ci{ 2121cb0ef41Sopenharmony_ci ec->cipher = cipher; 2131cb0ef41Sopenharmony_ci if (key) { 2141cb0ef41Sopenharmony_ci if ((ec->key = OPENSSL_malloc(keylen)) == NULL) { 2151cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 2161cb0ef41Sopenharmony_ci return 0; 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci memcpy(ec->key, key, keylen); 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci ec->keylen = keylen; 2211cb0ef41Sopenharmony_ci if (cipher != NULL) 2221cb0ef41Sopenharmony_ci ec->contentType = OBJ_nid2obj(NID_pkcs7_data); 2231cb0ef41Sopenharmony_ci return 1; 2241cb0ef41Sopenharmony_ci} 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ciint CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, 2271cb0ef41Sopenharmony_ci const unsigned char *key, size_t keylen) 2281cb0ef41Sopenharmony_ci{ 2291cb0ef41Sopenharmony_ci CMS_EncryptedContentInfo *ec; 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci if (!key || !keylen) { 2321cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY); 2331cb0ef41Sopenharmony_ci return 0; 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci if (ciph) { 2361cb0ef41Sopenharmony_ci cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData); 2371cb0ef41Sopenharmony_ci if (!cms->d.encryptedData) { 2381cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); 2391cb0ef41Sopenharmony_ci return 0; 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted); 2421cb0ef41Sopenharmony_ci cms->d.encryptedData->version = 0; 2431cb0ef41Sopenharmony_ci } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) { 2441cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_ENCRYPTED_DATA); 2451cb0ef41Sopenharmony_ci return 0; 2461cb0ef41Sopenharmony_ci } 2471cb0ef41Sopenharmony_ci ec = cms->d.encryptedData->encryptedContentInfo; 2481cb0ef41Sopenharmony_ci return ossl_cms_EncryptedContent_init(ec, ciph, key, keylen, 2491cb0ef41Sopenharmony_ci ossl_cms_get0_cmsctx(cms)); 2501cb0ef41Sopenharmony_ci} 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ciBIO *ossl_cms_EncryptedData_init_bio(const CMS_ContentInfo *cms) 2531cb0ef41Sopenharmony_ci{ 2541cb0ef41Sopenharmony_ci CMS_EncryptedData *enc = cms->d.encryptedData; 2551cb0ef41Sopenharmony_ci if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs) 2561cb0ef41Sopenharmony_ci enc->version = 2; 2571cb0ef41Sopenharmony_ci return ossl_cms_EncryptedContent_init_bio(enc->encryptedContentInfo, 2581cb0ef41Sopenharmony_ci ossl_cms_get0_cmsctx(cms)); 2591cb0ef41Sopenharmony_ci} 260