From: Gilad Ben-Yossef <gi...@benyossef.com>

commit 874e163759f27e0a9988c5d1f4605e3f25564fd2 upstream.

The MAC hash key might be passed to us on stack. Copy it to
a slab buffer before mapping to gurantee proper DMA mapping.

Signed-off-by: Gilad Ben-Yossef <gi...@benyossef.com>
Cc: sta...@vger.kernel.org # v4.19+
Signed-off-by: Herbert Xu <herb...@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 drivers/crypto/ccree/cc_hash.c |   24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

--- a/drivers/crypto/ccree/cc_hash.c
+++ b/drivers/crypto/ccree/cc_hash.c
@@ -64,6 +64,7 @@ struct cc_hash_alg {
 struct hash_key_req_ctx {
        u32 keylen;
        dma_addr_t key_dma_addr;
+       u8 *key;
 };
 
 /* hash per-session context */
@@ -724,13 +725,20 @@ static int cc_hash_setkey(struct crypto_
        ctx->key_params.keylen = keylen;
        ctx->key_params.key_dma_addr = 0;
        ctx->is_hmac = true;
+       ctx->key_params.key = NULL;
 
        if (keylen) {
+               ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL);
+               if (!ctx->key_params.key)
+                       return -ENOMEM;
+
                ctx->key_params.key_dma_addr =
-                       dma_map_single(dev, (void *)key, keylen, DMA_TO_DEVICE);
+                       dma_map_single(dev, (void *)ctx->key_params.key, keylen,
+                                      DMA_TO_DEVICE);
                if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) {
                        dev_err(dev, "Mapping key va=0x%p len=%u for DMA 
failed\n",
-                               key, keylen);
+                               ctx->key_params.key, keylen);
+                       kzfree(ctx->key_params.key);
                        return -ENOMEM;
                }
                dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad 
keylen=%u\n",
@@ -881,6 +889,9 @@ out:
                dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad 
keylen=%u\n",
                        &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
        }
+
+       kzfree(ctx->key_params.key);
+
        return rc;
 }
 
@@ -907,11 +918,16 @@ static int cc_xcbc_setkey(struct crypto_
 
        ctx->key_params.keylen = keylen;
 
+       ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL);
+       if (!ctx->key_params.key)
+               return -ENOMEM;
+
        ctx->key_params.key_dma_addr =
-               dma_map_single(dev, (void *)key, keylen, DMA_TO_DEVICE);
+               dma_map_single(dev, ctx->key_params.key, keylen, DMA_TO_DEVICE);
        if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) {
                dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
                        key, keylen);
+               kzfree(ctx->key_params.key);
                return -ENOMEM;
        }
        dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n",
@@ -963,6 +979,8 @@ static int cc_xcbc_setkey(struct crypto_
        dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n",
                &ctx->key_params.key_dma_addr, ctx->key_params.keylen);
 
+       kzfree(ctx->key_params.key);
+
        return rc;
 }
 


Reply via email to