crypto: mxs-dcp - fix scatterlist linearization for hash

commit fa03481b6e upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Rosioru Dragos
2020-02-25 17:05:52 +02:00
committed by Chris
parent b3315ae13d
commit 1a3cc49fe2

View File

@@ -25,6 +25,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
@@ -621,49 +622,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);
src = req->src;
len = req->nbytes;
do {
if (actx->fill + len > DCP_BUF_SZ)
clen = DCP_BUF_SZ - actx->fill;
else
clen = len;
while (len) {
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;
scatterwalk_map_and_copy(in_buf + actx->fill, src, oft, clen,
0);
/*
* 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);
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) {