162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Software async crypto daemon.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Added AEAD support to cryptd.
862306a36Sopenharmony_ci *    Authors: Tadeusz Struk (tadeusz.struk@intel.com)
962306a36Sopenharmony_ci *             Adrian Hoban <adrian.hoban@intel.com>
1062306a36Sopenharmony_ci *             Gabriele Paoloni <gabriele.paoloni@intel.com>
1162306a36Sopenharmony_ci *             Aidan O'Mahony (aidan.o.mahony@intel.com)
1262306a36Sopenharmony_ci *    Copyright (c) 2010, Intel Corporation.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <crypto/internal/hash.h>
1662306a36Sopenharmony_ci#include <crypto/internal/aead.h>
1762306a36Sopenharmony_ci#include <crypto/internal/skcipher.h>
1862306a36Sopenharmony_ci#include <crypto/cryptd.h>
1962306a36Sopenharmony_ci#include <linux/refcount.h>
2062306a36Sopenharmony_ci#include <linux/err.h>
2162306a36Sopenharmony_ci#include <linux/init.h>
2262306a36Sopenharmony_ci#include <linux/kernel.h>
2362306a36Sopenharmony_ci#include <linux/list.h>
2462306a36Sopenharmony_ci#include <linux/module.h>
2562306a36Sopenharmony_ci#include <linux/scatterlist.h>
2662306a36Sopenharmony_ci#include <linux/sched.h>
2762306a36Sopenharmony_ci#include <linux/slab.h>
2862306a36Sopenharmony_ci#include <linux/workqueue.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic unsigned int cryptd_max_cpu_qlen = 1000;
3162306a36Sopenharmony_cimodule_param(cryptd_max_cpu_qlen, uint, 0);
3262306a36Sopenharmony_ciMODULE_PARM_DESC(cryptd_max_cpu_qlen, "Set cryptd Max queue depth");
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic struct workqueue_struct *cryptd_wq;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistruct cryptd_cpu_queue {
3762306a36Sopenharmony_ci	struct crypto_queue queue;
3862306a36Sopenharmony_ci	struct work_struct work;
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct cryptd_queue {
4262306a36Sopenharmony_ci	/*
4362306a36Sopenharmony_ci	 * Protected by disabling BH to allow enqueueing from softinterrupt and
4462306a36Sopenharmony_ci	 * dequeuing from kworker (cryptd_queue_worker()).
4562306a36Sopenharmony_ci	 */
4662306a36Sopenharmony_ci	struct cryptd_cpu_queue __percpu *cpu_queue;
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistruct cryptd_instance_ctx {
5062306a36Sopenharmony_ci	struct crypto_spawn spawn;
5162306a36Sopenharmony_ci	struct cryptd_queue *queue;
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistruct skcipherd_instance_ctx {
5562306a36Sopenharmony_ci	struct crypto_skcipher_spawn spawn;
5662306a36Sopenharmony_ci	struct cryptd_queue *queue;
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct hashd_instance_ctx {
6062306a36Sopenharmony_ci	struct crypto_shash_spawn spawn;
6162306a36Sopenharmony_ci	struct cryptd_queue *queue;
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistruct aead_instance_ctx {
6562306a36Sopenharmony_ci	struct crypto_aead_spawn aead_spawn;
6662306a36Sopenharmony_ci	struct cryptd_queue *queue;
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistruct cryptd_skcipher_ctx {
7062306a36Sopenharmony_ci	refcount_t refcnt;
7162306a36Sopenharmony_ci	struct crypto_skcipher *child;
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistruct cryptd_skcipher_request_ctx {
7562306a36Sopenharmony_ci	struct skcipher_request req;
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistruct cryptd_hash_ctx {
7962306a36Sopenharmony_ci	refcount_t refcnt;
8062306a36Sopenharmony_ci	struct crypto_shash *child;
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistruct cryptd_hash_request_ctx {
8462306a36Sopenharmony_ci	crypto_completion_t complete;
8562306a36Sopenharmony_ci	void *data;
8662306a36Sopenharmony_ci	struct shash_desc desc;
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistruct cryptd_aead_ctx {
9062306a36Sopenharmony_ci	refcount_t refcnt;
9162306a36Sopenharmony_ci	struct crypto_aead *child;
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistruct cryptd_aead_request_ctx {
9562306a36Sopenharmony_ci	struct aead_request req;
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic void cryptd_queue_worker(struct work_struct *work);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic int cryptd_init_queue(struct cryptd_queue *queue,
10162306a36Sopenharmony_ci			     unsigned int max_cpu_qlen)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	int cpu;
10462306a36Sopenharmony_ci	struct cryptd_cpu_queue *cpu_queue;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	queue->cpu_queue = alloc_percpu(struct cryptd_cpu_queue);
10762306a36Sopenharmony_ci	if (!queue->cpu_queue)
10862306a36Sopenharmony_ci		return -ENOMEM;
10962306a36Sopenharmony_ci	for_each_possible_cpu(cpu) {
11062306a36Sopenharmony_ci		cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
11162306a36Sopenharmony_ci		crypto_init_queue(&cpu_queue->queue, max_cpu_qlen);
11262306a36Sopenharmony_ci		INIT_WORK(&cpu_queue->work, cryptd_queue_worker);
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci	pr_info("cryptd: max_cpu_qlen set to %d\n", max_cpu_qlen);
11562306a36Sopenharmony_ci	return 0;
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic void cryptd_fini_queue(struct cryptd_queue *queue)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	int cpu;
12162306a36Sopenharmony_ci	struct cryptd_cpu_queue *cpu_queue;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	for_each_possible_cpu(cpu) {
12462306a36Sopenharmony_ci		cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
12562306a36Sopenharmony_ci		BUG_ON(cpu_queue->queue.qlen);
12662306a36Sopenharmony_ci	}
12762306a36Sopenharmony_ci	free_percpu(queue->cpu_queue);
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic int cryptd_enqueue_request(struct cryptd_queue *queue,
13162306a36Sopenharmony_ci				  struct crypto_async_request *request)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	int err;
13462306a36Sopenharmony_ci	struct cryptd_cpu_queue *cpu_queue;
13562306a36Sopenharmony_ci	refcount_t *refcnt;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	local_bh_disable();
13862306a36Sopenharmony_ci	cpu_queue = this_cpu_ptr(queue->cpu_queue);
13962306a36Sopenharmony_ci	err = crypto_enqueue_request(&cpu_queue->queue, request);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	refcnt = crypto_tfm_ctx(request->tfm);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	if (err == -ENOSPC)
14462306a36Sopenharmony_ci		goto out;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	queue_work_on(smp_processor_id(), cryptd_wq, &cpu_queue->work);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	if (!refcount_read(refcnt))
14962306a36Sopenharmony_ci		goto out;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	refcount_inc(refcnt);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciout:
15462306a36Sopenharmony_ci	local_bh_enable();
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	return err;
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/* Called in workqueue context, do one real cryption work (via
16062306a36Sopenharmony_ci * req->complete) and reschedule itself if there are more work to
16162306a36Sopenharmony_ci * do. */
16262306a36Sopenharmony_cistatic void cryptd_queue_worker(struct work_struct *work)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct cryptd_cpu_queue *cpu_queue;
16562306a36Sopenharmony_ci	struct crypto_async_request *req, *backlog;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
16862306a36Sopenharmony_ci	/*
16962306a36Sopenharmony_ci	 * Only handle one request at a time to avoid hogging crypto workqueue.
17062306a36Sopenharmony_ci	 */
17162306a36Sopenharmony_ci	local_bh_disable();
17262306a36Sopenharmony_ci	backlog = crypto_get_backlog(&cpu_queue->queue);
17362306a36Sopenharmony_ci	req = crypto_dequeue_request(&cpu_queue->queue);
17462306a36Sopenharmony_ci	local_bh_enable();
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (!req)
17762306a36Sopenharmony_ci		return;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	if (backlog)
18062306a36Sopenharmony_ci		crypto_request_complete(backlog, -EINPROGRESS);
18162306a36Sopenharmony_ci	crypto_request_complete(req, 0);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	if (cpu_queue->queue.qlen)
18462306a36Sopenharmony_ci		queue_work(cryptd_wq, &cpu_queue->work);
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
19062306a36Sopenharmony_ci	struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
19162306a36Sopenharmony_ci	return ictx->queue;
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic void cryptd_type_and_mask(struct crypto_attr_type *algt,
19562306a36Sopenharmony_ci				 u32 *type, u32 *mask)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	/*
19862306a36Sopenharmony_ci	 * cryptd is allowed to wrap internal algorithms, but in that case the
19962306a36Sopenharmony_ci	 * resulting cryptd instance will be marked as internal as well.
20062306a36Sopenharmony_ci	 */
20162306a36Sopenharmony_ci	*type = algt->type & CRYPTO_ALG_INTERNAL;
20262306a36Sopenharmony_ci	*mask = algt->mask & CRYPTO_ALG_INTERNAL;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	/* No point in cryptd wrapping an algorithm that's already async. */
20562306a36Sopenharmony_ci	*mask |= CRYPTO_ALG_ASYNC;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	*mask |= crypto_algt_inherited_mask(algt);
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic int cryptd_init_instance(struct crypto_instance *inst,
21162306a36Sopenharmony_ci				struct crypto_alg *alg)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
21462306a36Sopenharmony_ci		     "cryptd(%s)",
21562306a36Sopenharmony_ci		     alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
21662306a36Sopenharmony_ci		return -ENAMETOOLONG;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	inst->alg.cra_priority = alg->cra_priority + 50;
22162306a36Sopenharmony_ci	inst->alg.cra_blocksize = alg->cra_blocksize;
22262306a36Sopenharmony_ci	inst->alg.cra_alignmask = alg->cra_alignmask;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	return 0;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic int cryptd_skcipher_setkey(struct crypto_skcipher *parent,
22862306a36Sopenharmony_ci				  const u8 *key, unsigned int keylen)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(parent);
23162306a36Sopenharmony_ci	struct crypto_skcipher *child = ctx->child;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
23462306a36Sopenharmony_ci	crypto_skcipher_set_flags(child,
23562306a36Sopenharmony_ci				  crypto_skcipher_get_flags(parent) &
23662306a36Sopenharmony_ci				  CRYPTO_TFM_REQ_MASK);
23762306a36Sopenharmony_ci	return crypto_skcipher_setkey(child, key, keylen);
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic struct skcipher_request *cryptd_skcipher_prepare(
24162306a36Sopenharmony_ci	struct skcipher_request *req, int err)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
24462306a36Sopenharmony_ci	struct skcipher_request *subreq = &rctx->req;
24562306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx;
24662306a36Sopenharmony_ci	struct crypto_skcipher *child;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	req->base.complete = subreq->base.complete;
24962306a36Sopenharmony_ci	req->base.data = subreq->base.data;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	if (unlikely(err == -EINPROGRESS))
25262306a36Sopenharmony_ci		return NULL;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
25562306a36Sopenharmony_ci	child = ctx->child;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	skcipher_request_set_tfm(subreq, child);
25862306a36Sopenharmony_ci	skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP,
25962306a36Sopenharmony_ci				      NULL, NULL);
26062306a36Sopenharmony_ci	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
26162306a36Sopenharmony_ci				   req->iv);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	return subreq;
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic void cryptd_skcipher_complete(struct skcipher_request *req, int err,
26762306a36Sopenharmony_ci				     crypto_completion_t complete)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
27062306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
27162306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
27262306a36Sopenharmony_ci	struct skcipher_request *subreq = &rctx->req;
27362306a36Sopenharmony_ci	int refcnt = refcount_read(&ctx->refcnt);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	local_bh_disable();
27662306a36Sopenharmony_ci	skcipher_request_complete(req, err);
27762306a36Sopenharmony_ci	local_bh_enable();
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	if (unlikely(err == -EINPROGRESS)) {
28062306a36Sopenharmony_ci		subreq->base.complete = req->base.complete;
28162306a36Sopenharmony_ci		subreq->base.data = req->base.data;
28262306a36Sopenharmony_ci		req->base.complete = complete;
28362306a36Sopenharmony_ci		req->base.data = req;
28462306a36Sopenharmony_ci	} else if (refcnt && refcount_dec_and_test(&ctx->refcnt))
28562306a36Sopenharmony_ci		crypto_free_skcipher(tfm);
28662306a36Sopenharmony_ci}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistatic void cryptd_skcipher_encrypt(void *data, int err)
28962306a36Sopenharmony_ci{
29062306a36Sopenharmony_ci	struct skcipher_request *req = data;
29162306a36Sopenharmony_ci	struct skcipher_request *subreq;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	subreq = cryptd_skcipher_prepare(req, err);
29462306a36Sopenharmony_ci	if (likely(subreq))
29562306a36Sopenharmony_ci		err = crypto_skcipher_encrypt(subreq);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	cryptd_skcipher_complete(req, err, cryptd_skcipher_encrypt);
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic void cryptd_skcipher_decrypt(void *data, int err)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	struct skcipher_request *req = data;
30362306a36Sopenharmony_ci	struct skcipher_request *subreq;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	subreq = cryptd_skcipher_prepare(req, err);
30662306a36Sopenharmony_ci	if (likely(subreq))
30762306a36Sopenharmony_ci		err = crypto_skcipher_decrypt(subreq);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	cryptd_skcipher_complete(req, err, cryptd_skcipher_decrypt);
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic int cryptd_skcipher_enqueue(struct skcipher_request *req,
31362306a36Sopenharmony_ci				   crypto_completion_t compl)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
31662306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
31762306a36Sopenharmony_ci	struct skcipher_request *subreq = &rctx->req;
31862306a36Sopenharmony_ci	struct cryptd_queue *queue;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	queue = cryptd_get_queue(crypto_skcipher_tfm(tfm));
32162306a36Sopenharmony_ci	subreq->base.complete = req->base.complete;
32262306a36Sopenharmony_ci	subreq->base.data = req->base.data;
32362306a36Sopenharmony_ci	req->base.complete = compl;
32462306a36Sopenharmony_ci	req->base.data = req;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	return cryptd_enqueue_request(queue, &req->base);
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic int cryptd_skcipher_encrypt_enqueue(struct skcipher_request *req)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	return cryptd_skcipher_enqueue(req, cryptd_skcipher_encrypt);
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_cistatic int cryptd_skcipher_decrypt_enqueue(struct skcipher_request *req)
33562306a36Sopenharmony_ci{
33662306a36Sopenharmony_ci	return cryptd_skcipher_enqueue(req, cryptd_skcipher_decrypt);
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistatic int cryptd_skcipher_init_tfm(struct crypto_skcipher *tfm)
34062306a36Sopenharmony_ci{
34162306a36Sopenharmony_ci	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
34262306a36Sopenharmony_ci	struct skcipherd_instance_ctx *ictx = skcipher_instance_ctx(inst);
34362306a36Sopenharmony_ci	struct crypto_skcipher_spawn *spawn = &ictx->spawn;
34462306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
34562306a36Sopenharmony_ci	struct crypto_skcipher *cipher;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	cipher = crypto_spawn_skcipher(spawn);
34862306a36Sopenharmony_ci	if (IS_ERR(cipher))
34962306a36Sopenharmony_ci		return PTR_ERR(cipher);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	ctx->child = cipher;
35262306a36Sopenharmony_ci	crypto_skcipher_set_reqsize(
35362306a36Sopenharmony_ci		tfm, sizeof(struct cryptd_skcipher_request_ctx) +
35462306a36Sopenharmony_ci		     crypto_skcipher_reqsize(cipher));
35562306a36Sopenharmony_ci	return 0;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic void cryptd_skcipher_exit_tfm(struct crypto_skcipher *tfm)
35962306a36Sopenharmony_ci{
36062306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	crypto_free_skcipher(ctx->child);
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_cistatic void cryptd_skcipher_free(struct skcipher_instance *inst)
36662306a36Sopenharmony_ci{
36762306a36Sopenharmony_ci	struct skcipherd_instance_ctx *ctx = skcipher_instance_ctx(inst);
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	crypto_drop_skcipher(&ctx->spawn);
37062306a36Sopenharmony_ci	kfree(inst);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int cryptd_create_skcipher(struct crypto_template *tmpl,
37462306a36Sopenharmony_ci				  struct rtattr **tb,
37562306a36Sopenharmony_ci				  struct crypto_attr_type *algt,
37662306a36Sopenharmony_ci				  struct cryptd_queue *queue)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	struct skcipherd_instance_ctx *ctx;
37962306a36Sopenharmony_ci	struct skcipher_instance *inst;
38062306a36Sopenharmony_ci	struct skcipher_alg *alg;
38162306a36Sopenharmony_ci	u32 type;
38262306a36Sopenharmony_ci	u32 mask;
38362306a36Sopenharmony_ci	int err;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	cryptd_type_and_mask(algt, &type, &mask);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
38862306a36Sopenharmony_ci	if (!inst)
38962306a36Sopenharmony_ci		return -ENOMEM;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	ctx = skcipher_instance_ctx(inst);
39262306a36Sopenharmony_ci	ctx->queue = queue;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	err = crypto_grab_skcipher(&ctx->spawn, skcipher_crypto_instance(inst),
39562306a36Sopenharmony_ci				   crypto_attr_alg_name(tb[1]), type, mask);
39662306a36Sopenharmony_ci	if (err)
39762306a36Sopenharmony_ci		goto err_free_inst;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	alg = crypto_spawn_skcipher_alg(&ctx->spawn);
40062306a36Sopenharmony_ci	err = cryptd_init_instance(skcipher_crypto_instance(inst), &alg->base);
40162306a36Sopenharmony_ci	if (err)
40262306a36Sopenharmony_ci		goto err_free_inst;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	inst->alg.base.cra_flags |= CRYPTO_ALG_ASYNC |
40562306a36Sopenharmony_ci		(alg->base.cra_flags & CRYPTO_ALG_INTERNAL);
40662306a36Sopenharmony_ci	inst->alg.ivsize = crypto_skcipher_alg_ivsize(alg);
40762306a36Sopenharmony_ci	inst->alg.chunksize = crypto_skcipher_alg_chunksize(alg);
40862306a36Sopenharmony_ci	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg);
40962306a36Sopenharmony_ci	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	inst->alg.base.cra_ctxsize = sizeof(struct cryptd_skcipher_ctx);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	inst->alg.init = cryptd_skcipher_init_tfm;
41462306a36Sopenharmony_ci	inst->alg.exit = cryptd_skcipher_exit_tfm;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	inst->alg.setkey = cryptd_skcipher_setkey;
41762306a36Sopenharmony_ci	inst->alg.encrypt = cryptd_skcipher_encrypt_enqueue;
41862306a36Sopenharmony_ci	inst->alg.decrypt = cryptd_skcipher_decrypt_enqueue;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	inst->free = cryptd_skcipher_free;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	err = skcipher_register_instance(tmpl, inst);
42362306a36Sopenharmony_ci	if (err) {
42462306a36Sopenharmony_cierr_free_inst:
42562306a36Sopenharmony_ci		cryptd_skcipher_free(inst);
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci	return err;
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic int cryptd_hash_init_tfm(struct crypto_ahash *tfm)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	struct ahash_instance *inst = ahash_alg_instance(tfm);
43362306a36Sopenharmony_ci	struct hashd_instance_ctx *ictx = ahash_instance_ctx(inst);
43462306a36Sopenharmony_ci	struct crypto_shash_spawn *spawn = &ictx->spawn;
43562306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
43662306a36Sopenharmony_ci	struct crypto_shash *hash;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	hash = crypto_spawn_shash(spawn);
43962306a36Sopenharmony_ci	if (IS_ERR(hash))
44062306a36Sopenharmony_ci		return PTR_ERR(hash);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	ctx->child = hash;
44362306a36Sopenharmony_ci	crypto_ahash_set_reqsize(tfm,
44462306a36Sopenharmony_ci				 sizeof(struct cryptd_hash_request_ctx) +
44562306a36Sopenharmony_ci				 crypto_shash_descsize(hash));
44662306a36Sopenharmony_ci	return 0;
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic int cryptd_hash_clone_tfm(struct crypto_ahash *ntfm,
45062306a36Sopenharmony_ci				 struct crypto_ahash *tfm)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	struct cryptd_hash_ctx *nctx = crypto_ahash_ctx(ntfm);
45362306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
45462306a36Sopenharmony_ci	struct crypto_shash *hash;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	hash = crypto_clone_shash(ctx->child);
45762306a36Sopenharmony_ci	if (IS_ERR(hash))
45862306a36Sopenharmony_ci		return PTR_ERR(hash);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	nctx->child = hash;
46162306a36Sopenharmony_ci	return 0;
46262306a36Sopenharmony_ci}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_cistatic void cryptd_hash_exit_tfm(struct crypto_ahash *tfm)
46562306a36Sopenharmony_ci{
46662306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	crypto_free_shash(ctx->child);
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_cistatic int cryptd_hash_setkey(struct crypto_ahash *parent,
47262306a36Sopenharmony_ci				   const u8 *key, unsigned int keylen)
47362306a36Sopenharmony_ci{
47462306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx   = crypto_ahash_ctx(parent);
47562306a36Sopenharmony_ci	struct crypto_shash *child = ctx->child;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	crypto_shash_clear_flags(child, CRYPTO_TFM_REQ_MASK);
47862306a36Sopenharmony_ci	crypto_shash_set_flags(child, crypto_ahash_get_flags(parent) &
47962306a36Sopenharmony_ci				      CRYPTO_TFM_REQ_MASK);
48062306a36Sopenharmony_ci	return crypto_shash_setkey(child, key, keylen);
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic int cryptd_hash_enqueue(struct ahash_request *req,
48462306a36Sopenharmony_ci				crypto_completion_t compl)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
48762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
48862306a36Sopenharmony_ci	struct cryptd_queue *queue =
48962306a36Sopenharmony_ci		cryptd_get_queue(crypto_ahash_tfm(tfm));
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	rctx->complete = req->base.complete;
49262306a36Sopenharmony_ci	rctx->data = req->base.data;
49362306a36Sopenharmony_ci	req->base.complete = compl;
49462306a36Sopenharmony_ci	req->base.data = req;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	return cryptd_enqueue_request(queue, &req->base);
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_cistatic struct shash_desc *cryptd_hash_prepare(struct ahash_request *req,
50062306a36Sopenharmony_ci					      int err)
50162306a36Sopenharmony_ci{
50262306a36Sopenharmony_ci	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	req->base.complete = rctx->complete;
50562306a36Sopenharmony_ci	req->base.data = rctx->data;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	if (unlikely(err == -EINPROGRESS))
50862306a36Sopenharmony_ci		return NULL;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	return &rctx->desc;
51162306a36Sopenharmony_ci}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cistatic void cryptd_hash_complete(struct ahash_request *req, int err,
51462306a36Sopenharmony_ci				 crypto_completion_t complete)
51562306a36Sopenharmony_ci{
51662306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
51762306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
51862306a36Sopenharmony_ci	int refcnt = refcount_read(&ctx->refcnt);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	local_bh_disable();
52162306a36Sopenharmony_ci	ahash_request_complete(req, err);
52262306a36Sopenharmony_ci	local_bh_enable();
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	if (err == -EINPROGRESS) {
52562306a36Sopenharmony_ci		req->base.complete = complete;
52662306a36Sopenharmony_ci		req->base.data = req;
52762306a36Sopenharmony_ci	} else if (refcnt && refcount_dec_and_test(&ctx->refcnt))
52862306a36Sopenharmony_ci		crypto_free_ahash(tfm);
52962306a36Sopenharmony_ci}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_cistatic void cryptd_hash_init(void *data, int err)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	struct ahash_request *req = data;
53462306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
53562306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
53662306a36Sopenharmony_ci	struct crypto_shash *child = ctx->child;
53762306a36Sopenharmony_ci	struct shash_desc *desc;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	desc = cryptd_hash_prepare(req, err);
54062306a36Sopenharmony_ci	if (unlikely(!desc))
54162306a36Sopenharmony_ci		goto out;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	desc->tfm = child;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	err = crypto_shash_init(desc);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ciout:
54862306a36Sopenharmony_ci	cryptd_hash_complete(req, err, cryptd_hash_init);
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_cistatic int cryptd_hash_init_enqueue(struct ahash_request *req)
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	return cryptd_hash_enqueue(req, cryptd_hash_init);
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_cistatic void cryptd_hash_update(void *data, int err)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	struct ahash_request *req = data;
55962306a36Sopenharmony_ci	struct shash_desc *desc;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	desc = cryptd_hash_prepare(req, err);
56262306a36Sopenharmony_ci	if (likely(desc))
56362306a36Sopenharmony_ci		err = shash_ahash_update(req, desc);
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	cryptd_hash_complete(req, err, cryptd_hash_update);
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_cistatic int cryptd_hash_update_enqueue(struct ahash_request *req)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	return cryptd_hash_enqueue(req, cryptd_hash_update);
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_cistatic void cryptd_hash_final(void *data, int err)
57462306a36Sopenharmony_ci{
57562306a36Sopenharmony_ci	struct ahash_request *req = data;
57662306a36Sopenharmony_ci	struct shash_desc *desc;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	desc = cryptd_hash_prepare(req, err);
57962306a36Sopenharmony_ci	if (likely(desc))
58062306a36Sopenharmony_ci		err = crypto_shash_final(desc, req->result);
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	cryptd_hash_complete(req, err, cryptd_hash_final);
58362306a36Sopenharmony_ci}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_cistatic int cryptd_hash_final_enqueue(struct ahash_request *req)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	return cryptd_hash_enqueue(req, cryptd_hash_final);
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic void cryptd_hash_finup(void *data, int err)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	struct ahash_request *req = data;
59362306a36Sopenharmony_ci	struct shash_desc *desc;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	desc = cryptd_hash_prepare(req, err);
59662306a36Sopenharmony_ci	if (likely(desc))
59762306a36Sopenharmony_ci		err = shash_ahash_finup(req, desc);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	cryptd_hash_complete(req, err, cryptd_hash_finup);
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic int cryptd_hash_finup_enqueue(struct ahash_request *req)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	return cryptd_hash_enqueue(req, cryptd_hash_finup);
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic void cryptd_hash_digest(void *data, int err)
60862306a36Sopenharmony_ci{
60962306a36Sopenharmony_ci	struct ahash_request *req = data;
61062306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
61162306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
61262306a36Sopenharmony_ci	struct crypto_shash *child = ctx->child;
61362306a36Sopenharmony_ci	struct shash_desc *desc;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	desc = cryptd_hash_prepare(req, err);
61662306a36Sopenharmony_ci	if (unlikely(!desc))
61762306a36Sopenharmony_ci		goto out;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	desc->tfm = child;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	err = shash_ahash_digest(req, desc);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ciout:
62462306a36Sopenharmony_ci	cryptd_hash_complete(req, err, cryptd_hash_digest);
62562306a36Sopenharmony_ci}
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_cistatic int cryptd_hash_digest_enqueue(struct ahash_request *req)
62862306a36Sopenharmony_ci{
62962306a36Sopenharmony_ci	return cryptd_hash_enqueue(req, cryptd_hash_digest);
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_cistatic int cryptd_hash_export(struct ahash_request *req, void *out)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	return crypto_shash_export(&rctx->desc, out);
63762306a36Sopenharmony_ci}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_cistatic int cryptd_hash_import(struct ahash_request *req, const void *in)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
64262306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
64362306a36Sopenharmony_ci	struct shash_desc *desc = cryptd_shash_desc(req);
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	desc->tfm = ctx->child;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	return crypto_shash_import(desc, in);
64862306a36Sopenharmony_ci}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_cistatic void cryptd_hash_free(struct ahash_instance *inst)
65162306a36Sopenharmony_ci{
65262306a36Sopenharmony_ci	struct hashd_instance_ctx *ctx = ahash_instance_ctx(inst);
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	crypto_drop_shash(&ctx->spawn);
65562306a36Sopenharmony_ci	kfree(inst);
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_cistatic int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
65962306a36Sopenharmony_ci			      struct crypto_attr_type *algt,
66062306a36Sopenharmony_ci			      struct cryptd_queue *queue)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	struct hashd_instance_ctx *ctx;
66362306a36Sopenharmony_ci	struct ahash_instance *inst;
66462306a36Sopenharmony_ci	struct shash_alg *alg;
66562306a36Sopenharmony_ci	u32 type;
66662306a36Sopenharmony_ci	u32 mask;
66762306a36Sopenharmony_ci	int err;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	cryptd_type_and_mask(algt, &type, &mask);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
67262306a36Sopenharmony_ci	if (!inst)
67362306a36Sopenharmony_ci		return -ENOMEM;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	ctx = ahash_instance_ctx(inst);
67662306a36Sopenharmony_ci	ctx->queue = queue;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	err = crypto_grab_shash(&ctx->spawn, ahash_crypto_instance(inst),
67962306a36Sopenharmony_ci				crypto_attr_alg_name(tb[1]), type, mask);
68062306a36Sopenharmony_ci	if (err)
68162306a36Sopenharmony_ci		goto err_free_inst;
68262306a36Sopenharmony_ci	alg = crypto_spawn_shash_alg(&ctx->spawn);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	err = cryptd_init_instance(ahash_crypto_instance(inst), &alg->base);
68562306a36Sopenharmony_ci	if (err)
68662306a36Sopenharmony_ci		goto err_free_inst;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	inst->alg.halg.base.cra_flags |= CRYPTO_ALG_ASYNC |
68962306a36Sopenharmony_ci		(alg->base.cra_flags & (CRYPTO_ALG_INTERNAL|
69062306a36Sopenharmony_ci					CRYPTO_ALG_OPTIONAL_KEY));
69162306a36Sopenharmony_ci	inst->alg.halg.digestsize = alg->digestsize;
69262306a36Sopenharmony_ci	inst->alg.halg.statesize = alg->statesize;
69362306a36Sopenharmony_ci	inst->alg.halg.base.cra_ctxsize = sizeof(struct cryptd_hash_ctx);
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	inst->alg.init_tfm = cryptd_hash_init_tfm;
69662306a36Sopenharmony_ci	inst->alg.clone_tfm = cryptd_hash_clone_tfm;
69762306a36Sopenharmony_ci	inst->alg.exit_tfm = cryptd_hash_exit_tfm;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	inst->alg.init   = cryptd_hash_init_enqueue;
70062306a36Sopenharmony_ci	inst->alg.update = cryptd_hash_update_enqueue;
70162306a36Sopenharmony_ci	inst->alg.final  = cryptd_hash_final_enqueue;
70262306a36Sopenharmony_ci	inst->alg.finup  = cryptd_hash_finup_enqueue;
70362306a36Sopenharmony_ci	inst->alg.export = cryptd_hash_export;
70462306a36Sopenharmony_ci	inst->alg.import = cryptd_hash_import;
70562306a36Sopenharmony_ci	if (crypto_shash_alg_has_setkey(alg))
70662306a36Sopenharmony_ci		inst->alg.setkey = cryptd_hash_setkey;
70762306a36Sopenharmony_ci	inst->alg.digest = cryptd_hash_digest_enqueue;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	inst->free = cryptd_hash_free;
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	err = ahash_register_instance(tmpl, inst);
71262306a36Sopenharmony_ci	if (err) {
71362306a36Sopenharmony_cierr_free_inst:
71462306a36Sopenharmony_ci		cryptd_hash_free(inst);
71562306a36Sopenharmony_ci	}
71662306a36Sopenharmony_ci	return err;
71762306a36Sopenharmony_ci}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_cistatic int cryptd_aead_setkey(struct crypto_aead *parent,
72062306a36Sopenharmony_ci			      const u8 *key, unsigned int keylen)
72162306a36Sopenharmony_ci{
72262306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent);
72362306a36Sopenharmony_ci	struct crypto_aead *child = ctx->child;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	return crypto_aead_setkey(child, key, keylen);
72662306a36Sopenharmony_ci}
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_cistatic int cryptd_aead_setauthsize(struct crypto_aead *parent,
72962306a36Sopenharmony_ci				   unsigned int authsize)
73062306a36Sopenharmony_ci{
73162306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent);
73262306a36Sopenharmony_ci	struct crypto_aead *child = ctx->child;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	return crypto_aead_setauthsize(child, authsize);
73562306a36Sopenharmony_ci}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_cistatic void cryptd_aead_crypt(struct aead_request *req,
73862306a36Sopenharmony_ci			      struct crypto_aead *child, int err,
73962306a36Sopenharmony_ci			      int (*crypt)(struct aead_request *req),
74062306a36Sopenharmony_ci			      crypto_completion_t compl)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	struct cryptd_aead_request_ctx *rctx;
74362306a36Sopenharmony_ci	struct aead_request *subreq;
74462306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx;
74562306a36Sopenharmony_ci	struct crypto_aead *tfm;
74662306a36Sopenharmony_ci	int refcnt;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	rctx = aead_request_ctx(req);
74962306a36Sopenharmony_ci	subreq = &rctx->req;
75062306a36Sopenharmony_ci	req->base.complete = subreq->base.complete;
75162306a36Sopenharmony_ci	req->base.data = subreq->base.data;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	tfm = crypto_aead_reqtfm(req);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	if (unlikely(err == -EINPROGRESS))
75662306a36Sopenharmony_ci		goto out;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	aead_request_set_tfm(subreq, child);
75962306a36Sopenharmony_ci	aead_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP,
76062306a36Sopenharmony_ci				  NULL, NULL);
76162306a36Sopenharmony_ci	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
76262306a36Sopenharmony_ci			       req->iv);
76362306a36Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	err = crypt(subreq);
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ciout:
76862306a36Sopenharmony_ci	ctx = crypto_aead_ctx(tfm);
76962306a36Sopenharmony_ci	refcnt = refcount_read(&ctx->refcnt);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	local_bh_disable();
77262306a36Sopenharmony_ci	aead_request_complete(req, err);
77362306a36Sopenharmony_ci	local_bh_enable();
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	if (err == -EINPROGRESS) {
77662306a36Sopenharmony_ci		subreq->base.complete = req->base.complete;
77762306a36Sopenharmony_ci		subreq->base.data = req->base.data;
77862306a36Sopenharmony_ci		req->base.complete = compl;
77962306a36Sopenharmony_ci		req->base.data = req;
78062306a36Sopenharmony_ci	} else if (refcnt && refcount_dec_and_test(&ctx->refcnt))
78162306a36Sopenharmony_ci		crypto_free_aead(tfm);
78262306a36Sopenharmony_ci}
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_cistatic void cryptd_aead_encrypt(void *data, int err)
78562306a36Sopenharmony_ci{
78662306a36Sopenharmony_ci	struct aead_request *req = data;
78762306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx;
78862306a36Sopenharmony_ci	struct crypto_aead *child;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
79162306a36Sopenharmony_ci	child = ctx->child;
79262306a36Sopenharmony_ci	cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->encrypt,
79362306a36Sopenharmony_ci			  cryptd_aead_encrypt);
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_cistatic void cryptd_aead_decrypt(void *data, int err)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	struct aead_request *req = data;
79962306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx;
80062306a36Sopenharmony_ci	struct crypto_aead *child;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
80362306a36Sopenharmony_ci	child = ctx->child;
80462306a36Sopenharmony_ci	cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->decrypt,
80562306a36Sopenharmony_ci			  cryptd_aead_decrypt);
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_cistatic int cryptd_aead_enqueue(struct aead_request *req,
80962306a36Sopenharmony_ci				    crypto_completion_t compl)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	struct cryptd_aead_request_ctx *rctx = aead_request_ctx(req);
81262306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
81362306a36Sopenharmony_ci	struct cryptd_queue *queue = cryptd_get_queue(crypto_aead_tfm(tfm));
81462306a36Sopenharmony_ci	struct aead_request *subreq = &rctx->req;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	subreq->base.complete = req->base.complete;
81762306a36Sopenharmony_ci	subreq->base.data = req->base.data;
81862306a36Sopenharmony_ci	req->base.complete = compl;
81962306a36Sopenharmony_ci	req->base.data = req;
82062306a36Sopenharmony_ci	return cryptd_enqueue_request(queue, &req->base);
82162306a36Sopenharmony_ci}
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_cistatic int cryptd_aead_encrypt_enqueue(struct aead_request *req)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	return cryptd_aead_enqueue(req, cryptd_aead_encrypt );
82662306a36Sopenharmony_ci}
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_cistatic int cryptd_aead_decrypt_enqueue(struct aead_request *req)
82962306a36Sopenharmony_ci{
83062306a36Sopenharmony_ci	return cryptd_aead_enqueue(req, cryptd_aead_decrypt );
83162306a36Sopenharmony_ci}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_cistatic int cryptd_aead_init_tfm(struct crypto_aead *tfm)
83462306a36Sopenharmony_ci{
83562306a36Sopenharmony_ci	struct aead_instance *inst = aead_alg_instance(tfm);
83662306a36Sopenharmony_ci	struct aead_instance_ctx *ictx = aead_instance_ctx(inst);
83762306a36Sopenharmony_ci	struct crypto_aead_spawn *spawn = &ictx->aead_spawn;
83862306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm);
83962306a36Sopenharmony_ci	struct crypto_aead *cipher;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	cipher = crypto_spawn_aead(spawn);
84262306a36Sopenharmony_ci	if (IS_ERR(cipher))
84362306a36Sopenharmony_ci		return PTR_ERR(cipher);
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	ctx->child = cipher;
84662306a36Sopenharmony_ci	crypto_aead_set_reqsize(
84762306a36Sopenharmony_ci		tfm, sizeof(struct cryptd_aead_request_ctx) +
84862306a36Sopenharmony_ci		     crypto_aead_reqsize(cipher));
84962306a36Sopenharmony_ci	return 0;
85062306a36Sopenharmony_ci}
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_cistatic void cryptd_aead_exit_tfm(struct crypto_aead *tfm)
85362306a36Sopenharmony_ci{
85462306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm);
85562306a36Sopenharmony_ci	crypto_free_aead(ctx->child);
85662306a36Sopenharmony_ci}
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_cistatic void cryptd_aead_free(struct aead_instance *inst)
85962306a36Sopenharmony_ci{
86062306a36Sopenharmony_ci	struct aead_instance_ctx *ctx = aead_instance_ctx(inst);
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	crypto_drop_aead(&ctx->aead_spawn);
86362306a36Sopenharmony_ci	kfree(inst);
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_cistatic int cryptd_create_aead(struct crypto_template *tmpl,
86762306a36Sopenharmony_ci		              struct rtattr **tb,
86862306a36Sopenharmony_ci			      struct crypto_attr_type *algt,
86962306a36Sopenharmony_ci			      struct cryptd_queue *queue)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci	struct aead_instance_ctx *ctx;
87262306a36Sopenharmony_ci	struct aead_instance *inst;
87362306a36Sopenharmony_ci	struct aead_alg *alg;
87462306a36Sopenharmony_ci	u32 type;
87562306a36Sopenharmony_ci	u32 mask;
87662306a36Sopenharmony_ci	int err;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	cryptd_type_and_mask(algt, &type, &mask);
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
88162306a36Sopenharmony_ci	if (!inst)
88262306a36Sopenharmony_ci		return -ENOMEM;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	ctx = aead_instance_ctx(inst);
88562306a36Sopenharmony_ci	ctx->queue = queue;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	err = crypto_grab_aead(&ctx->aead_spawn, aead_crypto_instance(inst),
88862306a36Sopenharmony_ci			       crypto_attr_alg_name(tb[1]), type, mask);
88962306a36Sopenharmony_ci	if (err)
89062306a36Sopenharmony_ci		goto err_free_inst;
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	alg = crypto_spawn_aead_alg(&ctx->aead_spawn);
89362306a36Sopenharmony_ci	err = cryptd_init_instance(aead_crypto_instance(inst), &alg->base);
89462306a36Sopenharmony_ci	if (err)
89562306a36Sopenharmony_ci		goto err_free_inst;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	inst->alg.base.cra_flags |= CRYPTO_ALG_ASYNC |
89862306a36Sopenharmony_ci		(alg->base.cra_flags & CRYPTO_ALG_INTERNAL);
89962306a36Sopenharmony_ci	inst->alg.base.cra_ctxsize = sizeof(struct cryptd_aead_ctx);
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	inst->alg.ivsize = crypto_aead_alg_ivsize(alg);
90262306a36Sopenharmony_ci	inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	inst->alg.init = cryptd_aead_init_tfm;
90562306a36Sopenharmony_ci	inst->alg.exit = cryptd_aead_exit_tfm;
90662306a36Sopenharmony_ci	inst->alg.setkey = cryptd_aead_setkey;
90762306a36Sopenharmony_ci	inst->alg.setauthsize = cryptd_aead_setauthsize;
90862306a36Sopenharmony_ci	inst->alg.encrypt = cryptd_aead_encrypt_enqueue;
90962306a36Sopenharmony_ci	inst->alg.decrypt = cryptd_aead_decrypt_enqueue;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	inst->free = cryptd_aead_free;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	err = aead_register_instance(tmpl, inst);
91462306a36Sopenharmony_ci	if (err) {
91562306a36Sopenharmony_cierr_free_inst:
91662306a36Sopenharmony_ci		cryptd_aead_free(inst);
91762306a36Sopenharmony_ci	}
91862306a36Sopenharmony_ci	return err;
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_cistatic struct cryptd_queue queue;
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_cistatic int cryptd_create(struct crypto_template *tmpl, struct rtattr **tb)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	struct crypto_attr_type *algt;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	algt = crypto_get_attr_type(tb);
92862306a36Sopenharmony_ci	if (IS_ERR(algt))
92962306a36Sopenharmony_ci		return PTR_ERR(algt);
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
93262306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
93362306a36Sopenharmony_ci		return cryptd_create_skcipher(tmpl, tb, algt, &queue);
93462306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_HASH:
93562306a36Sopenharmony_ci		return cryptd_create_hash(tmpl, tb, algt, &queue);
93662306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
93762306a36Sopenharmony_ci		return cryptd_create_aead(tmpl, tb, algt, &queue);
93862306a36Sopenharmony_ci	}
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	return -EINVAL;
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic struct crypto_template cryptd_tmpl = {
94462306a36Sopenharmony_ci	.name = "cryptd",
94562306a36Sopenharmony_ci	.create = cryptd_create,
94662306a36Sopenharmony_ci	.module = THIS_MODULE,
94762306a36Sopenharmony_ci};
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_cistruct cryptd_skcipher *cryptd_alloc_skcipher(const char *alg_name,
95062306a36Sopenharmony_ci					      u32 type, u32 mask)
95162306a36Sopenharmony_ci{
95262306a36Sopenharmony_ci	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
95362306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx;
95462306a36Sopenharmony_ci	struct crypto_skcipher *tfm;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
95762306a36Sopenharmony_ci		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
95862306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	tfm = crypto_alloc_skcipher(cryptd_alg_name, type, mask);
96162306a36Sopenharmony_ci	if (IS_ERR(tfm))
96262306a36Sopenharmony_ci		return ERR_CAST(tfm);
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
96562306a36Sopenharmony_ci		crypto_free_skcipher(tfm);
96662306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
96762306a36Sopenharmony_ci	}
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	ctx = crypto_skcipher_ctx(tfm);
97062306a36Sopenharmony_ci	refcount_set(&ctx->refcnt, 1);
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	return container_of(tfm, struct cryptd_skcipher, base);
97362306a36Sopenharmony_ci}
97462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_alloc_skcipher);
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_cistruct crypto_skcipher *cryptd_skcipher_child(struct cryptd_skcipher *tfm)
97762306a36Sopenharmony_ci{
97862306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	return ctx->child;
98162306a36Sopenharmony_ci}
98262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_skcipher_child);
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_cibool cryptd_skcipher_queued(struct cryptd_skcipher *tfm)
98562306a36Sopenharmony_ci{
98662306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	return refcount_read(&ctx->refcnt) - 1;
98962306a36Sopenharmony_ci}
99062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_skcipher_queued);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_civoid cryptd_free_skcipher(struct cryptd_skcipher *tfm)
99362306a36Sopenharmony_ci{
99462306a36Sopenharmony_ci	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	if (refcount_dec_and_test(&ctx->refcnt))
99762306a36Sopenharmony_ci		crypto_free_skcipher(&tfm->base);
99862306a36Sopenharmony_ci}
99962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_free_skcipher);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_cistruct cryptd_ahash *cryptd_alloc_ahash(const char *alg_name,
100262306a36Sopenharmony_ci					u32 type, u32 mask)
100362306a36Sopenharmony_ci{
100462306a36Sopenharmony_ci	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
100562306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx;
100662306a36Sopenharmony_ci	struct crypto_ahash *tfm;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
100962306a36Sopenharmony_ci		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
101062306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
101162306a36Sopenharmony_ci	tfm = crypto_alloc_ahash(cryptd_alg_name, type, mask);
101262306a36Sopenharmony_ci	if (IS_ERR(tfm))
101362306a36Sopenharmony_ci		return ERR_CAST(tfm);
101462306a36Sopenharmony_ci	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
101562306a36Sopenharmony_ci		crypto_free_ahash(tfm);
101662306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
101762306a36Sopenharmony_ci	}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	ctx = crypto_ahash_ctx(tfm);
102062306a36Sopenharmony_ci	refcount_set(&ctx->refcnt, 1);
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	return __cryptd_ahash_cast(tfm);
102362306a36Sopenharmony_ci}
102462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_alloc_ahash);
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_cistruct crypto_shash *cryptd_ahash_child(struct cryptd_ahash *tfm)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	return ctx->child;
103162306a36Sopenharmony_ci}
103262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_ahash_child);
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_cistruct shash_desc *cryptd_shash_desc(struct ahash_request *req)
103562306a36Sopenharmony_ci{
103662306a36Sopenharmony_ci	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
103762306a36Sopenharmony_ci	return &rctx->desc;
103862306a36Sopenharmony_ci}
103962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_shash_desc);
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_cibool cryptd_ahash_queued(struct cryptd_ahash *tfm)
104262306a36Sopenharmony_ci{
104362306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	return refcount_read(&ctx->refcnt) - 1;
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_ahash_queued);
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_civoid cryptd_free_ahash(struct cryptd_ahash *tfm)
105062306a36Sopenharmony_ci{
105162306a36Sopenharmony_ci	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	if (refcount_dec_and_test(&ctx->refcnt))
105462306a36Sopenharmony_ci		crypto_free_ahash(&tfm->base);
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_free_ahash);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_cistruct cryptd_aead *cryptd_alloc_aead(const char *alg_name,
105962306a36Sopenharmony_ci						  u32 type, u32 mask)
106062306a36Sopenharmony_ci{
106162306a36Sopenharmony_ci	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
106262306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx;
106362306a36Sopenharmony_ci	struct crypto_aead *tfm;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
106662306a36Sopenharmony_ci		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
106762306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
106862306a36Sopenharmony_ci	tfm = crypto_alloc_aead(cryptd_alg_name, type, mask);
106962306a36Sopenharmony_ci	if (IS_ERR(tfm))
107062306a36Sopenharmony_ci		return ERR_CAST(tfm);
107162306a36Sopenharmony_ci	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
107262306a36Sopenharmony_ci		crypto_free_aead(tfm);
107362306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
107462306a36Sopenharmony_ci	}
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	ctx = crypto_aead_ctx(tfm);
107762306a36Sopenharmony_ci	refcount_set(&ctx->refcnt, 1);
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	return __cryptd_aead_cast(tfm);
108062306a36Sopenharmony_ci}
108162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_alloc_aead);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_cistruct crypto_aead *cryptd_aead_child(struct cryptd_aead *tfm)
108462306a36Sopenharmony_ci{
108562306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx;
108662306a36Sopenharmony_ci	ctx = crypto_aead_ctx(&tfm->base);
108762306a36Sopenharmony_ci	return ctx->child;
108862306a36Sopenharmony_ci}
108962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_aead_child);
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_cibool cryptd_aead_queued(struct cryptd_aead *tfm)
109262306a36Sopenharmony_ci{
109362306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(&tfm->base);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	return refcount_read(&ctx->refcnt) - 1;
109662306a36Sopenharmony_ci}
109762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_aead_queued);
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_civoid cryptd_free_aead(struct cryptd_aead *tfm)
110062306a36Sopenharmony_ci{
110162306a36Sopenharmony_ci	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(&tfm->base);
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	if (refcount_dec_and_test(&ctx->refcnt))
110462306a36Sopenharmony_ci		crypto_free_aead(&tfm->base);
110562306a36Sopenharmony_ci}
110662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cryptd_free_aead);
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_cistatic int __init cryptd_init(void)
110962306a36Sopenharmony_ci{
111062306a36Sopenharmony_ci	int err;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	cryptd_wq = alloc_workqueue("cryptd", WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE,
111362306a36Sopenharmony_ci				    1);
111462306a36Sopenharmony_ci	if (!cryptd_wq)
111562306a36Sopenharmony_ci		return -ENOMEM;
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	err = cryptd_init_queue(&queue, cryptd_max_cpu_qlen);
111862306a36Sopenharmony_ci	if (err)
111962306a36Sopenharmony_ci		goto err_destroy_wq;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	err = crypto_register_template(&cryptd_tmpl);
112262306a36Sopenharmony_ci	if (err)
112362306a36Sopenharmony_ci		goto err_fini_queue;
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	return 0;
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_cierr_fini_queue:
112862306a36Sopenharmony_ci	cryptd_fini_queue(&queue);
112962306a36Sopenharmony_cierr_destroy_wq:
113062306a36Sopenharmony_ci	destroy_workqueue(cryptd_wq);
113162306a36Sopenharmony_ci	return err;
113262306a36Sopenharmony_ci}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_cistatic void __exit cryptd_exit(void)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci	destroy_workqueue(cryptd_wq);
113762306a36Sopenharmony_ci	cryptd_fini_queue(&queue);
113862306a36Sopenharmony_ci	crypto_unregister_template(&cryptd_tmpl);
113962306a36Sopenharmony_ci}
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_cisubsys_initcall(cryptd_init);
114262306a36Sopenharmony_cimodule_exit(cryptd_exit);
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
114562306a36Sopenharmony_ciMODULE_DESCRIPTION("Software async crypto daemon");
114662306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("cryptd");
1147