Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: mxs-dcp - fix scatterlist linearization for hash

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>

authored by

Rosioru Dragos and committed by
Herbert Xu
fa03481b 5fbab10d

+26 -28
+26 -28
drivers/crypto/mxs-dcp.c
··· 20 20 #include <crypto/sha.h> 21 21 #include <crypto/internal/hash.h> 22 22 #include <crypto/internal/skcipher.h> 23 + #include <crypto/scatterwalk.h> 23 24 24 25 #define DCP_MAX_CHANS 4 25 26 #define DCP_BUF_SZ PAGE_SIZE ··· 612 611 struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm); 613 612 struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req); 614 613 struct hash_alg_common *halg = crypto_hash_alg_common(tfm); 615 - const int nents = sg_nents(req->src); 616 614 617 615 uint8_t *in_buf = sdcp->coh->sha_in_buf; 618 616 uint8_t *out_buf = sdcp->coh->sha_out_buf; 619 617 620 - uint8_t *src_buf; 621 - 622 618 struct scatterlist *src; 623 619 624 - unsigned int i, len, clen; 620 + unsigned int i, len, clen, oft = 0; 625 621 int ret; 626 622 627 623 int fin = rctx->fini; 628 624 if (fin) 629 625 rctx->fini = 0; 630 626 631 - for_each_sg(req->src, src, nents, i) { 632 - src_buf = sg_virt(src); 633 - len = sg_dma_len(src); 627 + src = req->src; 628 + len = req->nbytes; 634 629 635 - do { 636 - if (actx->fill + len > DCP_BUF_SZ) 637 - clen = DCP_BUF_SZ - actx->fill; 638 - else 639 - clen = len; 630 + while (len) { 631 + if (actx->fill + len > DCP_BUF_SZ) 632 + clen = DCP_BUF_SZ - actx->fill; 633 + else 634 + clen = len; 640 635 641 - memcpy(in_buf + actx->fill, src_buf, clen); 642 - len -= clen; 643 - src_buf += clen; 644 - actx->fill += clen; 636 + scatterwalk_map_and_copy(in_buf + actx->fill, src, oft, clen, 637 + 0); 645 638 646 - /* 647 - * If we filled the buffer and still have some 648 - * more data, submit the buffer. 649 - */ 650 - if (len && actx->fill == DCP_BUF_SZ) { 651 - ret = mxs_dcp_run_sha(req); 652 - if (ret) 653 - return ret; 654 - actx->fill = 0; 655 - rctx->init = 0; 656 - } 657 - } while (len); 639 + len -= clen; 640 + oft += clen; 641 + actx->fill += clen; 642 + 643 + /* 644 + * If we filled the buffer and still have some 645 + * more data, submit the buffer. 646 + */ 647 + if (len && actx->fill == DCP_BUF_SZ) { 648 + ret = mxs_dcp_run_sha(req); 649 + if (ret) 650 + return ret; 651 + actx->fill = 0; 652 + rctx->init = 0; 653 + } 658 654 } 659 655 660 656 if (fin) {