crypto: mxs-dcp - fix scatterlist linearization for hash
authorRosioru Dragos <dragos.rosioru@nxp.com>
Tue, 25 Feb 2020 15:05:52 +0000 (17:05 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 6 Mar 2020 01:28:21 +0000 (12:28 +1100)
The incorrect traversal of the scatterlist, during the linearization phase
lead to computing the hash value of the wrong input buffer.
New implementation uses scatterwalk_map_and_copy()
to address this issue.

Cc: <stable@vger.kernel.org>
Fixes: 15b59e7c3733 ("crypto: mxs - Add Freescale MXS DCP driver")
Signed-off-by: Rosioru Dragos <dragos.rosioru@nxp.com>
Reviewed-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/mxs-dcp.c

index 435ac1c..d845302 100644 (file)
@@ -20,6 +20,7 @@
 #include <crypto/sha.h>
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
 
 #define DCP_MAX_CHANS  4
 #define DCP_BUF_SZ     PAGE_SIZE
@@ -611,49 +612,46 @@ static int dcp_sha_req_to_buf(struct crypto_async_request *arq)
        struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
        struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
        struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
-       const int nents = sg_nents(req->src);
 
        uint8_t *in_buf = sdcp->coh->sha_in_buf;
        uint8_t *out_buf = sdcp->coh->sha_out_buf;
 
-       uint8_t *src_buf;
-
        struct scatterlist *src;
 
-       unsigned int i, len, clen;
+       unsigned int i, len, clen, oft = 0;
        int ret;
 
        int fin = rctx->fini;
        if (fin)
                rctx->fini = 0;
 
-       for_each_sg(req->src, src, nents, i) {
-               src_buf = sg_virt(src);
-               len = sg_dma_len(src);
-
-               do {
-                       if (actx->fill + len > DCP_BUF_SZ)
-                               clen = DCP_BUF_SZ - actx->fill;
-                       else
-                               clen = len;
-
-                       memcpy(in_buf + actx->fill, src_buf, clen);
-                       len -= clen;
-                       src_buf += clen;
-                       actx->fill += clen;
+       src = req->src;
+       len = req->nbytes;
 
-                       /*
-                        * If we filled the buffer and still have some
-                        * more data, submit the buffer.
-                        */
-                       if (len && actx->fill == DCP_BUF_SZ) {
-                               ret = mxs_dcp_run_sha(req);
-                               if (ret)
-                                       return ret;
-                               actx->fill = 0;
-                               rctx->init = 0;
-                       }
-               } while (len);
+       while (len) {
+               if (actx->fill + len > DCP_BUF_SZ)
+                       clen = DCP_BUF_SZ - actx->fill;
+               else
+                       clen = len;
+
+               scatterwalk_map_and_copy(in_buf + actx->fill, src, oft, clen,
+                                        0);
+
+               len -= clen;
+               oft += clen;
+               actx->fill += clen;
+
+               /*
+                * If we filled the buffer and still have some
+                * more data, submit the buffer.
+                */
+               if (len && actx->fill == DCP_BUF_SZ) {
+                       ret = mxs_dcp_run_sha(req);
+                       if (ret)
+                               return ret;
+                       actx->fill = 0;
+                       rctx->init = 0;
+               }
        }
 
        if (fin) {