Commit c776f7d3 authored by Gilad Ben-Yossef's avatar Gilad Ben-Yossef Committed by Herbert Xu

crypto: ccree - make AEAD sgl iterator well behaved

Fix some scatter list interation code was not handling scatter lists
being shorter than expected in a graceful manner.
Signed-off-by: default avatarGilad Ben-Yossef <gilad@benyossef.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent da3cf67f
...@@ -659,11 +659,9 @@ static int cc_aead_chain_assoc(struct cc_drvdata *drvdata, ...@@ -659,11 +659,9 @@ static int cc_aead_chain_assoc(struct cc_drvdata *drvdata,
{ {
struct aead_req_ctx *areq_ctx = aead_request_ctx(req); struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
int rc = 0; int rc = 0;
u32 mapped_nents = 0; int mapped_nents = 0;
struct scatterlist *current_sg = req->src;
struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct crypto_aead *tfm = crypto_aead_reqtfm(req);
unsigned int sg_index = 0; unsigned int size_of_assoc = areq_ctx->assoclen;
u32 size_of_assoc = areq_ctx->assoclen;
struct device *dev = drvdata_to_dev(drvdata); struct device *dev = drvdata_to_dev(drvdata);
if (areq_ctx->is_gcm4543) if (areq_ctx->is_gcm4543)
...@@ -684,26 +682,10 @@ static int cc_aead_chain_assoc(struct cc_drvdata *drvdata, ...@@ -684,26 +682,10 @@ static int cc_aead_chain_assoc(struct cc_drvdata *drvdata,
goto chain_assoc_exit; goto chain_assoc_exit;
} }
//iterate over the sgl to see how many entries are for associated data mapped_nents = sg_nents_for_len(req->src, size_of_assoc);
//it is assumed that if we reach here , the sgl is already mapped if (mapped_nents < 0)
sg_index = current_sg->length; return mapped_nents;
//the first entry in the scatter list contains all the associated data
if (sg_index > size_of_assoc) {
mapped_nents++;
} else {
while (sg_index <= size_of_assoc) {
current_sg = sg_next(current_sg);
/* if have reached the end of the sgl, then this is
* unexpected
*/
if (!current_sg) {
dev_err(dev, "reached end of sg list. unexpected\n");
return -EINVAL;
}
sg_index += current_sg->length;
mapped_nents++;
}
}
if (mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) { if (mapped_nents > LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES) {
dev_err(dev, "Too many fragments. current %d max %d\n", dev_err(dev, "Too many fragments. current %d max %d\n",
mapped_nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES); mapped_nents, LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES);
...@@ -898,6 +880,7 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata, ...@@ -898,6 +880,7 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata,
u32 sg_index = 0; u32 sg_index = 0;
bool is_gcm4543 = areq_ctx->is_gcm4543; bool is_gcm4543 = areq_ctx->is_gcm4543;
u32 size_to_skip = areq_ctx->assoclen; u32 size_to_skip = areq_ctx->assoclen;
struct scatterlist *sgl;
if (is_gcm4543) if (is_gcm4543)
size_to_skip += crypto_aead_ivsize(tfm); size_to_skip += crypto_aead_ivsize(tfm);
...@@ -920,15 +903,13 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata, ...@@ -920,15 +903,13 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata,
sg_index = areq_ctx->src_sgl->length; sg_index = areq_ctx->src_sgl->length;
//check where the data starts //check where the data starts
while (sg_index <= size_to_skip) { while (sg_index <= size_to_skip) {
src_mapped_nents--;
offset -= areq_ctx->src_sgl->length; offset -= areq_ctx->src_sgl->length;
areq_ctx->src_sgl = sg_next(areq_ctx->src_sgl); sgl = sg_next(areq_ctx->src_sgl);
//if have reached the end of the sgl, then this is unexpected if (!sgl)
if (!areq_ctx->src_sgl) { break;
dev_err(dev, "reached end of sg list. unexpected\n"); areq_ctx->src_sgl = sgl;
return -EINVAL;
}
sg_index += areq_ctx->src_sgl->length; sg_index += areq_ctx->src_sgl->length;
src_mapped_nents--;
} }
if (src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) { if (src_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) {
dev_err(dev, "Too many fragments. current %d max %d\n", dev_err(dev, "Too many fragments. current %d max %d\n",
...@@ -962,15 +943,13 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata, ...@@ -962,15 +943,13 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata,
//check where the data starts //check where the data starts
while (sg_index <= size_to_skip) { while (sg_index <= size_to_skip) {
dst_mapped_nents--;
offset -= areq_ctx->dst_sgl->length; offset -= areq_ctx->dst_sgl->length;
areq_ctx->dst_sgl = sg_next(areq_ctx->dst_sgl); sgl = sg_next(areq_ctx->dst_sgl);
//if have reached the end of the sgl, then this is unexpected if (!sgl)
if (!areq_ctx->dst_sgl) { break;
dev_err(dev, "reached end of sg list. unexpected\n"); areq_ctx->dst_sgl = sgl;
return -EINVAL;
}
sg_index += areq_ctx->dst_sgl->length; sg_index += areq_ctx->dst_sgl->length;
dst_mapped_nents--;
} }
if (dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) { if (dst_mapped_nents > LLI_MAX_NUM_OF_DATA_ENTRIES) {
dev_err(dev, "Too many fragments. current %d max %d\n", dev_err(dev, "Too many fragments. current %d max %d\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment