summaryrefslogtreecommitdiff
path: root/crypto/echainiv.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-05-23 10:41:54 +0300
committerHerbert Xu <herbert@gondor.apana.org.au>2015-05-25 13:41:31 +0300
commit823655c99bdb990d687d8f293185dcc505be38c2 (patch)
tree92080c5c12a449773aa4a43993cde11617dea772 /crypto/echainiv.c
parentd1ee1f02b7a207e757cbd78a9865a69234a0d867 (diff)
downloadlinux-823655c99bdb990d687d8f293185dcc505be38c2.tar.xz
crypto: echainiv - Stop using cryptoff
The cryptoff parameter was added to facilitate the skipping of IVs that sit between the AD and the plain/cipher text. However, it was never implemented correctly as and we do not handle users such as IPsec setting cryptoff. It is simply ignored. Implementing correctly is in fact more trouble than what it's worth. This patch removes the uses of cryptoff and simply falls back to using the old AEAD interface as it's only needed for old AEAD implementations. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/echainiv.c')
-rw-r--r--crypto/echainiv.c35
1 files changed, 23 insertions, 12 deletions
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);