diff --git a/crypto/echainiv.c b/crypto/echainiv.c index 9018c87b5d1a..149d8fb87962 100644 --- a/crypto/echainiv.c +++ b/crypto/echainiv.c @@ -167,6 +167,9 @@ static int echainiv_encrypt_compat(struct aead_request *req) __be64 seq; int err; + if (req->cryptlen < ivsize) + return -EINVAL; + compl = req->base.complete; data = req->base.data; @@ -212,17 +215,18 @@ static int echainiv_encrypt(struct aead_request *req) crypto_completion_t compl; void *data; u8 *info; - unsigned int ivsize; + unsigned int ivsize = crypto_aead_ivsize(geniv); int err; + if (req->cryptlen < ivsize) + return -EINVAL; + aead_request_set_tfm(subreq, ctx->child); compl = echainiv_encrypt_complete; data = req; info = req->iv; - ivsize = crypto_aead_ivsize(geniv); - if (req->src != req->dst) { struct scatterlist src[2]; struct scatterlist dst[2]; @@ -270,22 +274,28 @@ static int echainiv_decrypt_compat(struct aead_request *req) { struct crypto_aead *geniv = crypto_aead_reqtfm(req); struct echainiv_ctx *ctx = crypto_aead_ctx(geniv); - struct aead_request *subreq = aead_request_ctx(req); + struct echainiv_request_ctx *rctx = aead_request_ctx(req); + struct aead_request *subreq = &rctx->subreq.areq; crypto_completion_t compl; void *data; - unsigned int ivsize; + unsigned int ivsize = crypto_aead_ivsize(geniv); + + if (req->cryptlen < ivsize + crypto_aead_authsize(geniv)) + return -EINVAL; aead_request_set_tfm(subreq, ctx->child); compl = req->base.complete; data = req->base.data; - ivsize = crypto_aead_ivsize(geniv); - aead_request_set_callback(subreq, req->base.flags, compl, data); - aead_request_set_crypt(subreq, req->src, req->dst, + aead_request_set_crypt(subreq, + scatterwalk_ffwd(rctx->src, req->src, + req->assoclen + ivsize), + scatterwalk_ffwd(rctx->dst, req->dst, + req->assoclen + ivsize), req->cryptlen - ivsize, req->iv); - aead_request_set_ad(subreq, req->assoclen, ivsize); + aead_request_set_assoc(subreq, req->src, req->assoclen); scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0); @@ -299,15 +309,16 @@ static int echainiv_decrypt(struct aead_request *req) struct aead_request *subreq = aead_request_ctx(req); crypto_completion_t compl; void *data; - unsigned int ivsize; + unsigned int ivsize = crypto_aead_ivsize(geniv); + + if (req->cryptlen < ivsize + crypto_aead_authsize(geniv)) + return -EINVAL; aead_request_set_tfm(subreq, ctx->child); compl = req->base.complete; data = req->base.data; - ivsize = crypto_aead_ivsize(geniv); - aead_request_set_callback(subreq, req->base.flags, compl, data); aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen - ivsize, req->iv);