summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRadu Solea <radu.solea@nxp.com>2017-07-05 15:30:44 +0300
committerRadu Solea <radu.solea@nxp.com>2017-07-05 16:36:36 +0300
commit93420765950b0932a980b9a1a7f4d2489e4ff165 (patch)
tree5599edcca2bdd919c330e4b0008f860921ba053f /drivers
parent25c42567af53f8efd6c862d28bf1554b371645a0 (diff)
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: Radu Solea <radu.solea@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/crypto/caam/caamalg.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index dbf28717ba6f..b8c0abd95250 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -163,6 +163,9 @@ struct caam_aead_alg {
bool registered;
};
+static uint8_t *ecb_zero_iv;
+static dma_addr_t ecb_ziv_dma;
+
/* Set DK bit in class 1 operation if shared */
static inline void append_dec_op1(u32 *desc, u32 type)
{
@@ -2647,6 +2650,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
int sgc;
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
int sec4_sg_index;
+ uint32_t c1_alg_typ = ctx->class1_alg_type;
src_nents = sg_count(req->src, req->nbytes);
@@ -2663,10 +2667,17 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
DMA_FROM_DEVICE);
}
- iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, iv_dma)) {
- dev_err(jrdev, "unable to map IV\n");
- return ERR_PTR(-ENOMEM);
+ if ((!req->info && ivsize) &&
+ ((c1_alg_typ & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES) &&
+ ((c1_alg_typ & OP_ALG_AAI_MASK) == OP_ALG_AAI_ECB)) {
+ iv_dma = ecb_ziv_dma;
+ } else {
+ iv_dma = dma_map_single(jrdev, req->info, ivsize,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, iv_dma)) {
+ dev_err(jrdev, "unable to map IV\n");
+ return ERR_PTR(-ENOMEM);
+ }
}
/*
@@ -4541,10 +4552,35 @@ static void caam_aead_exit(struct crypto_aead *tfm)
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;
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++) {
struct caam_aead_alg *t_alg = driver_aeads + i;
@@ -4658,6 +4694,16 @@ static int __init caam_algapi_init(void)
if (!priv)
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);