summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPascal van Leeuwen <pascalvanl@gmail.com>2019-12-11 19:32:36 +0300
committerHerbert Xu <herbert@gondor.apana.org.au>2019-12-20 09:58:34 +0300
commitcb97aa9473627720810a0a016621c36f15392802 (patch)
tree5db431f2bb3e9a5a661d30335a146840c03eef73
parent098e51e517bc2e5865c520f3eee8bf83dd320e61 (diff)
downloadlinux-cb97aa9473627720810a0a016621c36f15392802.tar.xz
crypto: inside-secure - Fix hang case on EIP97 with zero length input data
The EIP97 hardware cannot handle zero length input data and will (usually) hang when presented with this anyway. This patch converts any zero length input to a 1 byte dummy input to prevent this hanging. Signed-off-by: Pascal van Leeuwen <pvanleeuwen@rambus.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/inside-secure/safexcel_cipher.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c
index f5d9f9051297..bc5605e89d11 100644
--- a/drivers/crypto/inside-secure/safexcel_cipher.c
+++ b/drivers/crypto/inside-secure/safexcel_cipher.c
@@ -782,16 +782,31 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring,
memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len);
- /* The EIP cannot deal with zero length input packets! */
- if (totlen == 0)
- totlen = 1;
+ if (!totlen) {
+ /*
+ * The EIP97 cannot deal with zero length input packets!
+ * So stuff a dummy command descriptor indicating a 1 byte
+ * (dummy) input packet, using the context record as source.
+ */
+ first_cdesc = safexcel_add_cdesc(priv, ring,
+ 1, 1, ctx->base.ctxr_dma,
+ 1, 1, ctx->base.ctxr_dma,
+ &atoken);
+ if (IS_ERR(first_cdesc)) {
+ /* No space left in the command descriptor ring */
+ ret = PTR_ERR(first_cdesc);
+ goto cdesc_rollback;
+ }
+ n_cdesc = 1;
+ goto skip_cdesc;
+ }
/* command descriptors */
for_each_sg(src, sg, sreq->nr_src, i) {
int len = sg_dma_len(sg);
/* Do not overflow the request */
- if (queued - len < 0)
+ if (queued < len)
len = queued;
cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc,
@@ -803,27 +818,16 @@ static int safexcel_send_req(struct crypto_async_request *base, int ring,
ret = PTR_ERR(cdesc);
goto cdesc_rollback;
}
- n_cdesc++;
- if (n_cdesc == 1) {
+ if (!n_cdesc)
first_cdesc = cdesc;
- }
+ n_cdesc++;
queued -= len;
if (!queued)
break;
}
-
- if (unlikely(!n_cdesc)) {
- /*
- * Special case: zero length input buffer.
- * The engine always needs the 1st command descriptor, however!
- */
- first_cdesc = safexcel_add_cdesc(priv, ring, 1, 1, 0, 0, totlen,
- ctx->base.ctxr_dma, &atoken);
- n_cdesc = 1;
- }
-
+skip_cdesc:
/* Add context control words and token to first command descriptor */
safexcel_context_control(ctx, base, sreq, first_cdesc);
if (ctx->aead)