18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Scatterlist Cryptographic API.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
68c2ecf20Sopenharmony_ci * Copyright (c) 2002 David S. Miller (davem@redhat.com)
78c2ecf20Sopenharmony_ci * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
108c2ecf20Sopenharmony_ci * and Nettle, by Niels Möller.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/err.h>
148c2ecf20Sopenharmony_ci#include <linux/errno.h>
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/kmod.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/param.h>
198c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
208c2ecf20Sopenharmony_ci#include <linux/slab.h>
218c2ecf20Sopenharmony_ci#include <linux/string.h>
228c2ecf20Sopenharmony_ci#include <linux/completion.h>
238c2ecf20Sopenharmony_ci#include "internal.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ciLIST_HEAD(crypto_alg_list);
268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alg_list);
278c2ecf20Sopenharmony_ciDECLARE_RWSEM(crypto_alg_sem);
288c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alg_sem);
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ciBLOCKING_NOTIFIER_HEAD(crypto_chain);
318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_chain);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistruct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL;
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_mod_get);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_civoid crypto_mod_put(struct crypto_alg *alg)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	struct module *module = alg->cra_module;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	crypto_alg_put(alg);
468c2ecf20Sopenharmony_ci	module_put(module);
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_mod_put);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic inline int crypto_is_test_larval(struct crypto_larval *larval)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	return larval->alg.cra_driver_name[0];
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
568c2ecf20Sopenharmony_ci					      u32 mask)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	struct crypto_alg *q, *alg = NULL;
598c2ecf20Sopenharmony_ci	int best = -2;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	list_for_each_entry(q, &crypto_alg_list, cra_list) {
628c2ecf20Sopenharmony_ci		int exact, fuzzy;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci		if (crypto_is_moribund(q))
658c2ecf20Sopenharmony_ci			continue;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci		if ((q->cra_flags ^ type) & mask)
688c2ecf20Sopenharmony_ci			continue;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci		if (crypto_is_larval(q) &&
718c2ecf20Sopenharmony_ci		    !crypto_is_test_larval((struct crypto_larval *)q) &&
728c2ecf20Sopenharmony_ci		    ((struct crypto_larval *)q)->mask != mask)
738c2ecf20Sopenharmony_ci			continue;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci		exact = !strcmp(q->cra_driver_name, name);
768c2ecf20Sopenharmony_ci		fuzzy = !strcmp(q->cra_name, name);
778c2ecf20Sopenharmony_ci		if (!exact && !(fuzzy && q->cra_priority > best))
788c2ecf20Sopenharmony_ci			continue;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci		if (unlikely(!crypto_mod_get(q)))
818c2ecf20Sopenharmony_ci			continue;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci		best = q->cra_priority;
848c2ecf20Sopenharmony_ci		if (alg)
858c2ecf20Sopenharmony_ci			crypto_mod_put(alg);
868c2ecf20Sopenharmony_ci		alg = q;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci		if (exact)
898c2ecf20Sopenharmony_ci			break;
908c2ecf20Sopenharmony_ci	}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	return alg;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic void crypto_larval_destroy(struct crypto_alg *alg)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	struct crypto_larval *larval = (void *)alg;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	BUG_ON(!crypto_is_larval(alg));
1008c2ecf20Sopenharmony_ci	if (!IS_ERR_OR_NULL(larval->adult))
1018c2ecf20Sopenharmony_ci		crypto_mod_put(larval->adult);
1028c2ecf20Sopenharmony_ci	kfree(larval);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistruct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	struct crypto_larval *larval;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	larval = kzalloc(sizeof(*larval), GFP_KERNEL);
1108c2ecf20Sopenharmony_ci	if (!larval)
1118c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	larval->mask = mask;
1148c2ecf20Sopenharmony_ci	larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type;
1158c2ecf20Sopenharmony_ci	larval->alg.cra_priority = -1;
1168c2ecf20Sopenharmony_ci	larval->alg.cra_destroy = crypto_larval_destroy;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
1198c2ecf20Sopenharmony_ci	init_completion(&larval->completion);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	return larval;
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_larval_alloc);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic struct crypto_alg *crypto_larval_add(const char *name, u32 type,
1268c2ecf20Sopenharmony_ci					    u32 mask)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
1298c2ecf20Sopenharmony_ci	struct crypto_larval *larval;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	larval = crypto_larval_alloc(name, type, mask);
1328c2ecf20Sopenharmony_ci	if (IS_ERR(larval))
1338c2ecf20Sopenharmony_ci		return ERR_CAST(larval);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	refcount_set(&larval->alg.cra_refcnt, 2);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	down_write(&crypto_alg_sem);
1388c2ecf20Sopenharmony_ci	alg = __crypto_alg_lookup(name, type, mask);
1398c2ecf20Sopenharmony_ci	if (!alg) {
1408c2ecf20Sopenharmony_ci		alg = &larval->alg;
1418c2ecf20Sopenharmony_ci		list_add(&alg->cra_list, &crypto_alg_list);
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci	up_write(&crypto_alg_sem);
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	if (alg != &larval->alg) {
1468c2ecf20Sopenharmony_ci		kfree(larval);
1478c2ecf20Sopenharmony_ci		if (crypto_is_larval(alg))
1488c2ecf20Sopenharmony_ci			alg = crypto_larval_wait(alg);
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	return alg;
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_civoid crypto_larval_kill(struct crypto_alg *alg)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	struct crypto_larval *larval = (void *)alg;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	down_write(&crypto_alg_sem);
1598c2ecf20Sopenharmony_ci	list_del(&alg->cra_list);
1608c2ecf20Sopenharmony_ci	up_write(&crypto_alg_sem);
1618c2ecf20Sopenharmony_ci	complete_all(&larval->completion);
1628c2ecf20Sopenharmony_ci	crypto_alg_put(alg);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_larval_kill);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct crypto_larval *larval = (void *)alg;
1698c2ecf20Sopenharmony_ci	long timeout;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	timeout = wait_for_completion_killable_timeout(
1728c2ecf20Sopenharmony_ci		&larval->completion, 60 * HZ);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	alg = larval->adult;
1758c2ecf20Sopenharmony_ci	if (timeout < 0)
1768c2ecf20Sopenharmony_ci		alg = ERR_PTR(-EINTR);
1778c2ecf20Sopenharmony_ci	else if (!timeout)
1788c2ecf20Sopenharmony_ci		alg = ERR_PTR(-ETIMEDOUT);
1798c2ecf20Sopenharmony_ci	else if (!alg)
1808c2ecf20Sopenharmony_ci		alg = ERR_PTR(-ENOENT);
1818c2ecf20Sopenharmony_ci	else if (IS_ERR(alg))
1828c2ecf20Sopenharmony_ci		;
1838c2ecf20Sopenharmony_ci	else if (crypto_is_test_larval(larval) &&
1848c2ecf20Sopenharmony_ci		 !(alg->cra_flags & CRYPTO_ALG_TESTED))
1858c2ecf20Sopenharmony_ci		alg = ERR_PTR(-EAGAIN);
1868c2ecf20Sopenharmony_ci	else if (!crypto_mod_get(alg))
1878c2ecf20Sopenharmony_ci		alg = ERR_PTR(-EAGAIN);
1888c2ecf20Sopenharmony_ci	crypto_mod_put(&larval->alg);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	return alg;
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
1948c2ecf20Sopenharmony_ci					    u32 mask)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
1978c2ecf20Sopenharmony_ci	u32 test = 0;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (!((type | mask) & CRYPTO_ALG_TESTED))
2008c2ecf20Sopenharmony_ci		test |= CRYPTO_ALG_TESTED;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	down_read(&crypto_alg_sem);
2038c2ecf20Sopenharmony_ci	alg = __crypto_alg_lookup(name, type | test, mask | test);
2048c2ecf20Sopenharmony_ci	if (!alg && test) {
2058c2ecf20Sopenharmony_ci		alg = __crypto_alg_lookup(name, type, mask);
2068c2ecf20Sopenharmony_ci		if (alg && !crypto_is_larval(alg)) {
2078c2ecf20Sopenharmony_ci			/* Test failed */
2088c2ecf20Sopenharmony_ci			crypto_mod_put(alg);
2098c2ecf20Sopenharmony_ci			alg = ERR_PTR(-ELIBBAD);
2108c2ecf20Sopenharmony_ci		}
2118c2ecf20Sopenharmony_ci	}
2128c2ecf20Sopenharmony_ci	up_read(&crypto_alg_sem);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	return alg;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic struct crypto_alg *crypto_larval_lookup(const char *name, u32 type,
2188c2ecf20Sopenharmony_ci					       u32 mask)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	if (!name)
2238c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOENT);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	type &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
2268c2ecf20Sopenharmony_ci	mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	alg = crypto_alg_lookup(name, type, mask);
2298c2ecf20Sopenharmony_ci	if (!alg && !(mask & CRYPTO_NOLOAD)) {
2308c2ecf20Sopenharmony_ci		request_module("crypto-%s", name);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci		if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
2338c2ecf20Sopenharmony_ci		      CRYPTO_ALG_NEED_FALLBACK))
2348c2ecf20Sopenharmony_ci			request_module("crypto-%s-all", name);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci		alg = crypto_alg_lookup(name, type, mask);
2378c2ecf20Sopenharmony_ci	}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	if (!IS_ERR_OR_NULL(alg) && crypto_is_larval(alg))
2408c2ecf20Sopenharmony_ci		alg = crypto_larval_wait(alg);
2418c2ecf20Sopenharmony_ci	else if (!alg)
2428c2ecf20Sopenharmony_ci		alg = crypto_larval_add(name, type, mask);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	return alg;
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ciint crypto_probing_notify(unsigned long val, void *v)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	int ok;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	ok = blocking_notifier_call_chain(&crypto_chain, val, v);
2528c2ecf20Sopenharmony_ci	if (ok == NOTIFY_DONE) {
2538c2ecf20Sopenharmony_ci		request_module("cryptomgr");
2548c2ecf20Sopenharmony_ci		ok = blocking_notifier_call_chain(&crypto_chain, val, v);
2558c2ecf20Sopenharmony_ci	}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	return ok;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_probing_notify);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistruct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
2648c2ecf20Sopenharmony_ci	struct crypto_alg *larval;
2658c2ecf20Sopenharmony_ci	int ok;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	/*
2688c2ecf20Sopenharmony_ci	 * If the internal flag is set for a cipher, require a caller to
2698c2ecf20Sopenharmony_ci	 * to invoke the cipher with the internal flag to use that cipher.
2708c2ecf20Sopenharmony_ci	 * Also, if a caller wants to allocate a cipher that may or may
2718c2ecf20Sopenharmony_ci	 * not be an internal cipher, use type | CRYPTO_ALG_INTERNAL and
2728c2ecf20Sopenharmony_ci	 * !(mask & CRYPTO_ALG_INTERNAL).
2738c2ecf20Sopenharmony_ci	 */
2748c2ecf20Sopenharmony_ci	if (!((type | mask) & CRYPTO_ALG_INTERNAL))
2758c2ecf20Sopenharmony_ci		mask |= CRYPTO_ALG_INTERNAL;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	larval = crypto_larval_lookup(name, type, mask);
2788c2ecf20Sopenharmony_ci	if (IS_ERR(larval) || !crypto_is_larval(larval))
2798c2ecf20Sopenharmony_ci		return larval;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	if (ok == NOTIFY_STOP)
2848c2ecf20Sopenharmony_ci		alg = crypto_larval_wait(larval);
2858c2ecf20Sopenharmony_ci	else {
2868c2ecf20Sopenharmony_ci		crypto_mod_put(larval);
2878c2ecf20Sopenharmony_ci		alg = ERR_PTR(-ENOENT);
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci	crypto_larval_kill(larval);
2908c2ecf20Sopenharmony_ci	return alg;
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	if (type_obj)
2998c2ecf20Sopenharmony_ci		return type_obj->init(tfm, type, mask);
3008c2ecf20Sopenharmony_ci	return 0;
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic void crypto_exit_ops(struct crypto_tfm *tfm)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	const struct crypto_type *type = tfm->__crt_alg->cra_type;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (type && tfm->exit)
3088c2ecf20Sopenharmony_ci		tfm->exit(tfm);
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	const struct crypto_type *type_obj = alg->cra_type;
3148c2ecf20Sopenharmony_ci	unsigned int len;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
3178c2ecf20Sopenharmony_ci	if (type_obj)
3188c2ecf20Sopenharmony_ci		return len + type_obj->ctxsize(alg, type, mask);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
3218c2ecf20Sopenharmony_ci	default:
3228c2ecf20Sopenharmony_ci		BUG();
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_CIPHER:
3258c2ecf20Sopenharmony_ci		len += crypto_cipher_ctxsize(alg);
3268c2ecf20Sopenharmony_ci		break;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_COMPRESS:
3298c2ecf20Sopenharmony_ci		len += crypto_compress_ctxsize(alg);
3308c2ecf20Sopenharmony_ci		break;
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	return len;
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_civoid crypto_shoot_alg(struct crypto_alg *alg)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	down_write(&crypto_alg_sem);
3398c2ecf20Sopenharmony_ci	alg->cra_flags |= CRYPTO_ALG_DYING;
3408c2ecf20Sopenharmony_ci	up_write(&crypto_alg_sem);
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_shoot_alg);
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_cistruct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
3458c2ecf20Sopenharmony_ci				      u32 mask)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = NULL;
3488c2ecf20Sopenharmony_ci	unsigned int tfm_size;
3498c2ecf20Sopenharmony_ci	int err = -ENOMEM;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
3528c2ecf20Sopenharmony_ci	tfm = kzalloc(tfm_size, GFP_KERNEL);
3538c2ecf20Sopenharmony_ci	if (tfm == NULL)
3548c2ecf20Sopenharmony_ci		goto out_err;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	tfm->__crt_alg = alg;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	err = crypto_init_ops(tfm, type, mask);
3598c2ecf20Sopenharmony_ci	if (err)
3608c2ecf20Sopenharmony_ci		goto out_free_tfm;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
3638c2ecf20Sopenharmony_ci		goto cra_init_failed;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	goto out;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cicra_init_failed:
3688c2ecf20Sopenharmony_ci	crypto_exit_ops(tfm);
3698c2ecf20Sopenharmony_ciout_free_tfm:
3708c2ecf20Sopenharmony_ci	if (err == -EAGAIN)
3718c2ecf20Sopenharmony_ci		crypto_shoot_alg(alg);
3728c2ecf20Sopenharmony_ci	kfree(tfm);
3738c2ecf20Sopenharmony_ciout_err:
3748c2ecf20Sopenharmony_ci	tfm = ERR_PTR(err);
3758c2ecf20Sopenharmony_ciout:
3768c2ecf20Sopenharmony_ci	return tfm;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci/*
3818c2ecf20Sopenharmony_ci *	crypto_alloc_base - Locate algorithm and allocate transform
3828c2ecf20Sopenharmony_ci *	@alg_name: Name of algorithm
3838c2ecf20Sopenharmony_ci *	@type: Type of algorithm
3848c2ecf20Sopenharmony_ci *	@mask: Mask for type comparison
3858c2ecf20Sopenharmony_ci *
3868c2ecf20Sopenharmony_ci *	This function should not be used by new algorithm types.
3878c2ecf20Sopenharmony_ci *	Please use crypto_alloc_tfm instead.
3888c2ecf20Sopenharmony_ci *
3898c2ecf20Sopenharmony_ci *	crypto_alloc_base() will first attempt to locate an already loaded
3908c2ecf20Sopenharmony_ci *	algorithm.  If that fails and the kernel supports dynamically loadable
3918c2ecf20Sopenharmony_ci *	modules, it will then attempt to load a module of the same name or
3928c2ecf20Sopenharmony_ci *	alias.  If that fails it will send a query to any loaded crypto manager
3938c2ecf20Sopenharmony_ci *	to construct an algorithm on the fly.  A refcount is grabbed on the
3948c2ecf20Sopenharmony_ci *	algorithm which is then associated with the new transform.
3958c2ecf20Sopenharmony_ci *
3968c2ecf20Sopenharmony_ci *	The returned transform is of a non-determinate type.  Most people
3978c2ecf20Sopenharmony_ci *	should use one of the more specific allocation functions such as
3988c2ecf20Sopenharmony_ci *	crypto_alloc_skcipher().
3998c2ecf20Sopenharmony_ci *
4008c2ecf20Sopenharmony_ci *	In case of error the return value is an error pointer.
4018c2ecf20Sopenharmony_ci */
4028c2ecf20Sopenharmony_cistruct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm;
4058c2ecf20Sopenharmony_ci	int err;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	for (;;) {
4088c2ecf20Sopenharmony_ci		struct crypto_alg *alg;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci		alg = crypto_alg_mod_lookup(alg_name, type, mask);
4118c2ecf20Sopenharmony_ci		if (IS_ERR(alg)) {
4128c2ecf20Sopenharmony_ci			err = PTR_ERR(alg);
4138c2ecf20Sopenharmony_ci			goto err;
4148c2ecf20Sopenharmony_ci		}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		tfm = __crypto_alloc_tfm(alg, type, mask);
4178c2ecf20Sopenharmony_ci		if (!IS_ERR(tfm))
4188c2ecf20Sopenharmony_ci			return tfm;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci		crypto_mod_put(alg);
4218c2ecf20Sopenharmony_ci		err = PTR_ERR(tfm);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cierr:
4248c2ecf20Sopenharmony_ci		if (err != -EAGAIN)
4258c2ecf20Sopenharmony_ci			break;
4268c2ecf20Sopenharmony_ci		if (fatal_signal_pending(current)) {
4278c2ecf20Sopenharmony_ci			err = -EINTR;
4288c2ecf20Sopenharmony_ci			break;
4298c2ecf20Sopenharmony_ci		}
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	return ERR_PTR(err);
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alloc_base);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_civoid *crypto_create_tfm_node(struct crypto_alg *alg,
4378c2ecf20Sopenharmony_ci			const struct crypto_type *frontend,
4388c2ecf20Sopenharmony_ci			int node)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	char *mem;
4418c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = NULL;
4428c2ecf20Sopenharmony_ci	unsigned int tfmsize;
4438c2ecf20Sopenharmony_ci	unsigned int total;
4448c2ecf20Sopenharmony_ci	int err = -ENOMEM;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	tfmsize = frontend->tfmsize;
4478c2ecf20Sopenharmony_ci	total = tfmsize + sizeof(*tfm) + frontend->extsize(alg);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	mem = kzalloc_node(total, GFP_KERNEL, node);
4508c2ecf20Sopenharmony_ci	if (mem == NULL)
4518c2ecf20Sopenharmony_ci		goto out_err;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	tfm = (struct crypto_tfm *)(mem + tfmsize);
4548c2ecf20Sopenharmony_ci	tfm->__crt_alg = alg;
4558c2ecf20Sopenharmony_ci	tfm->node = node;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	err = frontend->init_tfm(tfm);
4588c2ecf20Sopenharmony_ci	if (err)
4598c2ecf20Sopenharmony_ci		goto out_free_tfm;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
4628c2ecf20Sopenharmony_ci		goto cra_init_failed;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	goto out;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_cicra_init_failed:
4678c2ecf20Sopenharmony_ci	crypto_exit_ops(tfm);
4688c2ecf20Sopenharmony_ciout_free_tfm:
4698c2ecf20Sopenharmony_ci	if (err == -EAGAIN)
4708c2ecf20Sopenharmony_ci		crypto_shoot_alg(alg);
4718c2ecf20Sopenharmony_ci	kfree(mem);
4728c2ecf20Sopenharmony_ciout_err:
4738c2ecf20Sopenharmony_ci	mem = ERR_PTR(err);
4748c2ecf20Sopenharmony_ciout:
4758c2ecf20Sopenharmony_ci	return mem;
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_create_tfm_node);
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_cistruct crypto_alg *crypto_find_alg(const char *alg_name,
4808c2ecf20Sopenharmony_ci				   const struct crypto_type *frontend,
4818c2ecf20Sopenharmony_ci				   u32 type, u32 mask)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	if (frontend) {
4848c2ecf20Sopenharmony_ci		type &= frontend->maskclear;
4858c2ecf20Sopenharmony_ci		mask &= frontend->maskclear;
4868c2ecf20Sopenharmony_ci		type |= frontend->type;
4878c2ecf20Sopenharmony_ci		mask |= frontend->maskset;
4888c2ecf20Sopenharmony_ci	}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	return crypto_alg_mod_lookup(alg_name, type, mask);
4918c2ecf20Sopenharmony_ci}
4928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_find_alg);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci/*
4958c2ecf20Sopenharmony_ci *	crypto_alloc_tfm_node - Locate algorithm and allocate transform
4968c2ecf20Sopenharmony_ci *	@alg_name: Name of algorithm
4978c2ecf20Sopenharmony_ci *	@frontend: Frontend algorithm type
4988c2ecf20Sopenharmony_ci *	@type: Type of algorithm
4998c2ecf20Sopenharmony_ci *	@mask: Mask for type comparison
5008c2ecf20Sopenharmony_ci *	@node: NUMA node in which users desire to put requests, if node is
5018c2ecf20Sopenharmony_ci *		NUMA_NO_NODE, it means users have no special requirement.
5028c2ecf20Sopenharmony_ci *
5038c2ecf20Sopenharmony_ci *	crypto_alloc_tfm() will first attempt to locate an already loaded
5048c2ecf20Sopenharmony_ci *	algorithm.  If that fails and the kernel supports dynamically loadable
5058c2ecf20Sopenharmony_ci *	modules, it will then attempt to load a module of the same name or
5068c2ecf20Sopenharmony_ci *	alias.  If that fails it will send a query to any loaded crypto manager
5078c2ecf20Sopenharmony_ci *	to construct an algorithm on the fly.  A refcount is grabbed on the
5088c2ecf20Sopenharmony_ci *	algorithm which is then associated with the new transform.
5098c2ecf20Sopenharmony_ci *
5108c2ecf20Sopenharmony_ci *	The returned transform is of a non-determinate type.  Most people
5118c2ecf20Sopenharmony_ci *	should use one of the more specific allocation functions such as
5128c2ecf20Sopenharmony_ci *	crypto_alloc_skcipher().
5138c2ecf20Sopenharmony_ci *
5148c2ecf20Sopenharmony_ci *	In case of error the return value is an error pointer.
5158c2ecf20Sopenharmony_ci */
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_civoid *crypto_alloc_tfm_node(const char *alg_name,
5188c2ecf20Sopenharmony_ci		       const struct crypto_type *frontend, u32 type, u32 mask,
5198c2ecf20Sopenharmony_ci		       int node)
5208c2ecf20Sopenharmony_ci{
5218c2ecf20Sopenharmony_ci	void *tfm;
5228c2ecf20Sopenharmony_ci	int err;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	for (;;) {
5258c2ecf20Sopenharmony_ci		struct crypto_alg *alg;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci		alg = crypto_find_alg(alg_name, frontend, type, mask);
5288c2ecf20Sopenharmony_ci		if (IS_ERR(alg)) {
5298c2ecf20Sopenharmony_ci			err = PTR_ERR(alg);
5308c2ecf20Sopenharmony_ci			goto err;
5318c2ecf20Sopenharmony_ci		}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci		tfm = crypto_create_tfm_node(alg, frontend, node);
5348c2ecf20Sopenharmony_ci		if (!IS_ERR(tfm))
5358c2ecf20Sopenharmony_ci			return tfm;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci		crypto_mod_put(alg);
5388c2ecf20Sopenharmony_ci		err = PTR_ERR(tfm);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_cierr:
5418c2ecf20Sopenharmony_ci		if (err != -EAGAIN)
5428c2ecf20Sopenharmony_ci			break;
5438c2ecf20Sopenharmony_ci		if (fatal_signal_pending(current)) {
5448c2ecf20Sopenharmony_ci			err = -EINTR;
5458c2ecf20Sopenharmony_ci			break;
5468c2ecf20Sopenharmony_ci		}
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	return ERR_PTR(err);
5508c2ecf20Sopenharmony_ci}
5518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_alloc_tfm_node);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci/*
5548c2ecf20Sopenharmony_ci *	crypto_destroy_tfm - Free crypto transform
5558c2ecf20Sopenharmony_ci *	@mem: Start of tfm slab
5568c2ecf20Sopenharmony_ci *	@tfm: Transform to free
5578c2ecf20Sopenharmony_ci *
5588c2ecf20Sopenharmony_ci *	This function frees up the transform and any associated resources,
5598c2ecf20Sopenharmony_ci *	then drops the refcount on the associated algorithm.
5608c2ecf20Sopenharmony_ci */
5618c2ecf20Sopenharmony_civoid crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(mem))
5668c2ecf20Sopenharmony_ci		return;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	alg = tfm->__crt_alg;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	if (!tfm->exit && alg->cra_exit)
5718c2ecf20Sopenharmony_ci		alg->cra_exit(tfm);
5728c2ecf20Sopenharmony_ci	crypto_exit_ops(tfm);
5738c2ecf20Sopenharmony_ci	crypto_mod_put(alg);
5748c2ecf20Sopenharmony_ci	kfree_sensitive(mem);
5758c2ecf20Sopenharmony_ci}
5768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_destroy_tfm);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ciint crypto_has_alg(const char *name, u32 type, u32 mask)
5798c2ecf20Sopenharmony_ci{
5808c2ecf20Sopenharmony_ci	int ret = 0;
5818c2ecf20Sopenharmony_ci	struct crypto_alg *alg = crypto_alg_mod_lookup(name, type, mask);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	if (!IS_ERR(alg)) {
5848c2ecf20Sopenharmony_ci		crypto_mod_put(alg);
5858c2ecf20Sopenharmony_ci		ret = 1;
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	return ret;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_has_alg);
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_civoid crypto_req_done(struct crypto_async_request *req, int err)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	struct crypto_wait *wait = req->data;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	if (err == -EINPROGRESS)
5978c2ecf20Sopenharmony_ci		return;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	wait->err = err;
6008c2ecf20Sopenharmony_ci	complete(&wait->completion);
6018c2ecf20Sopenharmony_ci}
6028c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(crypto_req_done);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Cryptographic core API");
6058c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
606