crypto: ccree - don't map MAC key on stack
authorGilad Ben-Yossef <gilad@benyossef.com>
Thu, 18 Apr 2019 13:39:04 +0000 (16:39 +0300)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 25 Apr 2019 07:38:15 +0000 (15:38 +0800)
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 <gilad@benyossef.com>
Cc: stable@vger.kernel.org # v4.19+
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/ccree/cc_hash.c

index 36e9fb4141f8604003db0623a755f4658e63b7e4..a6abe4e3bb0e78977fefe8664d64d25224a8f2fe 100644 (file)
@@ -69,6 +69,7 @@ struct cc_hash_alg {
 struct hash_key_req_ctx {
        u32 keylen;
        dma_addr_t key_dma_addr;
+       u8 *key;
 };
 
 /* hash per-session context */
@@ -742,13 +743,20 @@ static int cc_hash_setkey(struct crypto_ahash *ahash, const u8 *key,
        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",
@@ -899,6 +907,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;
 }
 
@@ -925,11 +936,16 @@ static int cc_xcbc_setkey(struct crypto_ahash *ahash,
 
        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",
@@ -981,6 +997,8 @@ static int cc_xcbc_setkey(struct crypto_ahash *ahash,
        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;
 }