summaryrefslogtreecommitdiffstats
path: root/drivers/crypto/caam/key_gen.c
diff options
context:
space:
mode:
authorHoria Geantă <horia.geanta@nxp.com>2019-07-31 15:08:11 +0200
committerHerbert Xu <herbert@gondor.apana.org.au>2019-08-09 07:11:49 +0200
commite9b4913a5f944b23d6109c44b6f3fc6e092e30ce (patch)
tree2a6c10fcb99ecb99da8b1bc30f38999833452a69 /drivers/crypto/caam/key_gen.c
parentcrypto: caam - keep both virtual and dma key addresses (diff)
downloadlinux-e9b4913a5f944b23d6109c44b6f3fc6e092e30ce.tar.xz
linux-e9b4913a5f944b23d6109c44b6f3fc6e092e30ce.zip
crypto: caam - fix MDHA key derivation for certain user key lengths
Fuzz testing uncovered an issue when |user key| > |derived key|. Derived key generation has to be fixed in two cases: 1. Era >= 6 (DKP is available) DKP cannot be used with immediate input key if |user key| > |derived key|, since the resulting descriptor (after DKP execution) would be invalid - having a few bytes from user key left in descriptor buffer as incorrect opcodes. Fix DKP usage both in standalone hmac and in authenc algorithms. For authenc the logic is simplified, by always storing both virtual and dma key addresses. 2. Era < 6 The same case (|user key| > |derived key|) fails when DKP is not available. Make sure gen_split_key() dma maps max(|user key|, |derived key|), since this is an in-place (bidirectional) operation. Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Reviewed-by: Iuliana Prodan <iuliana.prodan@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/caam/key_gen.c')
-rw-r--r--drivers/crypto/caam/key_gen.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
index c6f8375ae215..5a851ddc48fb 100644
--- a/drivers/crypto/caam/key_gen.c
+++ b/drivers/crypto/caam/key_gen.c
@@ -48,18 +48,20 @@ int gen_split_key(struct device *jrdev, u8 *key_out,
u32 *desc;
struct split_key_result result;
dma_addr_t dma_addr;
+ unsigned int local_max;
int ret = -ENOMEM;
adata->keylen = split_key_len(adata->algtype & OP_ALG_ALGSEL_MASK);
adata->keylen_pad = split_key_pad_len(adata->algtype &
OP_ALG_ALGSEL_MASK);
+ local_max = max(keylen, adata->keylen_pad);
dev_dbg(jrdev, "split keylen %d split keylen padded %d\n",
adata->keylen, adata->keylen_pad);
print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1);
- if (adata->keylen_pad > max_keylen)
+ if (local_max > max_keylen)
return -EINVAL;
desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
@@ -70,8 +72,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out,
memcpy(key_out, key_in, keylen);
- dma_addr = dma_map_single(jrdev, key_out, adata->keylen_pad,
- DMA_BIDIRECTIONAL);
+ dma_addr = dma_map_single(jrdev, key_out, local_max, DMA_BIDIRECTIONAL);
if (dma_mapping_error(jrdev, dma_addr)) {
dev_err(jrdev, "unable to map key memory\n");
goto out_free;
@@ -117,7 +118,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out,
adata->keylen_pad, 1);
}
- dma_unmap_single(jrdev, dma_addr, adata->keylen_pad, DMA_BIDIRECTIONAL);
+ dma_unmap_single(jrdev, dma_addr, local_max, DMA_BIDIRECTIONAL);
out_free:
kfree(desc);
return ret;