Skip to content
Snippets Groups Projects
Commit 84f5e221 authored by Radu Solea's avatar Radu Solea Committed by Jason Liu
Browse files

MA-9807: Fix ecb(aes) use without an IV


CAAM aes modes share descriptors, because of this CAAM requires an IV
for ECB. ECB does not need an IV and users do not have to pass valid
IV vectors. To allow correct usage with minimum impact to the driver a
zero IV is provided by the driver for ECB operations that need it.

Signed-off-by: default avatarRadu Solea <radu.solea@nxp.com>
parent 990db3f2
No related branches found
No related tags found
No related merge requests found
...@@ -1183,6 +1183,9 @@ static void init_ablkcipher_giv_job(u32 *sh_desc, dma_addr_t ptr, ...@@ -1183,6 +1183,9 @@ static void init_ablkcipher_giv_job(u32 *sh_desc, dma_addr_t ptr,
append_seq_out_ptr(desc, dst_dma, req->nbytes + ivsize, LDST_SGF); append_seq_out_ptr(desc, dst_dma, req->nbytes + ivsize, LDST_SGF);
} }
static uint8_t *ecb_zero_iv;
static dma_addr_t ecb_ziv_dma;
/* /*
* allocate and map the aead extended descriptor * allocate and map the aead extended descriptor
*/ */
...@@ -1486,6 +1489,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request ...@@ -1486,6 +1489,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
u8 *iv; u8 *iv;
int ivsize = crypto_ablkcipher_ivsize(ablkcipher); int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
int dst_sg_idx, sec4_sg_ents, sec4_sg_bytes; int dst_sg_idx, sec4_sg_ents, sec4_sg_bytes;
uint32_t c1_alg_typ = ctx->cdata.algtype;
src_nents = sg_nents_for_len(req->src, req->nbytes); src_nents = sg_nents_for_len(req->src, req->nbytes);
if (unlikely(src_nents < 0)) { if (unlikely(src_nents < 0)) {
...@@ -1555,13 +1559,19 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request ...@@ -1555,13 +1559,19 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes; iv = (u8 *)edesc->hw_desc + desc_bytes + sec4_sg_bytes;
memcpy(iv, req->info, ivsize); memcpy(iv, req->info, ivsize);
iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_TO_DEVICE); if ((!req->info && ivsize) &&
if (dma_mapping_error(jrdev, iv_dma)) { ((c1_alg_typ & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES) &&
dev_err(jrdev, "unable to map IV\n"); ((c1_alg_typ & OP_ALG_AAI_MASK) == OP_ALG_AAI_ECB)) {
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0, iv_dma = ecb_ziv_dma;
0, DMA_NONE, 0, 0); } else {
kfree(edesc); iv_dma = dma_map_single(jrdev, iv, ivsize, DMA_TO_DEVICE);
return ERR_PTR(-ENOMEM); if (dma_mapping_error(jrdev, iv_dma)) {
dev_err(jrdev, "unable to map IV\n");
caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
0, DMA_NONE, 0, 0);
kfree(edesc);
return ERR_PTR(-ENOMEM);
}
} }
dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0); dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
...@@ -3378,10 +3388,35 @@ static void caam_aead_exit(struct crypto_aead *tfm) ...@@ -3378,10 +3388,35 @@ static void caam_aead_exit(struct crypto_aead *tfm)
static void __exit caam_algapi_exit(void) static void __exit caam_algapi_exit(void)
{ {
struct device_node *dev_node;
struct platform_device *pdev;
struct device *ctrldev;
struct caam_crypto_alg *t_alg, *n; struct caam_crypto_alg *t_alg, *n;
int i; int i;
if (!ecb_zero_iv)
goto skip_ecb_ziv;
dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
if (!dev_node) {
dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
if (!dev_node)
goto skip_ecb_ziv;
}
pdev = of_find_device_by_node(dev_node);
if (!pdev) {
of_node_put(dev_node);
goto skip_ecb_ziv;
}
ctrldev = &pdev->dev;
dma_unmap_single(ctrldev, ecb_ziv_dma, AES_BLOCK_SIZE, DMA_TO_DEVICE);
kfree(ecb_zero_iv);
skip_ecb_ziv:
for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) { for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) {
struct caam_aead_alg *t_alg = driver_aeads + i; struct caam_aead_alg *t_alg = driver_aeads + i;
...@@ -3494,6 +3529,16 @@ static int __init caam_algapi_init(void) ...@@ -3494,6 +3529,16 @@ static int __init caam_algapi_init(void)
if (!priv) if (!priv)
return -ENODEV; return -ENODEV;
ecb_zero_iv = kzalloc(AES_BLOCK_SIZE, GFP_KERNEL);
if (!ecb_zero_iv)
return -ENOMEM;
ecb_ziv_dma = dma_map_single(ctrldev, ecb_zero_iv, AES_BLOCK_SIZE,
DMA_TO_DEVICE);
if (dma_mapping_error(ctrldev, ecb_ziv_dma)) {
kfree(ecb_zero_iv);
return -ENOMEM;
}
INIT_LIST_HEAD(&alg_list); INIT_LIST_HEAD(&alg_list);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment