From 2a114f31d60979922e3fe852b0d03f844b6fdf48 Mon Sep 17 00:00:00 2001 From: Khushi Date: Tue, 24 Dec 2024 04:00:48 +0000 Subject: [PATCH] Bug Fix: Intermittent failure in NvVseTestAES Fixed the issue caused by using common buffer in hwrng requests which led to overwriting the buffer and mismatch during concurrent AES operations Bug Id: Bug 5015880 Change-Id: I52d6ae016fcc58cd9f2129d13d458d2ff9b3da59 Signed-off-by: Khushi Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3273901 Reviewed-by: Suresh Venkatachalam GVS: buildbot_gerritrpt Reviewed-by: Leo Chiu Tested-by: mobile promotions Reviewed-by: mobile promotions Reviewed-by: Nagaraj P N Tested-by: Christoffer Arvidsson Reviewed-by: svcacv --- drivers/crypto/tegra-hv-vse-safety.c | 44 +++++++++++++++++++++------- drivers/crypto/tegra-hv-vse.h | 1 + 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/tegra-hv-vse-safety.c b/drivers/crypto/tegra-hv-vse-safety.c index 6c2a9487..c5fab98c 100644 --- a/drivers/crypto/tegra-hv-vse-safety.c +++ b/drivers/crypto/tegra-hv-vse-safety.c @@ -343,6 +343,11 @@ enum tegra_virtual_se_command { VIRTUAL_SE_AES_GCM_ENC_PROCESS }; +enum rng_call { + HW_RNG = 0x5A5A5A5A, + CRYPTODEV_RNG = 0xABABABAB +}; + /* CMAC response */ struct tegra_vse_cmac_data { u8 status; @@ -3035,7 +3040,7 @@ static void tegra_hv_vse_safety_rng_drbg_exit(struct crypto_tfm *tfm) } static int tegra_hv_vse_safety_get_random(struct tegra_virtual_se_rng_context *rng_ctx, - u8 *rdata, unsigned int dlen) + u8 *rdata, unsigned int dlen, enum rng_call is_hw_req) { struct tegra_virtual_se_dev *se_dev = g_virtual_se_dev[g_crypto_to_ivc_map[rng_ctx->node_id].engine_id]; @@ -3074,12 +3079,15 @@ static int tegra_hv_vse_safety_get_random(struct tegra_virtual_se_rng_context *r return 0; } - src = tegra_hv_vse_get_dma_buf(rng_ctx->node_id, AES_SRC_BUF_IDX, + if (is_hw_req == CRYPTODEV_RNG) { + src = tegra_hv_vse_get_dma_buf(rng_ctx->node_id, AES_SRC_BUF_IDX, TEGRA_VIRTUAL_SE_RNG_DT_SIZE); - if (!src) { - pr_err("%s rng src buf is NULL\n", __func__); - return -ENOMEM; - } + if (!src) { + pr_err("%s src is NULL\n", __func__); + return -ENOMEM; + } + } else + src = &rng_ctx->hwrng_dma_buf; ivc_tx = &ivc_req_msg->tx[0]; ivc_hdr = &ivc_req_msg->ivc_hdr; @@ -3115,8 +3123,7 @@ static int tegra_hv_vse_safety_get_random(struct tegra_virtual_se_rng_context *r if (data_len && num_blocks == j) { memcpy(rdata_addr, src->buf_ptr, data_len); } else { - memcpy(rdata_addr, - src->buf_ptr, + memcpy(rdata_addr, src->buf_ptr, TEGRA_VIRTUAL_SE_RNG_DT_SIZE); } } @@ -3130,7 +3137,7 @@ exit: static int tegra_hv_vse_safety_rng_drbg_get_random(struct crypto_rng *tfm, const u8 *src, unsigned int slen, u8 *rdata, unsigned int dlen) { - return tegra_hv_vse_safety_get_random(crypto_rng_ctx(tfm), rdata, dlen); + return tegra_hv_vse_safety_get_random(crypto_rng_ctx(tfm), rdata, dlen, CRYPTODEV_RNG); } static int tegra_hv_vse_safety_rng_drbg_reset(struct crypto_rng *tfm, @@ -4896,7 +4903,7 @@ static int tegra_hv_vse_safety_hwrng_read(struct hwrng *rng, void *buf, size_t s return 0; ctx = (struct tegra_virtual_se_rng_context *)rng->priv; - return tegra_hv_vse_safety_get_random(ctx, buf, size); + return tegra_hv_vse_safety_get_random(ctx, buf, size, HW_RNG); } #endif /* CONFIG_HW_RANDOM */ @@ -4920,6 +4927,15 @@ static int tegra_hv_vse_safety_register_hwrng(struct tegra_virtual_se_dev *se_de } rng_ctx->se_dev = se_dev; + + /* To ensure the memory is not overwritten when hwrng req arrives while + * AES CBC/CMAC or other AES operations are in progress + */ + rng_ctx->hwrng_dma_buf.buf_ptr = dma_alloc_coherent(se_dev->dev, TEGRA_VIRTUAL_SE_RNG_DT_SIZE, + &rng_ctx->hwrng_dma_buf.buf_iova, GFP_KERNEL); + if (!rng_ctx->hwrng_dma_buf.buf_ptr) + return -ENOMEM; + vse_hwrng->name = "tegra_hv_vse_safety"; vse_hwrng->read = tegra_hv_vse_safety_hwrng_read; vse_hwrng->quality = 1024; @@ -4928,6 +4944,11 @@ static int tegra_hv_vse_safety_register_hwrng(struct tegra_virtual_se_dev *se_de ret = devm_hwrng_register(se_dev->dev, vse_hwrng); out: if (ret) { + if (rng_ctx) { + dma_free_coherent(se_dev->dev, TEGRA_VIRTUAL_SE_RNG_DT_SIZE, + rng_ctx->hwrng_dma_buf.buf_ptr, rng_ctx->hwrng_dma_buf.buf_iova); + devm_kfree(se_dev->dev, rng_ctx); + } if (vse_hwrng) devm_kfree(se_dev->dev, vse_hwrng); } else { @@ -4948,6 +4969,9 @@ static void tegra_hv_vse_safety_unregister_hwrng(struct tegra_virtual_se_dev *se devm_hwrng_unregister(se_dev->dev, se_dev->hwrng); rng_ctx = (struct tegra_virtual_se_rng_context *)se_dev->hwrng->priv; + dma_free_coherent(se_dev->dev, TEGRA_VIRTUAL_SE_RNG_DT_SIZE, + rng_ctx->hwrng_dma_buf.buf_ptr, rng_ctx->hwrng_dma_buf.buf_iova); + devm_kfree(se_dev->dev, rng_ctx); devm_kfree(se_dev->dev, se_dev->hwrng); se_dev->hwrng = NULL; diff --git a/drivers/crypto/tegra-hv-vse.h b/drivers/crypto/tegra-hv-vse.h index 664d901f..aa6a96d6 100644 --- a/drivers/crypto/tegra-hv-vse.h +++ b/drivers/crypto/tegra-hv-vse.h @@ -94,6 +94,7 @@ struct tegra_virtual_se_dev { struct tegra_virtual_se_rng_context { /* Security Engine device */ struct tegra_virtual_se_dev *se_dev; + struct tegra_vse_dma_buf hwrng_dma_buf; /*Crypto dev instance*/ uint32_t node_id; };