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