Commit f1440a90 authored by Herbert Xu's avatar Herbert Xu
Browse files

crypto: api - Add support for duplicating algorithms before registration



If the bit CRYPTO_ALG_DUP_FIRST is set, an algorithm will be
duplicated by kmemdup before registration.  This is inteded for
hardware-based algorithms that may be unplugged at will.

Do not use this if the algorithm data structure is embedded in a
bigger data structure.  Perform the duplication in the driver
instead.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 66fecd9d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -150,6 +150,7 @@ static const struct crypto_type crypto_acomp_type = {
	.maskset = CRYPTO_ALG_TYPE_ACOMPRESS_MASK,
	.type = CRYPTO_ALG_TYPE_ACOMPRESS,
	.tfmsize = offsetof(struct crypto_acomp, base),
	.algsize = offsetof(struct acomp_alg, base),
};

struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type,
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ static const struct crypto_type crypto_aead_type = {
	.maskset = CRYPTO_ALG_TYPE_MASK,
	.type = CRYPTO_ALG_TYPE_AEAD,
	.tfmsize = offsetof(struct crypto_aead, base),
	.algsize = offsetof(struct aead_alg, base),
};

int crypto_grab_aead(struct crypto_aead_spawn *spawn,
+1 −0
Original line number Diff line number Diff line
@@ -792,6 +792,7 @@ static const struct crypto_type crypto_ahash_type = {
	.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
	.type = CRYPTO_ALG_TYPE_AHASH,
	.tfmsize = offsetof(struct crypto_ahash, base),
	.algsize = offsetof(struct ahash_alg, halg.base),
};

int crypto_grab_ahash(struct crypto_ahash_spawn *spawn,
+1 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ static const struct crypto_type crypto_akcipher_type = {
	.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
	.type = CRYPTO_ALG_TYPE_AKCIPHER,
	.tfmsize = offsetof(struct crypto_akcipher, base),
	.algsize = offsetof(struct akcipher_alg, base),
};

int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn,
+28 −13
Original line number Diff line number Diff line
@@ -66,13 +66,7 @@ static int crypto_check_alg(struct crypto_alg *alg)

static void crypto_free_instance(struct crypto_instance *inst)
{
	struct crypto_alg *alg = &inst->alg;
	const struct crypto_type *type;

	type = alg->cra_type;
	if (type->destroy)
		type->destroy(alg);
	type->free(inst);
	inst->alg.cra_type->free(inst);
}

static void crypto_destroy_instance_workfn(struct work_struct *w)
@@ -424,6 +418,15 @@ void crypto_remove_final(struct list_head *list)
}
EXPORT_SYMBOL_GPL(crypto_remove_final);

static void crypto_free_alg(struct crypto_alg *alg)
{
	unsigned int algsize = alg->cra_type->algsize;
	u8 *p = (u8 *)alg - algsize;

	crypto_destroy_alg(alg);
	kfree(p);
}

int crypto_register_alg(struct crypto_alg *alg)
{
	struct crypto_larval *larval;
@@ -436,6 +439,19 @@ int crypto_register_alg(struct crypto_alg *alg)
	if (err)
		return err;

	if (alg->cra_flags & CRYPTO_ALG_DUP_FIRST &&
	    !WARN_ON_ONCE(alg->cra_destroy)) {
		unsigned int algsize = alg->cra_type->algsize;
		u8 *p = (u8 *)alg - algsize;

		p = kmemdup(p, algsize + sizeof(*alg), GFP_KERNEL);
		if (!p)
			return -ENOMEM;

		alg = (void *)(p + algsize);
		alg->cra_destroy = crypto_free_alg;
	}

	down_write(&crypto_alg_sem);
	larval = __crypto_register_alg(alg, &algs_to_put);
	if (!IS_ERR_OR_NULL(larval)) {
@@ -444,8 +460,10 @@ int crypto_register_alg(struct crypto_alg *alg)
	}
	up_write(&crypto_alg_sem);

	if (IS_ERR(larval))
	if (IS_ERR(larval)) {
		crypto_alg_put(alg);
		return PTR_ERR(larval);
	}

	if (test_started)
		crypto_schedule_test(larval);
@@ -481,12 +499,9 @@ void crypto_unregister_alg(struct crypto_alg *alg)
	if (WARN(ret, "Algorithm %s is not registered", alg->cra_driver_name))
		return;

	if (alg->cra_destroy)
		crypto_alg_put(alg);
	else if (!WARN_ON(refcount_read(&alg->cra_refcnt) != 1) &&
		 alg->cra_type && alg->cra_type->destroy)
		alg->cra_type->destroy(alg);
	WARN_ON(!alg->cra_destroy && refcount_read(&alg->cra_refcnt) != 1);

	list_add(&alg->cra_list, &list);
	crypto_remove_final(&list);
}
EXPORT_SYMBOL_GPL(crypto_unregister_alg);
Loading