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: 15b59e7c37 ("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>
This commit is contained in:
Rosioru Dragos 2020-02-25 17:05:52 +02:00 committed by Herbert Xu
parent 5fbab10dee
commit fa03481b6e
1 changed files with 26 additions and 28 deletions

View File

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