Commit b756f1c8 authored by Corentin Labbe's avatar Corentin Labbe Committed by Herbert Xu

crypto: sun4i-ss - IV register does not work on A10 and A13

Allwinner A10 and A13 SoC have a version of the SS which produce
invalid IV in IVx register.

Instead of adding a variant for those, let's convert SS to produce IV
directly from data.
Fixes: 6298e948 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarCorentin Labbe <clabbe@baylibre.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 7bdcd851
...@@ -20,6 +20,7 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) ...@@ -20,6 +20,7 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq)
unsigned int ivsize = crypto_skcipher_ivsize(tfm); unsigned int ivsize = crypto_skcipher_ivsize(tfm);
struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq);
u32 mode = ctx->mode; u32 mode = ctx->mode;
void *backup_iv = NULL;
/* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */ /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */
u32 rx_cnt = SS_RX_DEFAULT; u32 rx_cnt = SS_RX_DEFAULT;
u32 tx_cnt = 0; u32 tx_cnt = 0;
...@@ -42,6 +43,13 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) ...@@ -42,6 +43,13 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq)
return -EINVAL; return -EINVAL;
} }
if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
backup_iv = kzalloc(ivsize, GFP_KERNEL);
if (!backup_iv)
return -ENOMEM;
scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
}
spin_lock_irqsave(&ss->slock, flags); spin_lock_irqsave(&ss->slock, flags);
for (i = 0; i < op->keylen; i += 4) for (i = 0; i < op->keylen; i += 4)
...@@ -102,9 +110,12 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) ...@@ -102,9 +110,12 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq)
} while (oleft); } while (oleft);
if (areq->iv) { if (areq->iv) {
for (i = 0; i < 4 && i < ivsize / 4; i++) { if (mode & SS_DECRYPTION) {
v = readl(ss->base + SS_IV0 + i * 4); memcpy(areq->iv, backup_iv, ivsize);
*(u32 *)(areq->iv + i * 4) = v; kfree_sensitive(backup_iv);
} else {
scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
ivsize, 0);
} }
} }
...@@ -161,6 +172,7 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) ...@@ -161,6 +172,7 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq)
unsigned int ileft = areq->cryptlen; unsigned int ileft = areq->cryptlen;
unsigned int oleft = areq->cryptlen; unsigned int oleft = areq->cryptlen;
unsigned int todo; unsigned int todo;
void *backup_iv = NULL;
struct sg_mapping_iter mi, mo; struct sg_mapping_iter mi, mo;
unsigned int oi, oo; /* offset for in and out */ unsigned int oi, oo; /* offset for in and out */
unsigned int ob = 0; /* offset in buf */ unsigned int ob = 0; /* offset in buf */
...@@ -202,6 +214,13 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) ...@@ -202,6 +214,13 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq)
if (need_fallback) if (need_fallback)
return sun4i_ss_cipher_poll_fallback(areq); return sun4i_ss_cipher_poll_fallback(areq);
if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
backup_iv = kzalloc(ivsize, GFP_KERNEL);
if (!backup_iv)
return -ENOMEM;
scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
}
spin_lock_irqsave(&ss->slock, flags); spin_lock_irqsave(&ss->slock, flags);
for (i = 0; i < op->keylen; i += 4) for (i = 0; i < op->keylen; i += 4)
...@@ -322,9 +341,12 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) ...@@ -322,9 +341,12 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq)
} }
} }
if (areq->iv) { if (areq->iv) {
for (i = 0; i < 4 && i < ivsize / 4; i++) { if (mode & SS_DECRYPTION) {
v = readl(ss->base + SS_IV0 + i * 4); memcpy(areq->iv, backup_iv, ivsize);
*(u32 *)(areq->iv + i * 4) = v; kfree_sensitive(backup_iv);
} else {
scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
ivsize, 0);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment