Commit c282586f authored by Eric Biggers's avatar Eric Biggers Committed by Herbert Xu
Browse files

crypto: chacha20poly1305 - use crypto_grab_ahash() and simplify error paths



Make the rfc7539 and rfc7539esp templates use the new function
crypto_grab_ahash() to initialize their ahash spawn.

This is needed to make all spawns be initialized in a consistent way.

Also simplify the error handling by taking advantage of crypto_drop_*()
now accepting (as a no-op) spawns that haven't been initialized yet, and
by taking advantage of crypto_grab_*() now handling ERR_PTR() names.

Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 05b3bbb5
Loading
Loading
Loading
Loading
+27 −57
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@
#include <linux/kernel.h>
#include <linux/module.h>

#include "internal.h"

struct chachapoly_instance_ctx {
	struct crypto_skcipher_spawn chacha;
	struct crypto_ahash_spawn poly;
@@ -560,11 +558,9 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
	struct crypto_attr_type *algt;
	u32 mask;
	struct aead_instance *inst;
	struct skcipher_alg *chacha;
	struct crypto_alg *poly;
	struct hash_alg_common *poly_hash;
	struct chachapoly_instance_ctx *ctx;
	const char *chacha_name, *poly_name;
	struct skcipher_alg *chacha;
	struct hash_alg_common *poly;
	int err;

	if (ivsize > CHACHAPOLY_IV_SIZE)
@@ -579,68 +575,51 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,

	mask = crypto_requires_sync(algt->type, algt->mask);

	chacha_name = crypto_attr_alg_name(tb[1]);
	if (IS_ERR(chacha_name))
		return PTR_ERR(chacha_name);
	poly_name = crypto_attr_alg_name(tb[2]);
	if (IS_ERR(poly_name))
		return PTR_ERR(poly_name);

	poly = crypto_find_alg(poly_name, &crypto_ahash_type,
			       CRYPTO_ALG_TYPE_HASH,
			       CRYPTO_ALG_TYPE_AHASH_MASK | mask);
	if (IS_ERR(poly))
		return PTR_ERR(poly);
	poly_hash = __crypto_hash_alg_common(poly);

	err = -EINVAL;
	if (poly_hash->digestsize != POLY1305_DIGEST_SIZE)
		goto out_put_poly;

	err = -ENOMEM;
	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
	if (!inst)
		goto out_put_poly;

		return -ENOMEM;
	ctx = aead_instance_ctx(inst);
	ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize;
	err = crypto_init_ahash_spawn(&ctx->poly, poly_hash,
				      aead_crypto_instance(inst));
	if (err)
		goto err_free_inst;

	err = crypto_grab_skcipher(&ctx->chacha, aead_crypto_instance(inst),
				   chacha_name, 0, mask);
				   crypto_attr_alg_name(tb[1]), 0, mask);
	if (err)
		goto err_drop_poly;

		goto err_free_inst;
	chacha = crypto_spawn_skcipher_alg(&ctx->chacha);

	err = crypto_grab_ahash(&ctx->poly, aead_crypto_instance(inst),
				crypto_attr_alg_name(tb[2]), 0, mask);
	if (err)
		goto err_free_inst;
	poly = crypto_spawn_ahash_alg(&ctx->poly);

	err = -EINVAL;
	if (poly->digestsize != POLY1305_DIGEST_SIZE)
		goto err_free_inst;
	/* Need 16-byte IV size, including Initial Block Counter value */
	if (crypto_skcipher_alg_ivsize(chacha) != CHACHA_IV_SIZE)
		goto out_drop_chacha;
		goto err_free_inst;
	/* Not a stream cipher? */
	if (chacha->base.cra_blocksize != 1)
		goto out_drop_chacha;
		goto err_free_inst;

	err = -ENAMETOOLONG;
	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
		     "%s(%s,%s)", name, chacha->base.cra_name,
		     poly->cra_name) >= CRYPTO_MAX_ALG_NAME)
		goto out_drop_chacha;
		     poly->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
		goto err_free_inst;
	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
		     "%s(%s,%s)", name, chacha->base.cra_driver_name,
		     poly->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
		goto out_drop_chacha;
		     poly->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
		goto err_free_inst;

	inst->alg.base.cra_flags = (chacha->base.cra_flags | poly->cra_flags) &
				   CRYPTO_ALG_ASYNC;
	inst->alg.base.cra_flags = (chacha->base.cra_flags |
				    poly->base.cra_flags) & CRYPTO_ALG_ASYNC;
	inst->alg.base.cra_priority = (chacha->base.cra_priority +
				       poly->cra_priority) / 2;
				       poly->base.cra_priority) / 2;
	inst->alg.base.cra_blocksize = 1;
	inst->alg.base.cra_alignmask = chacha->base.cra_alignmask |
				       poly->cra_alignmask;
				       poly->base.cra_alignmask;
	inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) +
				     ctx->saltlen;
	inst->alg.ivsize = ivsize;
@@ -656,20 +635,11 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
	inst->free = chachapoly_free;

	err = aead_register_instance(tmpl, inst);
	if (err)
		goto out_drop_chacha;

out_put_poly:
	crypto_mod_put(poly);
	return err;

out_drop_chacha:
	crypto_drop_skcipher(&ctx->chacha);
err_drop_poly:
	crypto_drop_ahash(&ctx->poly);
	if (err) {
err_free_inst:
	kfree(inst);
	goto out_put_poly;
		chachapoly_free(inst);
	}
	return err;
}

static int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb)