xref: /openbmc/linux/crypto/cryptd.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2124b53d0SHerbert Xu /*
3124b53d0SHerbert Xu  * Software async crypto daemon.
4124b53d0SHerbert Xu  *
5124b53d0SHerbert Xu  * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
6124b53d0SHerbert Xu  *
7298c926cSAdrian Hoban  * Added AEAD support to cryptd.
8298c926cSAdrian Hoban  *    Authors: Tadeusz Struk (tadeusz.struk@intel.com)
9298c926cSAdrian Hoban  *             Adrian Hoban <adrian.hoban@intel.com>
10298c926cSAdrian Hoban  *             Gabriele Paoloni <gabriele.paoloni@intel.com>
11298c926cSAdrian Hoban  *             Aidan O'Mahony (aidan.o.mahony@intel.com)
12298c926cSAdrian Hoban  *    Copyright (c) 2010, Intel Corporation.
13124b53d0SHerbert Xu  */
14124b53d0SHerbert Xu 
1518e33e6dSHerbert Xu #include <crypto/internal/hash.h>
16298c926cSAdrian Hoban #include <crypto/internal/aead.h>
174e0958d1SHerbert Xu #include <crypto/internal/skcipher.h>
181cac2cbcSHuang Ying #include <crypto/cryptd.h>
1943b970faSChuhong Yuan #include <linux/refcount.h>
20124b53d0SHerbert Xu #include <linux/err.h>
21124b53d0SHerbert Xu #include <linux/init.h>
22124b53d0SHerbert Xu #include <linux/kernel.h>
23124b53d0SHerbert Xu #include <linux/list.h>
24124b53d0SHerbert Xu #include <linux/module.h>
25124b53d0SHerbert Xu #include <linux/scatterlist.h>
26124b53d0SHerbert Xu #include <linux/sched.h>
27124b53d0SHerbert Xu #include <linux/slab.h>
283e56e168SEric Biggers #include <linux/workqueue.h>
29124b53d0SHerbert Xu 
30eaf356e4SColin Ian King static unsigned int cryptd_max_cpu_qlen = 1000;
31c3a53605SJon Maxwell module_param(cryptd_max_cpu_qlen, uint, 0);
32c3a53605SJon Maxwell MODULE_PARM_DESC(cryptd_max_cpu_qlen, "Set cryptd Max queue depth");
33124b53d0SHerbert Xu 
343e56e168SEric Biggers static struct workqueue_struct *cryptd_wq;
353e56e168SEric Biggers 
36254eff77SHuang Ying struct cryptd_cpu_queue {
37124b53d0SHerbert Xu 	struct crypto_queue queue;
38254eff77SHuang Ying 	struct work_struct work;
39254eff77SHuang Ying };
40254eff77SHuang Ying 
41254eff77SHuang Ying struct cryptd_queue {
4291e8bcd7SSebastian Andrzej Siewior 	/*
4391e8bcd7SSebastian Andrzej Siewior 	 * Protected by disabling BH to allow enqueueing from softinterrupt and
4491e8bcd7SSebastian Andrzej Siewior 	 * dequeuing from kworker (cryptd_queue_worker()).
4591e8bcd7SSebastian Andrzej Siewior 	 */
46a29d8b8eSTejun Heo 	struct cryptd_cpu_queue __percpu *cpu_queue;
47124b53d0SHerbert Xu };
48124b53d0SHerbert Xu 
49124b53d0SHerbert Xu struct cryptd_instance_ctx {
50124b53d0SHerbert Xu 	struct crypto_spawn spawn;
51254eff77SHuang Ying 	struct cryptd_queue *queue;
52124b53d0SHerbert Xu };
53124b53d0SHerbert Xu 
544e0958d1SHerbert Xu struct skcipherd_instance_ctx {
554e0958d1SHerbert Xu 	struct crypto_skcipher_spawn spawn;
564e0958d1SHerbert Xu 	struct cryptd_queue *queue;
574e0958d1SHerbert Xu };
584e0958d1SHerbert Xu 
5946309d89SHerbert Xu struct hashd_instance_ctx {
6046309d89SHerbert Xu 	struct crypto_shash_spawn spawn;
6146309d89SHerbert Xu 	struct cryptd_queue *queue;
6246309d89SHerbert Xu };
6346309d89SHerbert Xu 
64298c926cSAdrian Hoban struct aead_instance_ctx {
65298c926cSAdrian Hoban 	struct crypto_aead_spawn aead_spawn;
66298c926cSAdrian Hoban 	struct cryptd_queue *queue;
67298c926cSAdrian Hoban };
68298c926cSAdrian Hoban 
694e0958d1SHerbert Xu struct cryptd_skcipher_ctx {
7043b970faSChuhong Yuan 	refcount_t refcnt;
713a58c231SHerbert Xu 	struct crypto_skcipher *child;
724e0958d1SHerbert Xu };
734e0958d1SHerbert Xu 
744e0958d1SHerbert Xu struct cryptd_skcipher_request_ctx {
753a58c231SHerbert Xu 	struct skcipher_request req;
764e0958d1SHerbert Xu };
774e0958d1SHerbert Xu 
78b8a28251SLoc Ho struct cryptd_hash_ctx {
7943b970faSChuhong Yuan 	refcount_t refcnt;
8046309d89SHerbert Xu 	struct crypto_shash *child;
81b8a28251SLoc Ho };
82b8a28251SLoc Ho 
83b8a28251SLoc Ho struct cryptd_hash_request_ctx {
84b8a28251SLoc Ho 	crypto_completion_t complete;
85f27c94aaSHerbert Xu 	void *data;
8646309d89SHerbert Xu 	struct shash_desc desc;
87b8a28251SLoc Ho };
88124b53d0SHerbert Xu 
89298c926cSAdrian Hoban struct cryptd_aead_ctx {
9043b970faSChuhong Yuan 	refcount_t refcnt;
91298c926cSAdrian Hoban 	struct crypto_aead *child;
92298c926cSAdrian Hoban };
93298c926cSAdrian Hoban 
94298c926cSAdrian Hoban struct cryptd_aead_request_ctx {
95256f9e53SHerbert Xu 	struct aead_request req;
96298c926cSAdrian Hoban };
97298c926cSAdrian Hoban 
98254eff77SHuang Ying static void cryptd_queue_worker(struct work_struct *work);
99254eff77SHuang Ying 
cryptd_init_queue(struct cryptd_queue * queue,unsigned int max_cpu_qlen)100254eff77SHuang Ying static int cryptd_init_queue(struct cryptd_queue *queue,
101254eff77SHuang Ying 			     unsigned int max_cpu_qlen)
102254eff77SHuang Ying {
103254eff77SHuang Ying 	int cpu;
104254eff77SHuang Ying 	struct cryptd_cpu_queue *cpu_queue;
105254eff77SHuang Ying 
106254eff77SHuang Ying 	queue->cpu_queue = alloc_percpu(struct cryptd_cpu_queue);
107254eff77SHuang Ying 	if (!queue->cpu_queue)
108254eff77SHuang Ying 		return -ENOMEM;
109254eff77SHuang Ying 	for_each_possible_cpu(cpu) {
110254eff77SHuang Ying 		cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
111254eff77SHuang Ying 		crypto_init_queue(&cpu_queue->queue, max_cpu_qlen);
112254eff77SHuang Ying 		INIT_WORK(&cpu_queue->work, cryptd_queue_worker);
113254eff77SHuang Ying 	}
114c3a53605SJon Maxwell 	pr_info("cryptd: max_cpu_qlen set to %d\n", max_cpu_qlen);
115254eff77SHuang Ying 	return 0;
116254eff77SHuang Ying }
117254eff77SHuang Ying 
cryptd_fini_queue(struct cryptd_queue * queue)118254eff77SHuang Ying static void cryptd_fini_queue(struct cryptd_queue *queue)
119254eff77SHuang Ying {
120254eff77SHuang Ying 	int cpu;
121254eff77SHuang Ying 	struct cryptd_cpu_queue *cpu_queue;
122254eff77SHuang Ying 
123254eff77SHuang Ying 	for_each_possible_cpu(cpu) {
124254eff77SHuang Ying 		cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
125254eff77SHuang Ying 		BUG_ON(cpu_queue->queue.qlen);
126254eff77SHuang Ying 	}
127254eff77SHuang Ying 	free_percpu(queue->cpu_queue);
128254eff77SHuang Ying }
129254eff77SHuang Ying 
cryptd_enqueue_request(struct cryptd_queue * queue,struct crypto_async_request * request)130254eff77SHuang Ying static int cryptd_enqueue_request(struct cryptd_queue *queue,
131254eff77SHuang Ying 				  struct crypto_async_request *request)
132254eff77SHuang Ying {
13391e8bcd7SSebastian Andrzej Siewior 	int err;
134254eff77SHuang Ying 	struct cryptd_cpu_queue *cpu_queue;
13543b970faSChuhong Yuan 	refcount_t *refcnt;
136254eff77SHuang Ying 
13791e8bcd7SSebastian Andrzej Siewior 	local_bh_disable();
1380b44f486SChristoph Lameter 	cpu_queue = this_cpu_ptr(queue->cpu_queue);
139254eff77SHuang Ying 	err = crypto_enqueue_request(&cpu_queue->queue, request);
14081760ea6SHerbert Xu 
14181760ea6SHerbert Xu 	refcnt = crypto_tfm_ctx(request->tfm);
14281760ea6SHerbert Xu 
1436b80ea38SGilad Ben-Yossef 	if (err == -ENOSPC)
14491e8bcd7SSebastian Andrzej Siewior 		goto out;
14581760ea6SHerbert Xu 
14691e8bcd7SSebastian Andrzej Siewior 	queue_work_on(smp_processor_id(), cryptd_wq, &cpu_queue->work);
14781760ea6SHerbert Xu 
14843b970faSChuhong Yuan 	if (!refcount_read(refcnt))
14991e8bcd7SSebastian Andrzej Siewior 		goto out;
15081760ea6SHerbert Xu 
15143b970faSChuhong Yuan 	refcount_inc(refcnt);
15281760ea6SHerbert Xu 
15391e8bcd7SSebastian Andrzej Siewior out:
15491e8bcd7SSebastian Andrzej Siewior 	local_bh_enable();
155254eff77SHuang Ying 
156254eff77SHuang Ying 	return err;
157254eff77SHuang Ying }
158254eff77SHuang Ying 
159254eff77SHuang Ying /* Called in workqueue context, do one real cryption work (via
160254eff77SHuang Ying  * req->complete) and reschedule itself if there are more work to
161254eff77SHuang Ying  * do. */
cryptd_queue_worker(struct work_struct * work)162254eff77SHuang Ying static void cryptd_queue_worker(struct work_struct *work)
163254eff77SHuang Ying {
164254eff77SHuang Ying 	struct cryptd_cpu_queue *cpu_queue;
165254eff77SHuang Ying 	struct crypto_async_request *req, *backlog;
166254eff77SHuang Ying 
167254eff77SHuang Ying 	cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
1689efade1bSJussi Kivilinna 	/*
1699efade1bSJussi Kivilinna 	 * Only handle one request at a time to avoid hogging crypto workqueue.
1709efade1bSJussi Kivilinna 	 */
1719efade1bSJussi Kivilinna 	local_bh_disable();
172254eff77SHuang Ying 	backlog = crypto_get_backlog(&cpu_queue->queue);
173254eff77SHuang Ying 	req = crypto_dequeue_request(&cpu_queue->queue);
1749efade1bSJussi Kivilinna 	local_bh_enable();
175254eff77SHuang Ying 
176254eff77SHuang Ying 	if (!req)
177254eff77SHuang Ying 		return;
178254eff77SHuang Ying 
179254eff77SHuang Ying 	if (backlog)
180f27c94aaSHerbert Xu 		crypto_request_complete(backlog, -EINPROGRESS);
181f27c94aaSHerbert Xu 	crypto_request_complete(req, 0);
182254eff77SHuang Ying 
183254eff77SHuang Ying 	if (cpu_queue->queue.qlen)
1843e56e168SEric Biggers 		queue_work(cryptd_wq, &cpu_queue->work);
185254eff77SHuang Ying }
186254eff77SHuang Ying 
cryptd_get_queue(struct crypto_tfm * tfm)187254eff77SHuang Ying static inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm)
188124b53d0SHerbert Xu {
189124b53d0SHerbert Xu 	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
190124b53d0SHerbert Xu 	struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
191254eff77SHuang Ying 	return ictx->queue;
192124b53d0SHerbert Xu }
193124b53d0SHerbert Xu 
cryptd_type_and_mask(struct crypto_attr_type * algt,u32 * type,u32 * mask)1947bcb2c99SEric Biggers static void cryptd_type_and_mask(struct crypto_attr_type *algt,
1957bcb2c99SEric Biggers 				 u32 *type, u32 *mask)
196466a7b9eSStephan Mueller {
1977bcb2c99SEric Biggers 	/*
1987bcb2c99SEric Biggers 	 * cryptd is allowed to wrap internal algorithms, but in that case the
1997bcb2c99SEric Biggers 	 * resulting cryptd instance will be marked as internal as well.
2007bcb2c99SEric Biggers 	 */
2017bcb2c99SEric Biggers 	*type = algt->type & CRYPTO_ALG_INTERNAL;
2027bcb2c99SEric Biggers 	*mask = algt->mask & CRYPTO_ALG_INTERNAL;
203466a7b9eSStephan Mueller 
2047bcb2c99SEric Biggers 	/* No point in cryptd wrapping an algorithm that's already async. */
2057bcb2c99SEric Biggers 	*mask |= CRYPTO_ALG_ASYNC;
206f6da3205SHerbert Xu 
2077bcb2c99SEric Biggers 	*mask |= crypto_algt_inherited_mask(algt);
208466a7b9eSStephan Mueller }
209466a7b9eSStephan Mueller 
cryptd_init_instance(struct crypto_instance * inst,struct crypto_alg * alg)2109b8c456eSHerbert Xu static int cryptd_init_instance(struct crypto_instance *inst,
2119b8c456eSHerbert Xu 				struct crypto_alg *alg)
2129b8c456eSHerbert Xu {
2139b8c456eSHerbert Xu 	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
2149b8c456eSHerbert Xu 		     "cryptd(%s)",
2159b8c456eSHerbert Xu 		     alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
2169b8c456eSHerbert Xu 		return -ENAMETOOLONG;
2179b8c456eSHerbert Xu 
2189b8c456eSHerbert Xu 	memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
2199b8c456eSHerbert Xu 
2209b8c456eSHerbert Xu 	inst->alg.cra_priority = alg->cra_priority + 50;
2219b8c456eSHerbert Xu 	inst->alg.cra_blocksize = alg->cra_blocksize;
2229b8c456eSHerbert Xu 	inst->alg.cra_alignmask = alg->cra_alignmask;
2239b8c456eSHerbert Xu 
2249b8c456eSHerbert Xu 	return 0;
2259b8c456eSHerbert Xu }
2269b8c456eSHerbert Xu 
cryptd_skcipher_setkey(struct crypto_skcipher * parent,const u8 * key,unsigned int keylen)2274e0958d1SHerbert Xu static int cryptd_skcipher_setkey(struct crypto_skcipher *parent,
2284e0958d1SHerbert Xu 				  const u8 *key, unsigned int keylen)
2294e0958d1SHerbert Xu {
2304e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(parent);
2313a58c231SHerbert Xu 	struct crypto_skcipher *child = ctx->child;
2324e0958d1SHerbert Xu 
2333a58c231SHerbert Xu 	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
2343a58c231SHerbert Xu 	crypto_skcipher_set_flags(child,
23536b3875aSKees Cook 				  crypto_skcipher_get_flags(parent) &
2364e0958d1SHerbert Xu 				  CRYPTO_TFM_REQ_MASK);
2373a58c231SHerbert Xu 	return crypto_skcipher_setkey(child, key, keylen);
2384e0958d1SHerbert Xu }
2394e0958d1SHerbert Xu 
cryptd_skcipher_prepare(struct skcipher_request * req,int err)240f27c94aaSHerbert Xu static struct skcipher_request *cryptd_skcipher_prepare(
241f27c94aaSHerbert Xu 	struct skcipher_request *req, int err)
2424e0958d1SHerbert Xu {
243f27c94aaSHerbert Xu 	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
244f27c94aaSHerbert Xu 	struct skcipher_request *subreq = &rctx->req;
245f27c94aaSHerbert Xu 	struct cryptd_skcipher_ctx *ctx;
246f27c94aaSHerbert Xu 	struct crypto_skcipher *child;
247f27c94aaSHerbert Xu 
248f27c94aaSHerbert Xu 	req->base.complete = subreq->base.complete;
249f27c94aaSHerbert Xu 	req->base.data = subreq->base.data;
250f27c94aaSHerbert Xu 
251f27c94aaSHerbert Xu 	if (unlikely(err == -EINPROGRESS))
252f27c94aaSHerbert Xu 		return NULL;
253f27c94aaSHerbert Xu 
254f27c94aaSHerbert Xu 	ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
255f27c94aaSHerbert Xu 	child = ctx->child;
256f27c94aaSHerbert Xu 
257f27c94aaSHerbert Xu 	skcipher_request_set_tfm(subreq, child);
258f27c94aaSHerbert Xu 	skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP,
259f27c94aaSHerbert Xu 				      NULL, NULL);
260f27c94aaSHerbert Xu 	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
261f27c94aaSHerbert Xu 				   req->iv);
262f27c94aaSHerbert Xu 
263f27c94aaSHerbert Xu 	return subreq;
264f27c94aaSHerbert Xu }
265f27c94aaSHerbert Xu 
cryptd_skcipher_complete(struct skcipher_request * req,int err,crypto_completion_t complete)266f27c94aaSHerbert Xu static void cryptd_skcipher_complete(struct skcipher_request *req, int err,
267f27c94aaSHerbert Xu 				     crypto_completion_t complete)
268f27c94aaSHerbert Xu {
269f27c94aaSHerbert Xu 	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
2704e0958d1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
2714e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
272f27c94aaSHerbert Xu 	struct skcipher_request *subreq = &rctx->req;
27343b970faSChuhong Yuan 	int refcnt = refcount_read(&ctx->refcnt);
2744e0958d1SHerbert Xu 
2754e0958d1SHerbert Xu 	local_bh_disable();
276f27c94aaSHerbert Xu 	skcipher_request_complete(req, err);
2774e0958d1SHerbert Xu 	local_bh_enable();
2784e0958d1SHerbert Xu 
279f27c94aaSHerbert Xu 	if (unlikely(err == -EINPROGRESS)) {
280f27c94aaSHerbert Xu 		subreq->base.complete = req->base.complete;
281f27c94aaSHerbert Xu 		subreq->base.data = req->base.data;
282f27c94aaSHerbert Xu 		req->base.complete = complete;
283f27c94aaSHerbert Xu 		req->base.data = req;
284f27c94aaSHerbert Xu 	} else if (refcnt && refcount_dec_and_test(&ctx->refcnt))
2854e0958d1SHerbert Xu 		crypto_free_skcipher(tfm);
2864e0958d1SHerbert Xu }
2874e0958d1SHerbert Xu 
cryptd_skcipher_encrypt(void * data,int err)288255e48ebSHerbert Xu static void cryptd_skcipher_encrypt(void *data, int err)
2894e0958d1SHerbert Xu {
290255e48ebSHerbert Xu 	struct skcipher_request *req = data;
291f27c94aaSHerbert Xu 	struct skcipher_request *subreq;
2924e0958d1SHerbert Xu 
293f27c94aaSHerbert Xu 	subreq = cryptd_skcipher_prepare(req, err);
294f27c94aaSHerbert Xu 	if (likely(subreq))
2954e0958d1SHerbert Xu 		err = crypto_skcipher_encrypt(subreq);
2964e0958d1SHerbert Xu 
297f27c94aaSHerbert Xu 	cryptd_skcipher_complete(req, err, cryptd_skcipher_encrypt);
2984e0958d1SHerbert Xu }
2994e0958d1SHerbert Xu 
cryptd_skcipher_decrypt(void * data,int err)300255e48ebSHerbert Xu static void cryptd_skcipher_decrypt(void *data, int err)
3014e0958d1SHerbert Xu {
302255e48ebSHerbert Xu 	struct skcipher_request *req = data;
303f27c94aaSHerbert Xu 	struct skcipher_request *subreq;
3044e0958d1SHerbert Xu 
305f27c94aaSHerbert Xu 	subreq = cryptd_skcipher_prepare(req, err);
306f27c94aaSHerbert Xu 	if (likely(subreq))
3074e0958d1SHerbert Xu 		err = crypto_skcipher_decrypt(subreq);
3084e0958d1SHerbert Xu 
309f27c94aaSHerbert Xu 	cryptd_skcipher_complete(req, err, cryptd_skcipher_decrypt);
3104e0958d1SHerbert Xu }
3114e0958d1SHerbert Xu 
cryptd_skcipher_enqueue(struct skcipher_request * req,crypto_completion_t compl)3124e0958d1SHerbert Xu static int cryptd_skcipher_enqueue(struct skcipher_request *req,
3134e0958d1SHerbert Xu 				   crypto_completion_t compl)
3144e0958d1SHerbert Xu {
3154e0958d1SHerbert Xu 	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
3164e0958d1SHerbert Xu 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
317f27c94aaSHerbert Xu 	struct skcipher_request *subreq = &rctx->req;
3184e0958d1SHerbert Xu 	struct cryptd_queue *queue;
3194e0958d1SHerbert Xu 
3204e0958d1SHerbert Xu 	queue = cryptd_get_queue(crypto_skcipher_tfm(tfm));
321f27c94aaSHerbert Xu 	subreq->base.complete = req->base.complete;
322f27c94aaSHerbert Xu 	subreq->base.data = req->base.data;
3234e0958d1SHerbert Xu 	req->base.complete = compl;
324f27c94aaSHerbert Xu 	req->base.data = req;
3254e0958d1SHerbert Xu 
3264e0958d1SHerbert Xu 	return cryptd_enqueue_request(queue, &req->base);
3274e0958d1SHerbert Xu }
3284e0958d1SHerbert Xu 
cryptd_skcipher_encrypt_enqueue(struct skcipher_request * req)3294e0958d1SHerbert Xu static int cryptd_skcipher_encrypt_enqueue(struct skcipher_request *req)
3304e0958d1SHerbert Xu {
3314e0958d1SHerbert Xu 	return cryptd_skcipher_enqueue(req, cryptd_skcipher_encrypt);
3324e0958d1SHerbert Xu }
3334e0958d1SHerbert Xu 
cryptd_skcipher_decrypt_enqueue(struct skcipher_request * req)3344e0958d1SHerbert Xu static int cryptd_skcipher_decrypt_enqueue(struct skcipher_request *req)
3354e0958d1SHerbert Xu {
3364e0958d1SHerbert Xu 	return cryptd_skcipher_enqueue(req, cryptd_skcipher_decrypt);
3374e0958d1SHerbert Xu }
3384e0958d1SHerbert Xu 
cryptd_skcipher_init_tfm(struct crypto_skcipher * tfm)3394e0958d1SHerbert Xu static int cryptd_skcipher_init_tfm(struct crypto_skcipher *tfm)
3404e0958d1SHerbert Xu {
3414e0958d1SHerbert Xu 	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
3424e0958d1SHerbert Xu 	struct skcipherd_instance_ctx *ictx = skcipher_instance_ctx(inst);
3434e0958d1SHerbert Xu 	struct crypto_skcipher_spawn *spawn = &ictx->spawn;
3444e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
3454e0958d1SHerbert Xu 	struct crypto_skcipher *cipher;
3464e0958d1SHerbert Xu 
3474e0958d1SHerbert Xu 	cipher = crypto_spawn_skcipher(spawn);
3484e0958d1SHerbert Xu 	if (IS_ERR(cipher))
3494e0958d1SHerbert Xu 		return PTR_ERR(cipher);
3504e0958d1SHerbert Xu 
3513a58c231SHerbert Xu 	ctx->child = cipher;
3524e0958d1SHerbert Xu 	crypto_skcipher_set_reqsize(
3533a58c231SHerbert Xu 		tfm, sizeof(struct cryptd_skcipher_request_ctx) +
3543a58c231SHerbert Xu 		     crypto_skcipher_reqsize(cipher));
3554e0958d1SHerbert Xu 	return 0;
3564e0958d1SHerbert Xu }
3574e0958d1SHerbert Xu 
cryptd_skcipher_exit_tfm(struct crypto_skcipher * tfm)3584e0958d1SHerbert Xu static void cryptd_skcipher_exit_tfm(struct crypto_skcipher *tfm)
3594e0958d1SHerbert Xu {
3604e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
3614e0958d1SHerbert Xu 
3623a58c231SHerbert Xu 	crypto_free_skcipher(ctx->child);
3634e0958d1SHerbert Xu }
3644e0958d1SHerbert Xu 
cryptd_skcipher_free(struct skcipher_instance * inst)3654e0958d1SHerbert Xu static void cryptd_skcipher_free(struct skcipher_instance *inst)
3664e0958d1SHerbert Xu {
3674e0958d1SHerbert Xu 	struct skcipherd_instance_ctx *ctx = skcipher_instance_ctx(inst);
3684e0958d1SHerbert Xu 
3694e0958d1SHerbert Xu 	crypto_drop_skcipher(&ctx->spawn);
3701a0fad63SVincent Whitchurch 	kfree(inst);
3714e0958d1SHerbert Xu }
3724e0958d1SHerbert Xu 
cryptd_create_skcipher(struct crypto_template * tmpl,struct rtattr ** tb,struct crypto_attr_type * algt,struct cryptd_queue * queue)3734e0958d1SHerbert Xu static int cryptd_create_skcipher(struct crypto_template *tmpl,
3744e0958d1SHerbert Xu 				  struct rtattr **tb,
3757bcb2c99SEric Biggers 				  struct crypto_attr_type *algt,
3764e0958d1SHerbert Xu 				  struct cryptd_queue *queue)
3774e0958d1SHerbert Xu {
3784e0958d1SHerbert Xu 	struct skcipherd_instance_ctx *ctx;
3794e0958d1SHerbert Xu 	struct skcipher_instance *inst;
3804e0958d1SHerbert Xu 	struct skcipher_alg *alg;
3814e0958d1SHerbert Xu 	u32 type;
3824e0958d1SHerbert Xu 	u32 mask;
3834e0958d1SHerbert Xu 	int err;
3844e0958d1SHerbert Xu 
3857bcb2c99SEric Biggers 	cryptd_type_and_mask(algt, &type, &mask);
3864e0958d1SHerbert Xu 
3874e0958d1SHerbert Xu 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
3884e0958d1SHerbert Xu 	if (!inst)
3894e0958d1SHerbert Xu 		return -ENOMEM;
3904e0958d1SHerbert Xu 
3914e0958d1SHerbert Xu 	ctx = skcipher_instance_ctx(inst);
3924e0958d1SHerbert Xu 	ctx->queue = queue;
3934e0958d1SHerbert Xu 
394b9f76dddSEric Biggers 	err = crypto_grab_skcipher(&ctx->spawn, skcipher_crypto_instance(inst),
395b8c0d74aSEric Biggers 				   crypto_attr_alg_name(tb[1]), type, mask);
3964e0958d1SHerbert Xu 	if (err)
397b8c0d74aSEric Biggers 		goto err_free_inst;
3984e0958d1SHerbert Xu 
3994e0958d1SHerbert Xu 	alg = crypto_spawn_skcipher_alg(&ctx->spawn);
4004e0958d1SHerbert Xu 	err = cryptd_init_instance(skcipher_crypto_instance(inst), &alg->base);
4014e0958d1SHerbert Xu 	if (err)
402b8c0d74aSEric Biggers 		goto err_free_inst;
4034e0958d1SHerbert Xu 
4047bcb2c99SEric Biggers 	inst->alg.base.cra_flags |= CRYPTO_ALG_ASYNC |
4054e0958d1SHerbert Xu 		(alg->base.cra_flags & CRYPTO_ALG_INTERNAL);
4064e0958d1SHerbert Xu 	inst->alg.ivsize = crypto_skcipher_alg_ivsize(alg);
4074e0958d1SHerbert Xu 	inst->alg.chunksize = crypto_skcipher_alg_chunksize(alg);
4084e0958d1SHerbert Xu 	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg);
4094e0958d1SHerbert Xu 	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg);
4104e0958d1SHerbert Xu 
4114e0958d1SHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct cryptd_skcipher_ctx);
4124e0958d1SHerbert Xu 
4134e0958d1SHerbert Xu 	inst->alg.init = cryptd_skcipher_init_tfm;
4144e0958d1SHerbert Xu 	inst->alg.exit = cryptd_skcipher_exit_tfm;
4154e0958d1SHerbert Xu 
4164e0958d1SHerbert Xu 	inst->alg.setkey = cryptd_skcipher_setkey;
4174e0958d1SHerbert Xu 	inst->alg.encrypt = cryptd_skcipher_encrypt_enqueue;
4184e0958d1SHerbert Xu 	inst->alg.decrypt = cryptd_skcipher_decrypt_enqueue;
4194e0958d1SHerbert Xu 
4204e0958d1SHerbert Xu 	inst->free = cryptd_skcipher_free;
4214e0958d1SHerbert Xu 
4224e0958d1SHerbert Xu 	err = skcipher_register_instance(tmpl, inst);
4234e0958d1SHerbert Xu 	if (err) {
424b8c0d74aSEric Biggers err_free_inst:
425b8c0d74aSEric Biggers 		cryptd_skcipher_free(inst);
4264e0958d1SHerbert Xu 	}
4274e0958d1SHerbert Xu 	return err;
4284e0958d1SHerbert Xu }
4294e0958d1SHerbert Xu 
cryptd_hash_init_tfm(struct crypto_ahash * tfm)4300303b7f5SHerbert Xu static int cryptd_hash_init_tfm(struct crypto_ahash *tfm)
431b8a28251SLoc Ho {
4320303b7f5SHerbert Xu 	struct ahash_instance *inst = ahash_alg_instance(tfm);
4330303b7f5SHerbert Xu 	struct hashd_instance_ctx *ictx = ahash_instance_ctx(inst);
43446309d89SHerbert Xu 	struct crypto_shash_spawn *spawn = &ictx->spawn;
4350303b7f5SHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
43646309d89SHerbert Xu 	struct crypto_shash *hash;
437b8a28251SLoc Ho 
43846309d89SHerbert Xu 	hash = crypto_spawn_shash(spawn);
43946309d89SHerbert Xu 	if (IS_ERR(hash))
44046309d89SHerbert Xu 		return PTR_ERR(hash);
441b8a28251SLoc Ho 
44246309d89SHerbert Xu 	ctx->child = hash;
4430303b7f5SHerbert Xu 	crypto_ahash_set_reqsize(tfm,
4440d6669e2SHerbert Xu 				 sizeof(struct cryptd_hash_request_ctx) +
4450d6669e2SHerbert Xu 				 crypto_shash_descsize(hash));
446b8a28251SLoc Ho 	return 0;
447b8a28251SLoc Ho }
448b8a28251SLoc Ho 
cryptd_hash_clone_tfm(struct crypto_ahash * ntfm,struct crypto_ahash * tfm)449*cfbda734SHerbert Xu static int cryptd_hash_clone_tfm(struct crypto_ahash *ntfm,
450*cfbda734SHerbert Xu 				 struct crypto_ahash *tfm)
451*cfbda734SHerbert Xu {
452*cfbda734SHerbert Xu 	struct cryptd_hash_ctx *nctx = crypto_ahash_ctx(ntfm);
453*cfbda734SHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
454*cfbda734SHerbert Xu 	struct crypto_shash *hash;
455*cfbda734SHerbert Xu 
456*cfbda734SHerbert Xu 	hash = crypto_clone_shash(ctx->child);
457*cfbda734SHerbert Xu 	if (IS_ERR(hash))
458*cfbda734SHerbert Xu 		return PTR_ERR(hash);
459*cfbda734SHerbert Xu 
460*cfbda734SHerbert Xu 	nctx->child = hash;
461*cfbda734SHerbert Xu 	return 0;
462*cfbda734SHerbert Xu }
463*cfbda734SHerbert Xu 
cryptd_hash_exit_tfm(struct crypto_ahash * tfm)4640303b7f5SHerbert Xu static void cryptd_hash_exit_tfm(struct crypto_ahash *tfm)
465b8a28251SLoc Ho {
4660303b7f5SHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
467b8a28251SLoc Ho 
46846309d89SHerbert Xu 	crypto_free_shash(ctx->child);
469b8a28251SLoc Ho }
470b8a28251SLoc Ho 
cryptd_hash_setkey(struct crypto_ahash * parent,const u8 * key,unsigned int keylen)471b8a28251SLoc Ho static int cryptd_hash_setkey(struct crypto_ahash *parent,
472b8a28251SLoc Ho 				   const u8 *key, unsigned int keylen)
473b8a28251SLoc Ho {
474b8a28251SLoc Ho 	struct cryptd_hash_ctx *ctx   = crypto_ahash_ctx(parent);
47546309d89SHerbert Xu 	struct crypto_shash *child = ctx->child;
476b8a28251SLoc Ho 
47746309d89SHerbert Xu 	crypto_shash_clear_flags(child, CRYPTO_TFM_REQ_MASK);
47846309d89SHerbert Xu 	crypto_shash_set_flags(child, crypto_ahash_get_flags(parent) &
479b8a28251SLoc Ho 				      CRYPTO_TFM_REQ_MASK);
480af5034e8SEric Biggers 	return crypto_shash_setkey(child, key, keylen);
481b8a28251SLoc Ho }
482b8a28251SLoc Ho 
cryptd_hash_enqueue(struct ahash_request * req,crypto_completion_t compl)483b8a28251SLoc Ho static int cryptd_hash_enqueue(struct ahash_request *req,
4843e3dc25fSMark Rustad 				crypto_completion_t compl)
485b8a28251SLoc Ho {
486b8a28251SLoc Ho 	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
487b8a28251SLoc Ho 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
488254eff77SHuang Ying 	struct cryptd_queue *queue =
489254eff77SHuang Ying 		cryptd_get_queue(crypto_ahash_tfm(tfm));
490b8a28251SLoc Ho 
491b8a28251SLoc Ho 	rctx->complete = req->base.complete;
492f27c94aaSHerbert Xu 	rctx->data = req->base.data;
4933e3dc25fSMark Rustad 	req->base.complete = compl;
494f27c94aaSHerbert Xu 	req->base.data = req;
495b8a28251SLoc Ho 
496254eff77SHuang Ying 	return cryptd_enqueue_request(queue, &req->base);
497b8a28251SLoc Ho }
498b8a28251SLoc Ho 
cryptd_hash_prepare(struct ahash_request * req,int err)499f27c94aaSHerbert Xu static struct shash_desc *cryptd_hash_prepare(struct ahash_request *req,
500f27c94aaSHerbert Xu 					      int err)
501f27c94aaSHerbert Xu {
502f27c94aaSHerbert Xu 	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
503f27c94aaSHerbert Xu 
504f27c94aaSHerbert Xu 	req->base.complete = rctx->complete;
505f27c94aaSHerbert Xu 	req->base.data = rctx->data;
506f27c94aaSHerbert Xu 
507f27c94aaSHerbert Xu 	if (unlikely(err == -EINPROGRESS))
508f27c94aaSHerbert Xu 		return NULL;
509f27c94aaSHerbert Xu 
510f27c94aaSHerbert Xu 	return &rctx->desc;
511f27c94aaSHerbert Xu }
512f27c94aaSHerbert Xu 
cryptd_hash_complete(struct ahash_request * req,int err,crypto_completion_t complete)513f27c94aaSHerbert Xu static void cryptd_hash_complete(struct ahash_request *req, int err,
514f27c94aaSHerbert Xu 				 crypto_completion_t complete)
51581760ea6SHerbert Xu {
51681760ea6SHerbert Xu 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
51781760ea6SHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
51843b970faSChuhong Yuan 	int refcnt = refcount_read(&ctx->refcnt);
51981760ea6SHerbert Xu 
52081760ea6SHerbert Xu 	local_bh_disable();
521f27c94aaSHerbert Xu 	ahash_request_complete(req, err);
52281760ea6SHerbert Xu 	local_bh_enable();
52381760ea6SHerbert Xu 
524f27c94aaSHerbert Xu 	if (err == -EINPROGRESS) {
525f27c94aaSHerbert Xu 		req->base.complete = complete;
526f27c94aaSHerbert Xu 		req->base.data = req;
527f27c94aaSHerbert Xu 	} else if (refcnt && refcount_dec_and_test(&ctx->refcnt))
52881760ea6SHerbert Xu 		crypto_free_ahash(tfm);
52981760ea6SHerbert Xu }
53081760ea6SHerbert Xu 
cryptd_hash_init(void * data,int err)531255e48ebSHerbert Xu static void cryptd_hash_init(void *data, int err)
532b8a28251SLoc Ho {
533255e48ebSHerbert Xu 	struct ahash_request *req = data;
534f27c94aaSHerbert Xu 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
535f27c94aaSHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
536f27c94aaSHerbert Xu 	struct crypto_shash *child = ctx->child;
537f27c94aaSHerbert Xu 	struct shash_desc *desc;
538b8a28251SLoc Ho 
539f27c94aaSHerbert Xu 	desc = cryptd_hash_prepare(req, err);
540f27c94aaSHerbert Xu 	if (unlikely(!desc))
541b8a28251SLoc Ho 		goto out;
542b8a28251SLoc Ho 
54346309d89SHerbert Xu 	desc->tfm = child;
544b8a28251SLoc Ho 
54546309d89SHerbert Xu 	err = crypto_shash_init(desc);
546b8a28251SLoc Ho 
547b8a28251SLoc Ho out:
548f27c94aaSHerbert Xu 	cryptd_hash_complete(req, err, cryptd_hash_init);
549b8a28251SLoc Ho }
550b8a28251SLoc Ho 
cryptd_hash_init_enqueue(struct ahash_request * req)551b8a28251SLoc Ho static int cryptd_hash_init_enqueue(struct ahash_request *req)
552b8a28251SLoc Ho {
553b8a28251SLoc Ho 	return cryptd_hash_enqueue(req, cryptd_hash_init);
554b8a28251SLoc Ho }
555b8a28251SLoc Ho 
cryptd_hash_update(void * data,int err)556255e48ebSHerbert Xu static void cryptd_hash_update(void *data, int err)
557b8a28251SLoc Ho {
558255e48ebSHerbert Xu 	struct ahash_request *req = data;
559f27c94aaSHerbert Xu 	struct shash_desc *desc;
560b8a28251SLoc Ho 
561f27c94aaSHerbert Xu 	desc = cryptd_hash_prepare(req, err);
562f27c94aaSHerbert Xu 	if (likely(desc))
563f27c94aaSHerbert Xu 		err = shash_ahash_update(req, desc);
564b8a28251SLoc Ho 
565f27c94aaSHerbert Xu 	cryptd_hash_complete(req, err, cryptd_hash_update);
566b8a28251SLoc Ho }
567b8a28251SLoc Ho 
cryptd_hash_update_enqueue(struct ahash_request * req)568b8a28251SLoc Ho static int cryptd_hash_update_enqueue(struct ahash_request *req)
569b8a28251SLoc Ho {
570b8a28251SLoc Ho 	return cryptd_hash_enqueue(req, cryptd_hash_update);
571b8a28251SLoc Ho }
572b8a28251SLoc Ho 
cryptd_hash_final(void * data,int err)573255e48ebSHerbert Xu static void cryptd_hash_final(void *data, int err)
574b8a28251SLoc Ho {
575255e48ebSHerbert Xu 	struct ahash_request *req = data;
576f27c94aaSHerbert Xu 	struct shash_desc *desc;
577b8a28251SLoc Ho 
578f27c94aaSHerbert Xu 	desc = cryptd_hash_prepare(req, err);
579f27c94aaSHerbert Xu 	if (likely(desc))
580f27c94aaSHerbert Xu 		err = crypto_shash_final(desc, req->result);
581b8a28251SLoc Ho 
582f27c94aaSHerbert Xu 	cryptd_hash_complete(req, err, cryptd_hash_final);
583b8a28251SLoc Ho }
584b8a28251SLoc Ho 
cryptd_hash_final_enqueue(struct ahash_request * req)585b8a28251SLoc Ho static int cryptd_hash_final_enqueue(struct ahash_request *req)
586b8a28251SLoc Ho {
587b8a28251SLoc Ho 	return cryptd_hash_enqueue(req, cryptd_hash_final);
588b8a28251SLoc Ho }
589b8a28251SLoc Ho 
cryptd_hash_finup(void * data,int err)590255e48ebSHerbert Xu static void cryptd_hash_finup(void *data, int err)
5916fba00d1SHerbert Xu {
592255e48ebSHerbert Xu 	struct ahash_request *req = data;
593f27c94aaSHerbert Xu 	struct shash_desc *desc;
5946fba00d1SHerbert Xu 
595f27c94aaSHerbert Xu 	desc = cryptd_hash_prepare(req, err);
596f27c94aaSHerbert Xu 	if (likely(desc))
597f27c94aaSHerbert Xu 		err = shash_ahash_finup(req, desc);
5986fba00d1SHerbert Xu 
599f27c94aaSHerbert Xu 	cryptd_hash_complete(req, err, cryptd_hash_finup);
6006fba00d1SHerbert Xu }
6016fba00d1SHerbert Xu 
cryptd_hash_finup_enqueue(struct ahash_request * req)6026fba00d1SHerbert Xu static int cryptd_hash_finup_enqueue(struct ahash_request *req)
6036fba00d1SHerbert Xu {
6046fba00d1SHerbert Xu 	return cryptd_hash_enqueue(req, cryptd_hash_finup);
6056fba00d1SHerbert Xu }
6066fba00d1SHerbert Xu 
cryptd_hash_digest(void * data,int err)607255e48ebSHerbert Xu static void cryptd_hash_digest(void *data, int err)
608b8a28251SLoc Ho {
609255e48ebSHerbert Xu 	struct ahash_request *req = data;
610f27c94aaSHerbert Xu 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
611f27c94aaSHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
612f27c94aaSHerbert Xu 	struct crypto_shash *child = ctx->child;
613f27c94aaSHerbert Xu 	struct shash_desc *desc;
614b8a28251SLoc Ho 
615f27c94aaSHerbert Xu 	desc = cryptd_hash_prepare(req, err);
616f27c94aaSHerbert Xu 	if (unlikely(!desc))
617b8a28251SLoc Ho 		goto out;
618b8a28251SLoc Ho 
61946309d89SHerbert Xu 	desc->tfm = child;
620b8a28251SLoc Ho 
62146309d89SHerbert Xu 	err = shash_ahash_digest(req, desc);
622b8a28251SLoc Ho 
623b8a28251SLoc Ho out:
624f27c94aaSHerbert Xu 	cryptd_hash_complete(req, err, cryptd_hash_digest);
625b8a28251SLoc Ho }
626b8a28251SLoc Ho 
cryptd_hash_digest_enqueue(struct ahash_request * req)627b8a28251SLoc Ho static int cryptd_hash_digest_enqueue(struct ahash_request *req)
628b8a28251SLoc Ho {
629b8a28251SLoc Ho 	return cryptd_hash_enqueue(req, cryptd_hash_digest);
630b8a28251SLoc Ho }
631b8a28251SLoc Ho 
cryptd_hash_export(struct ahash_request * req,void * out)6326fba00d1SHerbert Xu static int cryptd_hash_export(struct ahash_request *req, void *out)
6336fba00d1SHerbert Xu {
6346fba00d1SHerbert Xu 	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
6356fba00d1SHerbert Xu 
6366fba00d1SHerbert Xu 	return crypto_shash_export(&rctx->desc, out);
6376fba00d1SHerbert Xu }
6386fba00d1SHerbert Xu 
cryptd_hash_import(struct ahash_request * req,const void * in)6396fba00d1SHerbert Xu static int cryptd_hash_import(struct ahash_request *req, const void *in)
6406fba00d1SHerbert Xu {
6410bd22235SArd Biesheuvel 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
6420bd22235SArd Biesheuvel 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
6430bd22235SArd Biesheuvel 	struct shash_desc *desc = cryptd_shash_desc(req);
6446fba00d1SHerbert Xu 
6450bd22235SArd Biesheuvel 	desc->tfm = ctx->child;
6460bd22235SArd Biesheuvel 
6470bd22235SArd Biesheuvel 	return crypto_shash_import(desc, in);
6486fba00d1SHerbert Xu }
6496fba00d1SHerbert Xu 
cryptd_hash_free(struct ahash_instance * inst)650758ec5acSEric Biggers static void cryptd_hash_free(struct ahash_instance *inst)
651758ec5acSEric Biggers {
652758ec5acSEric Biggers 	struct hashd_instance_ctx *ctx = ahash_instance_ctx(inst);
653758ec5acSEric Biggers 
654758ec5acSEric Biggers 	crypto_drop_shash(&ctx->spawn);
655758ec5acSEric Biggers 	kfree(inst);
656758ec5acSEric Biggers }
657758ec5acSEric Biggers 
cryptd_create_hash(struct crypto_template * tmpl,struct rtattr ** tb,struct crypto_attr_type * algt,struct cryptd_queue * queue)6589cd899a3SHerbert Xu static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
6597bcb2c99SEric Biggers 			      struct crypto_attr_type *algt,
6609cd899a3SHerbert Xu 			      struct cryptd_queue *queue)
661b8a28251SLoc Ho {
66246309d89SHerbert Xu 	struct hashd_instance_ctx *ctx;
6630b535adfSHerbert Xu 	struct ahash_instance *inst;
664218c5035SEric Biggers 	struct shash_alg *alg;
6657bcb2c99SEric Biggers 	u32 type;
6667bcb2c99SEric Biggers 	u32 mask;
66746309d89SHerbert Xu 	int err;
668b8a28251SLoc Ho 
6697bcb2c99SEric Biggers 	cryptd_type_and_mask(algt, &type, &mask);
670466a7b9eSStephan Mueller 
671218c5035SEric Biggers 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
672218c5035SEric Biggers 	if (!inst)
673218c5035SEric Biggers 		return -ENOMEM;
674b8a28251SLoc Ho 
6750b535adfSHerbert Xu 	ctx = ahash_instance_ctx(inst);
67646309d89SHerbert Xu 	ctx->queue = queue;
67746309d89SHerbert Xu 
678218c5035SEric Biggers 	err = crypto_grab_shash(&ctx->spawn, ahash_crypto_instance(inst),
679218c5035SEric Biggers 				crypto_attr_alg_name(tb[1]), type, mask);
68046309d89SHerbert Xu 	if (err)
681218c5035SEric Biggers 		goto err_free_inst;
682218c5035SEric Biggers 	alg = crypto_spawn_shash_alg(&ctx->spawn);
683218c5035SEric Biggers 
684218c5035SEric Biggers 	err = cryptd_init_instance(ahash_crypto_instance(inst), &alg->base);
685218c5035SEric Biggers 	if (err)
686218c5035SEric Biggers 		goto err_free_inst;
68746309d89SHerbert Xu 
6887bcb2c99SEric Biggers 	inst->alg.halg.base.cra_flags |= CRYPTO_ALG_ASYNC |
689218c5035SEric Biggers 		(alg->base.cra_flags & (CRYPTO_ALG_INTERNAL|
690a208fa8fSEric Biggers 					CRYPTO_ALG_OPTIONAL_KEY));
691218c5035SEric Biggers 	inst->alg.halg.digestsize = alg->digestsize;
692218c5035SEric Biggers 	inst->alg.halg.statesize = alg->statesize;
6930b535adfSHerbert Xu 	inst->alg.halg.base.cra_ctxsize = sizeof(struct cryptd_hash_ctx);
694b8a28251SLoc Ho 
6950303b7f5SHerbert Xu 	inst->alg.init_tfm = cryptd_hash_init_tfm;
696*cfbda734SHerbert Xu 	inst->alg.clone_tfm = cryptd_hash_clone_tfm;
6970303b7f5SHerbert Xu 	inst->alg.exit_tfm = cryptd_hash_exit_tfm;
698b8a28251SLoc Ho 
6990b535adfSHerbert Xu 	inst->alg.init   = cryptd_hash_init_enqueue;
7000b535adfSHerbert Xu 	inst->alg.update = cryptd_hash_update_enqueue;
7010b535adfSHerbert Xu 	inst->alg.final  = cryptd_hash_final_enqueue;
7026fba00d1SHerbert Xu 	inst->alg.finup  = cryptd_hash_finup_enqueue;
7036fba00d1SHerbert Xu 	inst->alg.export = cryptd_hash_export;
7046fba00d1SHerbert Xu 	inst->alg.import = cryptd_hash_import;
705218c5035SEric Biggers 	if (crypto_shash_alg_has_setkey(alg))
7060b535adfSHerbert Xu 		inst->alg.setkey = cryptd_hash_setkey;
7070b535adfSHerbert Xu 	inst->alg.digest = cryptd_hash_digest_enqueue;
708b8a28251SLoc Ho 
709758ec5acSEric Biggers 	inst->free = cryptd_hash_free;
710758ec5acSEric Biggers 
7110b535adfSHerbert Xu 	err = ahash_register_instance(tmpl, inst);
7129cd899a3SHerbert Xu 	if (err) {
713218c5035SEric Biggers err_free_inst:
714b8c0d74aSEric Biggers 		cryptd_hash_free(inst);
7159cd899a3SHerbert Xu 	}
7169cd899a3SHerbert Xu 	return err;
717b8a28251SLoc Ho }
718b8a28251SLoc Ho 
cryptd_aead_setkey(struct crypto_aead * parent,const u8 * key,unsigned int keylen)71992b9876bSHerbert Xu static int cryptd_aead_setkey(struct crypto_aead *parent,
72092b9876bSHerbert Xu 			      const u8 *key, unsigned int keylen)
72192b9876bSHerbert Xu {
72292b9876bSHerbert Xu 	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent);
72392b9876bSHerbert Xu 	struct crypto_aead *child = ctx->child;
72492b9876bSHerbert Xu 
72592b9876bSHerbert Xu 	return crypto_aead_setkey(child, key, keylen);
72692b9876bSHerbert Xu }
72792b9876bSHerbert Xu 
cryptd_aead_setauthsize(struct crypto_aead * parent,unsigned int authsize)72892b9876bSHerbert Xu static int cryptd_aead_setauthsize(struct crypto_aead *parent,
72992b9876bSHerbert Xu 				   unsigned int authsize)
73092b9876bSHerbert Xu {
73192b9876bSHerbert Xu 	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent);
73292b9876bSHerbert Xu 	struct crypto_aead *child = ctx->child;
73392b9876bSHerbert Xu 
73492b9876bSHerbert Xu 	return crypto_aead_setauthsize(child, authsize);
73592b9876bSHerbert Xu }
73692b9876bSHerbert Xu 
cryptd_aead_crypt(struct aead_request * req,struct crypto_aead * child,int err,int (* crypt)(struct aead_request * req),crypto_completion_t compl)737298c926cSAdrian Hoban static void cryptd_aead_crypt(struct aead_request *req,
738f27c94aaSHerbert Xu 			      struct crypto_aead *child, int err,
739f27c94aaSHerbert Xu 			      int (*crypt)(struct aead_request *req),
740f27c94aaSHerbert Xu 			      crypto_completion_t compl)
741298c926cSAdrian Hoban {
742298c926cSAdrian Hoban 	struct cryptd_aead_request_ctx *rctx;
743256f9e53SHerbert Xu 	struct aead_request *subreq;
74481760ea6SHerbert Xu 	struct cryptd_aead_ctx *ctx;
74581760ea6SHerbert Xu 	struct crypto_aead *tfm;
74681760ea6SHerbert Xu 	int refcnt;
747ec9f2006SHerbert Xu 
748298c926cSAdrian Hoban 	rctx = aead_request_ctx(req);
749256f9e53SHerbert Xu 	subreq = &rctx->req;
750f27c94aaSHerbert Xu 	req->base.complete = subreq->base.complete;
751f27c94aaSHerbert Xu 	req->base.data = subreq->base.data;
752298c926cSAdrian Hoban 
75331bd44e7SHerbert Xu 	tfm = crypto_aead_reqtfm(req);
75431bd44e7SHerbert Xu 
755298c926cSAdrian Hoban 	if (unlikely(err == -EINPROGRESS))
756298c926cSAdrian Hoban 		goto out;
757256f9e53SHerbert Xu 
758256f9e53SHerbert Xu 	aead_request_set_tfm(subreq, child);
759256f9e53SHerbert Xu 	aead_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP,
760256f9e53SHerbert Xu 				  NULL, NULL);
761256f9e53SHerbert Xu 	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
762256f9e53SHerbert Xu 			       req->iv);
763256f9e53SHerbert Xu 	aead_request_set_ad(subreq, req->assoclen);
764256f9e53SHerbert Xu 
765256f9e53SHerbert Xu 	err = crypt(subreq);
766256f9e53SHerbert Xu 
767298c926cSAdrian Hoban out:
76881760ea6SHerbert Xu 	ctx = crypto_aead_ctx(tfm);
76943b970faSChuhong Yuan 	refcnt = refcount_read(&ctx->refcnt);
77081760ea6SHerbert Xu 
771298c926cSAdrian Hoban 	local_bh_disable();
772f27c94aaSHerbert Xu 	aead_request_complete(req, err);
773298c926cSAdrian Hoban 	local_bh_enable();
77481760ea6SHerbert Xu 
775f27c94aaSHerbert Xu 	if (err == -EINPROGRESS) {
776f27c94aaSHerbert Xu 		subreq->base.complete = req->base.complete;
777f27c94aaSHerbert Xu 		subreq->base.data = req->base.data;
778f27c94aaSHerbert Xu 		req->base.complete = compl;
779f27c94aaSHerbert Xu 		req->base.data = req;
780f27c94aaSHerbert Xu 	} else if (refcnt && refcount_dec_and_test(&ctx->refcnt))
78181760ea6SHerbert Xu 		crypto_free_aead(tfm);
782298c926cSAdrian Hoban }
783298c926cSAdrian Hoban 
cryptd_aead_encrypt(void * data,int err)784255e48ebSHerbert Xu static void cryptd_aead_encrypt(void *data, int err)
785298c926cSAdrian Hoban {
786255e48ebSHerbert Xu 	struct aead_request *req = data;
787255e48ebSHerbert Xu 	struct cryptd_aead_ctx *ctx;
788255e48ebSHerbert Xu 	struct crypto_aead *child;
789298c926cSAdrian Hoban 
790255e48ebSHerbert Xu 	ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
791255e48ebSHerbert Xu 	child = ctx->child;
792f27c94aaSHerbert Xu 	cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->encrypt,
793f27c94aaSHerbert Xu 			  cryptd_aead_encrypt);
794298c926cSAdrian Hoban }
795298c926cSAdrian Hoban 
cryptd_aead_decrypt(void * data,int err)796255e48ebSHerbert Xu static void cryptd_aead_decrypt(void *data, int err)
797298c926cSAdrian Hoban {
798255e48ebSHerbert Xu 	struct aead_request *req = data;
799255e48ebSHerbert Xu 	struct cryptd_aead_ctx *ctx;
800255e48ebSHerbert Xu 	struct crypto_aead *child;
801298c926cSAdrian Hoban 
802255e48ebSHerbert Xu 	ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
803255e48ebSHerbert Xu 	child = ctx->child;
804f27c94aaSHerbert Xu 	cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->decrypt,
805f27c94aaSHerbert Xu 			  cryptd_aead_decrypt);
806298c926cSAdrian Hoban }
807298c926cSAdrian Hoban 
cryptd_aead_enqueue(struct aead_request * req,crypto_completion_t compl)808298c926cSAdrian Hoban static int cryptd_aead_enqueue(struct aead_request *req,
8093e3dc25fSMark Rustad 				    crypto_completion_t compl)
810298c926cSAdrian Hoban {
811298c926cSAdrian Hoban 	struct cryptd_aead_request_ctx *rctx = aead_request_ctx(req);
812298c926cSAdrian Hoban 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
813298c926cSAdrian Hoban 	struct cryptd_queue *queue = cryptd_get_queue(crypto_aead_tfm(tfm));
814f27c94aaSHerbert Xu 	struct aead_request *subreq = &rctx->req;
815298c926cSAdrian Hoban 
816f27c94aaSHerbert Xu 	subreq->base.complete = req->base.complete;
817f27c94aaSHerbert Xu 	subreq->base.data = req->base.data;
8183e3dc25fSMark Rustad 	req->base.complete = compl;
819f27c94aaSHerbert Xu 	req->base.data = req;
820298c926cSAdrian Hoban 	return cryptd_enqueue_request(queue, &req->base);
821298c926cSAdrian Hoban }
822298c926cSAdrian Hoban 
cryptd_aead_encrypt_enqueue(struct aead_request * req)823298c926cSAdrian Hoban static int cryptd_aead_encrypt_enqueue(struct aead_request *req)
824298c926cSAdrian Hoban {
825298c926cSAdrian Hoban 	return cryptd_aead_enqueue(req, cryptd_aead_encrypt );
826298c926cSAdrian Hoban }
827298c926cSAdrian Hoban 
cryptd_aead_decrypt_enqueue(struct aead_request * req)828298c926cSAdrian Hoban static int cryptd_aead_decrypt_enqueue(struct aead_request *req)
829298c926cSAdrian Hoban {
830298c926cSAdrian Hoban 	return cryptd_aead_enqueue(req, cryptd_aead_decrypt );
831298c926cSAdrian Hoban }
832298c926cSAdrian Hoban 
cryptd_aead_init_tfm(struct crypto_aead * tfm)833f614e546SHerbert Xu static int cryptd_aead_init_tfm(struct crypto_aead *tfm)
834298c926cSAdrian Hoban {
835f614e546SHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
836f614e546SHerbert Xu 	struct aead_instance_ctx *ictx = aead_instance_ctx(inst);
837298c926cSAdrian Hoban 	struct crypto_aead_spawn *spawn = &ictx->aead_spawn;
838f614e546SHerbert Xu 	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm);
839298c926cSAdrian Hoban 	struct crypto_aead *cipher;
840298c926cSAdrian Hoban 
841298c926cSAdrian Hoban 	cipher = crypto_spawn_aead(spawn);
842298c926cSAdrian Hoban 	if (IS_ERR(cipher))
843298c926cSAdrian Hoban 		return PTR_ERR(cipher);
844298c926cSAdrian Hoban 
845298c926cSAdrian Hoban 	ctx->child = cipher;
846ec9f2006SHerbert Xu 	crypto_aead_set_reqsize(
847256f9e53SHerbert Xu 		tfm, sizeof(struct cryptd_aead_request_ctx) +
848256f9e53SHerbert Xu 		     crypto_aead_reqsize(cipher));
849298c926cSAdrian Hoban 	return 0;
850298c926cSAdrian Hoban }
851298c926cSAdrian Hoban 
cryptd_aead_exit_tfm(struct crypto_aead * tfm)852f614e546SHerbert Xu static void cryptd_aead_exit_tfm(struct crypto_aead *tfm)
853298c926cSAdrian Hoban {
854f614e546SHerbert Xu 	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm);
855298c926cSAdrian Hoban 	crypto_free_aead(ctx->child);
856298c926cSAdrian Hoban }
857298c926cSAdrian Hoban 
cryptd_aead_free(struct aead_instance * inst)858758ec5acSEric Biggers static void cryptd_aead_free(struct aead_instance *inst)
859758ec5acSEric Biggers {
860758ec5acSEric Biggers 	struct aead_instance_ctx *ctx = aead_instance_ctx(inst);
861758ec5acSEric Biggers 
862758ec5acSEric Biggers 	crypto_drop_aead(&ctx->aead_spawn);
863758ec5acSEric Biggers 	kfree(inst);
864758ec5acSEric Biggers }
865758ec5acSEric Biggers 
cryptd_create_aead(struct crypto_template * tmpl,struct rtattr ** tb,struct crypto_attr_type * algt,struct cryptd_queue * queue)866298c926cSAdrian Hoban static int cryptd_create_aead(struct crypto_template *tmpl,
867298c926cSAdrian Hoban 		              struct rtattr **tb,
8687bcb2c99SEric Biggers 			      struct crypto_attr_type *algt,
869298c926cSAdrian Hoban 			      struct cryptd_queue *queue)
870298c926cSAdrian Hoban {
871298c926cSAdrian Hoban 	struct aead_instance_ctx *ctx;
872f614e546SHerbert Xu 	struct aead_instance *inst;
873f614e546SHerbert Xu 	struct aead_alg *alg;
8747bcb2c99SEric Biggers 	u32 type;
8757bcb2c99SEric Biggers 	u32 mask;
876298c926cSAdrian Hoban 	int err;
877298c926cSAdrian Hoban 
8787bcb2c99SEric Biggers 	cryptd_type_and_mask(algt, &type, &mask);
879466a7b9eSStephan Mueller 
8809b8c456eSHerbert Xu 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
8819b8c456eSHerbert Xu 	if (!inst)
8829b8c456eSHerbert Xu 		return -ENOMEM;
883298c926cSAdrian Hoban 
884f614e546SHerbert Xu 	ctx = aead_instance_ctx(inst);
885298c926cSAdrian Hoban 	ctx->queue = queue;
886298c926cSAdrian Hoban 
887cd900f0cSEric Biggers 	err = crypto_grab_aead(&ctx->aead_spawn, aead_crypto_instance(inst),
888b8c0d74aSEric Biggers 			       crypto_attr_alg_name(tb[1]), type, mask);
889298c926cSAdrian Hoban 	if (err)
890b8c0d74aSEric Biggers 		goto err_free_inst;
891298c926cSAdrian Hoban 
892f614e546SHerbert Xu 	alg = crypto_spawn_aead_alg(&ctx->aead_spawn);
893f614e546SHerbert Xu 	err = cryptd_init_instance(aead_crypto_instance(inst), &alg->base);
8949b8c456eSHerbert Xu 	if (err)
895b8c0d74aSEric Biggers 		goto err_free_inst;
8969b8c456eSHerbert Xu 
8977bcb2c99SEric Biggers 	inst->alg.base.cra_flags |= CRYPTO_ALG_ASYNC |
8985e4b8c1fSHerbert Xu 		(alg->base.cra_flags & CRYPTO_ALG_INTERNAL);
899f614e546SHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct cryptd_aead_ctx);
900298c926cSAdrian Hoban 
901f614e546SHerbert Xu 	inst->alg.ivsize = crypto_aead_alg_ivsize(alg);
902f614e546SHerbert Xu 	inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
903f614e546SHerbert Xu 
904f614e546SHerbert Xu 	inst->alg.init = cryptd_aead_init_tfm;
905f614e546SHerbert Xu 	inst->alg.exit = cryptd_aead_exit_tfm;
906f614e546SHerbert Xu 	inst->alg.setkey = cryptd_aead_setkey;
907f614e546SHerbert Xu 	inst->alg.setauthsize = cryptd_aead_setauthsize;
908f614e546SHerbert Xu 	inst->alg.encrypt = cryptd_aead_encrypt_enqueue;
909f614e546SHerbert Xu 	inst->alg.decrypt = cryptd_aead_decrypt_enqueue;
910f614e546SHerbert Xu 
911758ec5acSEric Biggers 	inst->free = cryptd_aead_free;
912758ec5acSEric Biggers 
913f614e546SHerbert Xu 	err = aead_register_instance(tmpl, inst);
914298c926cSAdrian Hoban 	if (err) {
915b8c0d74aSEric Biggers err_free_inst:
916b8c0d74aSEric Biggers 		cryptd_aead_free(inst);
917298c926cSAdrian Hoban 	}
918298c926cSAdrian Hoban 	return err;
919298c926cSAdrian Hoban }
920298c926cSAdrian Hoban 
921254eff77SHuang Ying static struct cryptd_queue queue;
922124b53d0SHerbert Xu 
cryptd_create(struct crypto_template * tmpl,struct rtattr ** tb)9239cd899a3SHerbert Xu static int cryptd_create(struct crypto_template *tmpl, struct rtattr **tb)
924124b53d0SHerbert Xu {
925124b53d0SHerbert Xu 	struct crypto_attr_type *algt;
926124b53d0SHerbert Xu 
927124b53d0SHerbert Xu 	algt = crypto_get_attr_type(tb);
928124b53d0SHerbert Xu 	if (IS_ERR(algt))
9299cd899a3SHerbert Xu 		return PTR_ERR(algt);
930124b53d0SHerbert Xu 
931124b53d0SHerbert Xu 	switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
932c65058b7SEric Biggers 	case CRYPTO_ALG_TYPE_SKCIPHER:
9337bcb2c99SEric Biggers 		return cryptd_create_skcipher(tmpl, tb, algt, &queue);
93484ede58dSEric Biggers 	case CRYPTO_ALG_TYPE_HASH:
9357bcb2c99SEric Biggers 		return cryptd_create_hash(tmpl, tb, algt, &queue);
936298c926cSAdrian Hoban 	case CRYPTO_ALG_TYPE_AEAD:
9377bcb2c99SEric Biggers 		return cryptd_create_aead(tmpl, tb, algt, &queue);
938124b53d0SHerbert Xu 	}
939124b53d0SHerbert Xu 
9409cd899a3SHerbert Xu 	return -EINVAL;
941124b53d0SHerbert Xu }
942124b53d0SHerbert Xu 
943124b53d0SHerbert Xu static struct crypto_template cryptd_tmpl = {
944124b53d0SHerbert Xu 	.name = "cryptd",
9459cd899a3SHerbert Xu 	.create = cryptd_create,
946124b53d0SHerbert Xu 	.module = THIS_MODULE,
947124b53d0SHerbert Xu };
948124b53d0SHerbert Xu 
cryptd_alloc_skcipher(const char * alg_name,u32 type,u32 mask)9494e0958d1SHerbert Xu struct cryptd_skcipher *cryptd_alloc_skcipher(const char *alg_name,
9504e0958d1SHerbert Xu 					      u32 type, u32 mask)
9514e0958d1SHerbert Xu {
9524e0958d1SHerbert Xu 	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
9534e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx;
9544e0958d1SHerbert Xu 	struct crypto_skcipher *tfm;
9554e0958d1SHerbert Xu 
9564e0958d1SHerbert Xu 	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
9574e0958d1SHerbert Xu 		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
9584e0958d1SHerbert Xu 		return ERR_PTR(-EINVAL);
9594e0958d1SHerbert Xu 
9604e0958d1SHerbert Xu 	tfm = crypto_alloc_skcipher(cryptd_alg_name, type, mask);
9614e0958d1SHerbert Xu 	if (IS_ERR(tfm))
9624e0958d1SHerbert Xu 		return ERR_CAST(tfm);
9634e0958d1SHerbert Xu 
9644e0958d1SHerbert Xu 	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
9654e0958d1SHerbert Xu 		crypto_free_skcipher(tfm);
9664e0958d1SHerbert Xu 		return ERR_PTR(-EINVAL);
9674e0958d1SHerbert Xu 	}
9684e0958d1SHerbert Xu 
9694e0958d1SHerbert Xu 	ctx = crypto_skcipher_ctx(tfm);
97043b970faSChuhong Yuan 	refcount_set(&ctx->refcnt, 1);
9714e0958d1SHerbert Xu 
9724e0958d1SHerbert Xu 	return container_of(tfm, struct cryptd_skcipher, base);
9734e0958d1SHerbert Xu }
9744e0958d1SHerbert Xu EXPORT_SYMBOL_GPL(cryptd_alloc_skcipher);
9754e0958d1SHerbert Xu 
cryptd_skcipher_child(struct cryptd_skcipher * tfm)9764e0958d1SHerbert Xu struct crypto_skcipher *cryptd_skcipher_child(struct cryptd_skcipher *tfm)
9774e0958d1SHerbert Xu {
9784e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
9794e0958d1SHerbert Xu 
9803a58c231SHerbert Xu 	return ctx->child;
9814e0958d1SHerbert Xu }
9824e0958d1SHerbert Xu EXPORT_SYMBOL_GPL(cryptd_skcipher_child);
9834e0958d1SHerbert Xu 
cryptd_skcipher_queued(struct cryptd_skcipher * tfm)9844e0958d1SHerbert Xu bool cryptd_skcipher_queued(struct cryptd_skcipher *tfm)
9854e0958d1SHerbert Xu {
9864e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
9874e0958d1SHerbert Xu 
98843b970faSChuhong Yuan 	return refcount_read(&ctx->refcnt) - 1;
9894e0958d1SHerbert Xu }
9904e0958d1SHerbert Xu EXPORT_SYMBOL_GPL(cryptd_skcipher_queued);
9914e0958d1SHerbert Xu 
cryptd_free_skcipher(struct cryptd_skcipher * tfm)9924e0958d1SHerbert Xu void cryptd_free_skcipher(struct cryptd_skcipher *tfm)
9934e0958d1SHerbert Xu {
9944e0958d1SHerbert Xu 	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
9954e0958d1SHerbert Xu 
99643b970faSChuhong Yuan 	if (refcount_dec_and_test(&ctx->refcnt))
9974e0958d1SHerbert Xu 		crypto_free_skcipher(&tfm->base);
9984e0958d1SHerbert Xu }
9994e0958d1SHerbert Xu EXPORT_SYMBOL_GPL(cryptd_free_skcipher);
10004e0958d1SHerbert Xu 
cryptd_alloc_ahash(const char * alg_name,u32 type,u32 mask)1001ace13663SHuang Ying struct cryptd_ahash *cryptd_alloc_ahash(const char *alg_name,
1002ace13663SHuang Ying 					u32 type, u32 mask)
1003ace13663SHuang Ying {
1004ace13663SHuang Ying 	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
100581760ea6SHerbert Xu 	struct cryptd_hash_ctx *ctx;
1006ace13663SHuang Ying 	struct crypto_ahash *tfm;
1007ace13663SHuang Ying 
1008ace13663SHuang Ying 	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
1009ace13663SHuang Ying 		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
1010ace13663SHuang Ying 		return ERR_PTR(-EINVAL);
1011ace13663SHuang Ying 	tfm = crypto_alloc_ahash(cryptd_alg_name, type, mask);
1012ace13663SHuang Ying 	if (IS_ERR(tfm))
1013ace13663SHuang Ying 		return ERR_CAST(tfm);
1014ace13663SHuang Ying 	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
1015ace13663SHuang Ying 		crypto_free_ahash(tfm);
1016ace13663SHuang Ying 		return ERR_PTR(-EINVAL);
1017ace13663SHuang Ying 	}
1018ace13663SHuang Ying 
101981760ea6SHerbert Xu 	ctx = crypto_ahash_ctx(tfm);
102043b970faSChuhong Yuan 	refcount_set(&ctx->refcnt, 1);
102181760ea6SHerbert Xu 
1022ace13663SHuang Ying 	return __cryptd_ahash_cast(tfm);
1023ace13663SHuang Ying }
1024ace13663SHuang Ying EXPORT_SYMBOL_GPL(cryptd_alloc_ahash);
1025ace13663SHuang Ying 
cryptd_ahash_child(struct cryptd_ahash * tfm)1026ace13663SHuang Ying struct crypto_shash *cryptd_ahash_child(struct cryptd_ahash *tfm)
1027ace13663SHuang Ying {
1028ace13663SHuang Ying 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
1029ace13663SHuang Ying 
1030ace13663SHuang Ying 	return ctx->child;
1031ace13663SHuang Ying }
1032ace13663SHuang Ying EXPORT_SYMBOL_GPL(cryptd_ahash_child);
1033ace13663SHuang Ying 
cryptd_shash_desc(struct ahash_request * req)10340e1227d3SHuang Ying struct shash_desc *cryptd_shash_desc(struct ahash_request *req)
10350e1227d3SHuang Ying {
10360e1227d3SHuang Ying 	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
10370e1227d3SHuang Ying 	return &rctx->desc;
10380e1227d3SHuang Ying }
10390e1227d3SHuang Ying EXPORT_SYMBOL_GPL(cryptd_shash_desc);
10400e1227d3SHuang Ying 
cryptd_ahash_queued(struct cryptd_ahash * tfm)104181760ea6SHerbert Xu bool cryptd_ahash_queued(struct cryptd_ahash *tfm)
104281760ea6SHerbert Xu {
104381760ea6SHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
104481760ea6SHerbert Xu 
104543b970faSChuhong Yuan 	return refcount_read(&ctx->refcnt) - 1;
104681760ea6SHerbert Xu }
104781760ea6SHerbert Xu EXPORT_SYMBOL_GPL(cryptd_ahash_queued);
104881760ea6SHerbert Xu 
cryptd_free_ahash(struct cryptd_ahash * tfm)1049ace13663SHuang Ying void cryptd_free_ahash(struct cryptd_ahash *tfm)
1050ace13663SHuang Ying {
105181760ea6SHerbert Xu 	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
105281760ea6SHerbert Xu 
105343b970faSChuhong Yuan 	if (refcount_dec_and_test(&ctx->refcnt))
1054ace13663SHuang Ying 		crypto_free_ahash(&tfm->base);
1055ace13663SHuang Ying }
1056ace13663SHuang Ying EXPORT_SYMBOL_GPL(cryptd_free_ahash);
1057ace13663SHuang Ying 
cryptd_alloc_aead(const char * alg_name,u32 type,u32 mask)1058298c926cSAdrian Hoban struct cryptd_aead *cryptd_alloc_aead(const char *alg_name,
1059298c926cSAdrian Hoban 						  u32 type, u32 mask)
1060298c926cSAdrian Hoban {
1061298c926cSAdrian Hoban 	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
106281760ea6SHerbert Xu 	struct cryptd_aead_ctx *ctx;
1063298c926cSAdrian Hoban 	struct crypto_aead *tfm;
1064298c926cSAdrian Hoban 
1065298c926cSAdrian Hoban 	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
1066298c926cSAdrian Hoban 		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
1067298c926cSAdrian Hoban 		return ERR_PTR(-EINVAL);
1068298c926cSAdrian Hoban 	tfm = crypto_alloc_aead(cryptd_alg_name, type, mask);
1069298c926cSAdrian Hoban 	if (IS_ERR(tfm))
1070298c926cSAdrian Hoban 		return ERR_CAST(tfm);
1071298c926cSAdrian Hoban 	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
1072298c926cSAdrian Hoban 		crypto_free_aead(tfm);
1073298c926cSAdrian Hoban 		return ERR_PTR(-EINVAL);
1074298c926cSAdrian Hoban 	}
107581760ea6SHerbert Xu 
107681760ea6SHerbert Xu 	ctx = crypto_aead_ctx(tfm);
107743b970faSChuhong Yuan 	refcount_set(&ctx->refcnt, 1);
107881760ea6SHerbert Xu 
1079298c926cSAdrian Hoban 	return __cryptd_aead_cast(tfm);
1080298c926cSAdrian Hoban }
1081298c926cSAdrian Hoban EXPORT_SYMBOL_GPL(cryptd_alloc_aead);
1082298c926cSAdrian Hoban 
cryptd_aead_child(struct cryptd_aead * tfm)1083298c926cSAdrian Hoban struct crypto_aead *cryptd_aead_child(struct cryptd_aead *tfm)
1084298c926cSAdrian Hoban {
1085298c926cSAdrian Hoban 	struct cryptd_aead_ctx *ctx;
1086298c926cSAdrian Hoban 	ctx = crypto_aead_ctx(&tfm->base);
1087298c926cSAdrian Hoban 	return ctx->child;
1088298c926cSAdrian Hoban }
1089298c926cSAdrian Hoban EXPORT_SYMBOL_GPL(cryptd_aead_child);
1090298c926cSAdrian Hoban 
cryptd_aead_queued(struct cryptd_aead * tfm)109181760ea6SHerbert Xu bool cryptd_aead_queued(struct cryptd_aead *tfm)
109281760ea6SHerbert Xu {
109381760ea6SHerbert Xu 	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(&tfm->base);
109481760ea6SHerbert Xu 
109543b970faSChuhong Yuan 	return refcount_read(&ctx->refcnt) - 1;
109681760ea6SHerbert Xu }
109781760ea6SHerbert Xu EXPORT_SYMBOL_GPL(cryptd_aead_queued);
109881760ea6SHerbert Xu 
cryptd_free_aead(struct cryptd_aead * tfm)1099298c926cSAdrian Hoban void cryptd_free_aead(struct cryptd_aead *tfm)
1100298c926cSAdrian Hoban {
110181760ea6SHerbert Xu 	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(&tfm->base);
110281760ea6SHerbert Xu 
110343b970faSChuhong Yuan 	if (refcount_dec_and_test(&ctx->refcnt))
1104298c926cSAdrian Hoban 		crypto_free_aead(&tfm->base);
1105298c926cSAdrian Hoban }
1106298c926cSAdrian Hoban EXPORT_SYMBOL_GPL(cryptd_free_aead);
1107298c926cSAdrian Hoban 
cryptd_init(void)1108124b53d0SHerbert Xu static int __init cryptd_init(void)
1109124b53d0SHerbert Xu {
1110124b53d0SHerbert Xu 	int err;
1111124b53d0SHerbert Xu 
11123e56e168SEric Biggers 	cryptd_wq = alloc_workqueue("cryptd", WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE,
11133e56e168SEric Biggers 				    1);
11143e56e168SEric Biggers 	if (!cryptd_wq)
11153e56e168SEric Biggers 		return -ENOMEM;
11163e56e168SEric Biggers 
1117c3a53605SJon Maxwell 	err = cryptd_init_queue(&queue, cryptd_max_cpu_qlen);
1118124b53d0SHerbert Xu 	if (err)
11193e56e168SEric Biggers 		goto err_destroy_wq;
1120124b53d0SHerbert Xu 
1121124b53d0SHerbert Xu 	err = crypto_register_template(&cryptd_tmpl);
1122124b53d0SHerbert Xu 	if (err)
11233e56e168SEric Biggers 		goto err_fini_queue;
1124124b53d0SHerbert Xu 
11253e56e168SEric Biggers 	return 0;
11263e56e168SEric Biggers 
11273e56e168SEric Biggers err_fini_queue:
11283e56e168SEric Biggers 	cryptd_fini_queue(&queue);
11293e56e168SEric Biggers err_destroy_wq:
11303e56e168SEric Biggers 	destroy_workqueue(cryptd_wq);
1131124b53d0SHerbert Xu 	return err;
1132124b53d0SHerbert Xu }
1133124b53d0SHerbert Xu 
cryptd_exit(void)1134124b53d0SHerbert Xu static void __exit cryptd_exit(void)
1135124b53d0SHerbert Xu {
11363e56e168SEric Biggers 	destroy_workqueue(cryptd_wq);
1137254eff77SHuang Ying 	cryptd_fini_queue(&queue);
1138124b53d0SHerbert Xu 	crypto_unregister_template(&cryptd_tmpl);
1139124b53d0SHerbert Xu }
1140124b53d0SHerbert Xu 
1141b2bac6acSHerbert Xu subsys_initcall(cryptd_init);
1142124b53d0SHerbert Xu module_exit(cryptd_exit);
1143124b53d0SHerbert Xu 
1144124b53d0SHerbert Xu MODULE_LICENSE("GPL");
1145124b53d0SHerbert Xu MODULE_DESCRIPTION("Software async crypto daemon");
11464943ba16SKees Cook MODULE_ALIAS_CRYPTO("cryptd");
1147