From 81a59f000e1d4a60a03081a1fc64aee46d6f0c3e Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Mon, 6 Jan 2014 13:34:17 -0600 Subject: crypto: ccp - Change data length declarations to u64 When performing a hash operation if the amount of data buffered and a request at or near the maximum data length is received then the length calcuation could wrap causing an error in executing the hash operation. Fix this by using a u64 type for the input and output data lengths in all CCP operations. Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-sha.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/crypto/ccp/ccp-crypto-sha.c') diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index 183d16e46d20..d30f6c893ffb 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -101,8 +101,9 @@ static int ccp_sha_complete(struct crypto_async_request *async_req, int ret) if (rctx->hash_rem) { /* Save remaining data to buffer */ - scatterwalk_map_and_copy(rctx->buf, rctx->cmd.u.sha.src, - rctx->hash_cnt, rctx->hash_rem, 0); + unsigned int offset = rctx->nbytes - rctx->hash_rem; + scatterwalk_map_and_copy(rctx->buf, rctx->src, + offset, rctx->hash_rem, 0); rctx->buf_count = rctx->hash_rem; } else rctx->buf_count = 0; @@ -129,11 +130,14 @@ static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes, struct scatterlist *sg; unsigned int block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); - unsigned int len, sg_count; + unsigned int sg_count; gfp_t gfp; + u64 len; int ret; - if (!final && ((nbytes + rctx->buf_count) <= block_size)) { + len = (u64)rctx->buf_count + (u64)nbytes; + + if (!final && (len <= block_size)) { scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src, 0, nbytes, 0); rctx->buf_count += nbytes; @@ -141,12 +145,13 @@ static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes, return 0; } - len = rctx->buf_count + nbytes; + rctx->src = req->src; + rctx->nbytes = nbytes; rctx->final = final; - rctx->hash_cnt = final ? len : len & ~(block_size - 1); - rctx->hash_rem = final ? 0 : len & (block_size - 1); - if (!final && (rctx->hash_cnt == len)) { + rctx->hash_rem = final ? 0 : len & (block_size - 1); + rctx->hash_cnt = len - rctx->hash_rem; + if (!final && !rctx->hash_rem) { /* CCP can't do zero length final, so keep some data around */ rctx->hash_cnt -= block_size; rctx->hash_rem = block_size; -- cgit