crypto: sun8i-ss - handle requests if last block is not modulo 64
authorCorentin Labbe <clabbe@baylibre.com>
Mon, 2 May 2022 20:19:21 +0000 (20:19 +0000)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 13 May 2022 09:24:19 +0000 (17:24 +0800)
The current sun8i-ss handle only requests with all SG length being
modulo 64.
But the last SG could be always handled by copying it on the pad buffer.

Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h

index 786b6f5..8d31fd4 100644 (file)
@@ -487,7 +487,7 @@ static int allocate_flows(struct sun8i_ss_dev *ss)
                }
 
                /* the padding could be up to two block. */
-               ss->flows[i].pad = devm_kmalloc(ss->dev, SHA256_BLOCK_SIZE * 2,
+               ss->flows[i].pad = devm_kmalloc(ss->dev, MAX_PAD_SIZE,
                                                GFP_KERNEL | GFP_DMA);
                if (!ss->flows[i].pad)
                        goto error_engine;
index 53e5bfb..1b44c1a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
 #include <crypto/internal/hash.h>
+#include <crypto/scatterwalk.h>
 #include <crypto/sha1.h>
 #include <crypto/sha2.h>
 #include <crypto/md5.h>
@@ -262,6 +263,9 @@ static bool sun8i_ss_hash_need_fallback(struct ahash_request *areq)
 
        if (areq->nbytes == 0)
                return true;
+       if (areq->nbytes >= MAX_PAD_SIZE - 64)
+               return true;
+
        /* we need to reserve one SG for the padding one */
        if (sg_nents(areq->src) > MAX_SG - 1)
                return true;
@@ -270,10 +274,13 @@ static bool sun8i_ss_hash_need_fallback(struct ahash_request *areq)
                /* SS can operate hash only on full block size
                 * since SS support only MD5,sha1,sha224 and sha256, blocksize
                 * is always 64
-                * TODO: handle request if last SG is not len%64
-                * but this will need to copy data on a new SG of size=64
                 */
-               if (sg->length % 64 || !IS_ALIGNED(sg->offset, sizeof(u32)))
+               /* Only the last block could be bounced to the pad buffer */
+               if (sg->length % 64 && sg_next(sg))
+                       return true;
+               if (!IS_ALIGNED(sg->offset, sizeof(u32)))
+                       return true;
+               if (sg->length % 4)
                        return true;
                sg = sg_next(sg);
        }
@@ -361,6 +368,7 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq)
                goto theend;
        }
 
+       j = 0;
        len = areq->nbytes;
        sg = areq->src;
        i = 0;
@@ -369,12 +377,19 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq)
                        sg = sg_next(sg);
                        continue;
                }
-               rctx->t_src[i].addr = sg_dma_address(sg);
                todo = min(len, sg_dma_len(sg));
-               rctx->t_src[i].len = todo / 4;
-               len -= todo;
-               rctx->t_dst[i].addr = addr_res;
-               rctx->t_dst[i].len = digestsize / 4;
+               /* only the last SG could be with a size not modulo64 */
+               if (todo % 64 == 0) {
+                       rctx->t_src[i].addr = sg_dma_address(sg);
+                       rctx->t_src[i].len = todo / 4;
+                       rctx->t_dst[i].addr = addr_res;
+                       rctx->t_dst[i].len = digestsize / 4;
+                       len -= todo;
+               } else {
+                       scatterwalk_map_and_copy(bf, sg, 0, todo, 0);
+                       j += todo / 4;
+                       len -= todo;
+               }
                sg = sg_next(sg);
                i++;
        }
@@ -384,8 +399,10 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq)
                goto theend;
        }
 
+       if (j > 0)
+               i--;
+
        byte_count = areq->nbytes;
-       j = 0;
        bf[j++] = cpu_to_le32(0x80);
 
        fill = 64 - (byte_count % 64);
index eb82ee5..2e35246 100644 (file)
@@ -82,6 +82,8 @@
 #define PRNG_DATA_SIZE (160 / 8)
 #define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8)
 
+#define MAX_PAD_SIZE 4096
+
 /*
  * struct ss_clock - Describe clocks used by sun8i-ss
  * @name:       Name of clock needed by this variant