From 3735304a1d1a39404c7725c227ae037c21125ad0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Jul 2015 07:17:20 +0800 Subject: crypto: echainiv - Fix encryption convention This patch fixes a bug where we were incorrectly including the IV in the AD during encryption. The IV must remain in the plain text for it to be encrypted. During decryption there is no need to copy the IV to dst because it's now part of the AD. This patch removes an unncessary check on authsize which would be performed by the underlying decrypt call. Finally this patch makes use of the type-safe init/exit functions. Signed-off-by: Herbert Xu --- crypto/echainiv.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'crypto/echainiv.c') diff --git a/crypto/echainiv.c b/crypto/echainiv.c index b6e43dc6..d3896c7e 100644 --- a/crypto/echainiv.c +++ b/crypto/echainiv.c @@ -145,8 +145,8 @@ static int echainiv_encrypt(struct aead_request *req) aead_request_set_callback(subreq, req->base.flags, compl, data); aead_request_set_crypt(subreq, req->dst, req->dst, - req->cryptlen - ivsize, info); - aead_request_set_ad(subreq, req->assoclen + ivsize); + req->cryptlen, info); + aead_request_set_ad(subreq, req->assoclen); crypto_xor(info, ctx->salt, ivsize); scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1); @@ -166,7 +166,7 @@ static int echainiv_decrypt(struct aead_request *req) void *data; unsigned int ivsize = crypto_aead_ivsize(geniv); - if (req->cryptlen < ivsize + crypto_aead_authsize(geniv)) + if (req->cryptlen < ivsize) return -EINVAL; aead_request_set_tfm(subreq, ctx->geniv.child); @@ -180,16 +180,12 @@ static int echainiv_decrypt(struct aead_request *req) aead_request_set_ad(subreq, req->assoclen + ivsize); scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0); - if (req->src != req->dst) - scatterwalk_map_and_copy(req->iv, req->dst, - req->assoclen, ivsize, 1); return crypto_aead_decrypt(subreq); } -static int echainiv_init(struct crypto_tfm *tfm) +static int echainiv_init(struct crypto_aead *geniv) { - struct crypto_aead *geniv = __crypto_aead_cast(tfm); struct echainiv_ctx *ctx = crypto_aead_ctx(geniv); int err; @@ -212,7 +208,7 @@ static int echainiv_init(struct crypto_tfm *tfm) if (IS_ERR(ctx->null)) goto out; - err = aead_geniv_init(tfm); + err = aead_geniv_init(crypto_aead_tfm(geniv)); if (err) goto drop_null; @@ -227,9 +223,9 @@ drop_null: goto out; } -static void echainiv_exit(struct crypto_tfm *tfm) +static void echainiv_exit(struct crypto_aead *tfm) { - struct echainiv_ctx *ctx = crypto_tfm_ctx(tfm); + struct echainiv_ctx *ctx = crypto_aead_ctx(tfm); crypto_free_aead(ctx->geniv.child); crypto_put_default_null_skcipher(); @@ -262,13 +258,15 @@ static int echainiv_aead_create(struct crypto_template *tmpl, inst->alg.encrypt = echainiv_encrypt; inst->alg.decrypt = echainiv_decrypt; - inst->alg.base.cra_init = echainiv_init; - inst->alg.base.cra_exit = echainiv_exit; + inst->alg.init = echainiv_init; + inst->alg.exit = echainiv_exit; inst->alg.base.cra_alignmask |= __alignof__(u32) - 1; inst->alg.base.cra_ctxsize = sizeof(struct echainiv_ctx); inst->alg.base.cra_ctxsize += inst->alg.ivsize; + inst->free = aead_geniv_free; + done: err = aead_register_instance(tmpl, inst); if (err) -- cgit v1.2.3 From 52a08691eb960af2c36ffe4fe1f001eed07cde1f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 13 Aug 2015 17:28:56 +0800 Subject: crypto: echainiv - Remove AEAD compatibility code Now that we no longer have any legacy AEAD implementations the compatibility code path can no longer be triggered. This patch removes it. Signed-off-by: Herbert Xu --- crypto/echainiv.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'crypto/echainiv.c') diff --git a/crypto/echainiv.c b/crypto/echainiv.c index d3896c7e..806ebe73 100644 --- a/crypto/echainiv.c +++ b/crypto/echainiv.c @@ -247,9 +247,6 @@ static int echainiv_aead_create(struct crypto_template *tmpl, spawn = aead_instance_ctx(inst); alg = crypto_spawn_aead_alg(spawn); - if (alg->base.cra_aead.encrypt) - goto done; - err = -EINVAL; if (inst->alg.ivsize & (sizeof(u32) - 1) || inst->alg.ivsize > MAX_IV_SIZE) @@ -267,7 +264,6 @@ static int echainiv_aead_create(struct crypto_template *tmpl, inst->free = aead_geniv_free; -done: err = aead_register_instance(tmpl, inst); if (err) goto free_inst; -- cgit v1.2.3 From a7d52c0d945730ef4f0677f64dbe7439eec1de59 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 13 Aug 2015 17:29:01 +0800 Subject: crypto: echainiv - Use generic geniv init/exit helpers This patch replaces the echainiv init/exit handlers with the generic geniv helpers. Signed-off-by: Herbert Xu --- crypto/echainiv.c | 70 ++++++------------------------------------------------- 1 file changed, 7 insertions(+), 63 deletions(-) (limited to 'crypto/echainiv.c') diff --git a/crypto/echainiv.c b/crypto/echainiv.c index 806ebe73..b96a8456 100644 --- a/crypto/echainiv.c +++ b/crypto/echainiv.c @@ -19,8 +19,6 @@ */ #include -#include -#include #include #include #include @@ -33,13 +31,6 @@ #define MAX_IV_SIZE 16 -struct echainiv_ctx { - /* aead_geniv_ctx must be first the element */ - struct aead_geniv_ctx geniv; - struct crypto_blkcipher *null; - u8 salt[] __attribute__ ((aligned(__alignof__(u32)))); -}; - static DEFINE_PER_CPU(u32 [MAX_IV_SIZE / sizeof(u32)], echainiv_iv); /* We don't care if we get preempted and read/write IVs from the next CPU. */ @@ -103,7 +94,7 @@ static void echainiv_encrypt_complete(struct crypto_async_request *base, static int echainiv_encrypt(struct aead_request *req) { struct crypto_aead *geniv = crypto_aead_reqtfm(req); - struct echainiv_ctx *ctx = crypto_aead_ctx(geniv); + struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); struct aead_request *subreq = aead_request_ctx(req); crypto_completion_t compl; void *data; @@ -114,7 +105,7 @@ static int echainiv_encrypt(struct aead_request *req) if (req->cryptlen < ivsize) return -EINVAL; - aead_request_set_tfm(subreq, ctx->geniv.child); + aead_request_set_tfm(subreq, ctx->child); compl = echainiv_encrypt_complete; data = req; @@ -160,7 +151,7 @@ static int echainiv_encrypt(struct aead_request *req) static int echainiv_decrypt(struct aead_request *req) { struct crypto_aead *geniv = crypto_aead_reqtfm(req); - struct echainiv_ctx *ctx = crypto_aead_ctx(geniv); + struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv); struct aead_request *subreq = aead_request_ctx(req); crypto_completion_t compl; void *data; @@ -169,7 +160,7 @@ static int echainiv_decrypt(struct aead_request *req) if (req->cryptlen < ivsize) return -EINVAL; - aead_request_set_tfm(subreq, ctx->geniv.child); + aead_request_set_tfm(subreq, ctx->child); compl = req->base.complete; data = req->base.data; @@ -184,53 +175,6 @@ static int echainiv_decrypt(struct aead_request *req) return crypto_aead_decrypt(subreq); } -static int echainiv_init(struct crypto_aead *geniv) -{ - struct echainiv_ctx *ctx = crypto_aead_ctx(geniv); - int err; - - spin_lock_init(&ctx->geniv.lock); - - crypto_aead_set_reqsize(geniv, sizeof(struct aead_request)); - - err = crypto_get_default_rng(); - if (err) - goto out; - - err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, - crypto_aead_ivsize(geniv)); - crypto_put_default_rng(); - if (err) - goto out; - - ctx->null = crypto_get_default_null_skcipher(); - err = PTR_ERR(ctx->null); - if (IS_ERR(ctx->null)) - goto out; - - err = aead_geniv_init(crypto_aead_tfm(geniv)); - if (err) - goto drop_null; - - ctx->geniv.child = geniv->child; - geniv->child = geniv; - -out: - return err; - -drop_null: - crypto_put_default_null_skcipher(); - goto out; -} - -static void echainiv_exit(struct crypto_aead *tfm) -{ - struct echainiv_ctx *ctx = crypto_aead_ctx(tfm); - - crypto_free_aead(ctx->geniv.child); - crypto_put_default_null_skcipher(); -} - static int echainiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb) { @@ -255,11 +199,11 @@ static int echainiv_aead_create(struct crypto_template *tmpl, inst->alg.encrypt = echainiv_encrypt; inst->alg.decrypt = echainiv_decrypt; - inst->alg.init = echainiv_init; - inst->alg.exit = echainiv_exit; + inst->alg.init = aead_init_geniv; + inst->alg.exit = aead_exit_geniv; inst->alg.base.cra_alignmask |= __alignof__(u32) - 1; - inst->alg.base.cra_ctxsize = sizeof(struct echainiv_ctx); + inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx); inst->alg.base.cra_ctxsize += inst->alg.ivsize; inst->free = aead_geniv_free; -- cgit v1.2.3