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

crypto: adiantum - use crypto_grab_{cipher,shash} and simplify error paths



Make the adiantum template use the new functions crypto_grab_cipher()
and crypto_grab_shash() to initialize its cipher and shash spawns.

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 0764ac28
Loading
Loading
Loading
Loading
+25 −60
Original line number Diff line number Diff line
@@ -39,8 +39,6 @@
#include <crypto/scatterwalk.h>
#include <linux/module.h>

#include "internal.h"

/*
 * Size of right-hand part of input data, in bytes; also the size of the block
 * cipher's block size and the hash function's output.
@@ -64,7 +62,7 @@

struct adiantum_instance_ctx {
	struct crypto_skcipher_spawn streamcipher_spawn;
	struct crypto_spawn blockcipher_spawn;
	struct crypto_cipher_spawn blockcipher_spawn;
	struct crypto_shash_spawn hash_spawn;
};

@@ -410,7 +408,7 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm)
	if (IS_ERR(streamcipher))
		return PTR_ERR(streamcipher);

	blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn);
	blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn.base);
	if (IS_ERR(blockcipher)) {
		err = PTR_ERR(blockcipher);
		goto err_free_streamcipher;
@@ -461,7 +459,7 @@ static void adiantum_free_instance(struct skcipher_instance *inst)
	struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst);

	crypto_drop_skcipher(&ictx->streamcipher_spawn);
	crypto_drop_spawn(&ictx->blockcipher_spawn);
	crypto_drop_cipher(&ictx->blockcipher_spawn);
	crypto_drop_shash(&ictx->hash_spawn);
	kfree(inst);
}
@@ -494,14 +492,11 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
{
	struct crypto_attr_type *algt;
	u32 mask;
	const char *streamcipher_name;
	const char *blockcipher_name;
	const char *nhpoly1305_name;
	struct skcipher_instance *inst;
	struct adiantum_instance_ctx *ictx;
	struct skcipher_alg *streamcipher_alg;
	struct crypto_alg *blockcipher_alg;
	struct crypto_alg *_hash_alg;
	struct shash_alg *hash_alg;
	int err;

@@ -514,20 +509,6 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)

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

	streamcipher_name = crypto_attr_alg_name(tb[1]);
	if (IS_ERR(streamcipher_name))
		return PTR_ERR(streamcipher_name);

	blockcipher_name = crypto_attr_alg_name(tb[2]);
	if (IS_ERR(blockcipher_name))
		return PTR_ERR(blockcipher_name);

	nhpoly1305_name = crypto_attr_alg_name(tb[3]);
	if (nhpoly1305_name == ERR_PTR(-ENOENT))
		nhpoly1305_name = "nhpoly1305";
	if (IS_ERR(nhpoly1305_name))
		return PTR_ERR(nhpoly1305_name);

	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
	if (!inst)
		return -ENOMEM;
@@ -536,33 +517,29 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
	/* Stream cipher, e.g. "xchacha12" */
	err = crypto_grab_skcipher(&ictx->streamcipher_spawn,
				   skcipher_crypto_instance(inst),
				   streamcipher_name, 0, mask);
				   crypto_attr_alg_name(tb[1]), 0, mask);
	if (err)
		goto out_free_inst;
		goto err_free_inst;
	streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn);

	/* Block cipher, e.g. "aes" */
	err = crypto_grab_spawn(&ictx->blockcipher_spawn,
	err = crypto_grab_cipher(&ictx->blockcipher_spawn,
				 skcipher_crypto_instance(inst),
				blockcipher_name,
				CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK);
				 crypto_attr_alg_name(tb[2]), 0, mask);
	if (err)
		goto out_drop_streamcipher;
	blockcipher_alg = ictx->blockcipher_spawn.alg;
		goto err_free_inst;
	blockcipher_alg = crypto_spawn_cipher_alg(&ictx->blockcipher_spawn);

	/* NHPoly1305 ε-∆U hash function */
	_hash_alg = crypto_alg_mod_lookup(nhpoly1305_name,
					  CRYPTO_ALG_TYPE_SHASH,
					  CRYPTO_ALG_TYPE_MASK);
	if (IS_ERR(_hash_alg)) {
		err = PTR_ERR(_hash_alg);
		goto out_drop_blockcipher;
	}
	hash_alg = __crypto_shash_alg(_hash_alg);
	err = crypto_init_shash_spawn(&ictx->hash_spawn, hash_alg,
				      skcipher_crypto_instance(inst));
	nhpoly1305_name = crypto_attr_alg_name(tb[3]);
	if (nhpoly1305_name == ERR_PTR(-ENOENT))
		nhpoly1305_name = "nhpoly1305";
	err = crypto_grab_shash(&ictx->hash_spawn,
				skcipher_crypto_instance(inst),
				nhpoly1305_name, 0, mask);
	if (err)
		goto out_put_hash;
		goto err_free_inst;
	hash_alg = crypto_spawn_shash_alg(&ictx->hash_spawn);

	/* Check the set of algorithms */
	if (!adiantum_supported_algorithms(streamcipher_alg, blockcipher_alg,
@@ -571,7 +548,7 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
			streamcipher_alg->base.cra_name,
			blockcipher_alg->cra_name, hash_alg->base.cra_name);
		err = -EINVAL;
		goto out_drop_hash;
		goto err_free_inst;
	}

	/* Instance fields */
@@ -580,13 +557,13 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
		     "adiantum(%s,%s)", streamcipher_alg->base.cra_name,
		     blockcipher_alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
		goto out_drop_hash;
		goto err_free_inst;
	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
		     "adiantum(%s,%s,%s)",
		     streamcipher_alg->base.cra_driver_name,
		     blockcipher_alg->cra_driver_name,
		     hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
		goto out_drop_hash;
		goto err_free_inst;

	inst->alg.base.cra_flags = streamcipher_alg->base.cra_flags &
				   CRYPTO_ALG_ASYNC;
@@ -616,22 +593,10 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
	inst->free = adiantum_free_instance;

	err = skcipher_register_instance(tmpl, inst);
	if (err)
		goto out_drop_hash;

	crypto_mod_put(_hash_alg);
	return 0;

out_drop_hash:
	crypto_drop_shash(&ictx->hash_spawn);
out_put_hash:
	crypto_mod_put(_hash_alg);
out_drop_blockcipher:
	crypto_drop_spawn(&ictx->blockcipher_spawn);
out_drop_streamcipher:
	crypto_drop_skcipher(&ictx->streamcipher_spawn);
out_free_inst:
	kfree(inst);
	if (err) {
err_free_inst:
		adiantum_free_instance(inst);
	}
	return err;
}