cregit-Linux how code gets into the kernel

Release 4.7 crypto/cryptd.c

Directory: crypto
/*
 * Software async crypto daemon.
 *
 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
 *
 * Added AEAD support to cryptd.
 *    Authors: Tadeusz Struk (tadeusz.struk@intel.com)
 *             Adrian Hoban <adrian.hoban@intel.com>
 *             Gabriele Paoloni <gabriele.paoloni@intel.com>
 *             Aidan O'Mahony (aidan.o.mahony@intel.com)
 *    Copyright (c) 2010, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 */

#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/aead.h>
#include <crypto/cryptd.h>
#include <crypto/crypto_wq.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
#include <linux/slab.h>


#define CRYPTD_MAX_CPU_QLEN 100


struct cryptd_cpu_queue {
	
struct crypto_queue queue;
	
struct work_struct work;
};


struct cryptd_queue {
	
struct cryptd_cpu_queue __percpu *cpu_queue;
};


struct cryptd_instance_ctx {
	
struct crypto_spawn spawn;
	
struct cryptd_queue *queue;
};


struct hashd_instance_ctx {
	
struct crypto_shash_spawn spawn;
	
struct cryptd_queue *queue;
};


struct aead_instance_ctx {
	
struct crypto_aead_spawn aead_spawn;
	
struct cryptd_queue *queue;
};


struct cryptd_blkcipher_ctx {
	
struct crypto_blkcipher *child;
};


struct cryptd_blkcipher_request_ctx {
	
crypto_completion_t complete;
};


struct cryptd_hash_ctx {
	
struct crypto_shash *child;
};


struct cryptd_hash_request_ctx {
	
crypto_completion_t complete;
	
struct shash_desc desc;
};


struct cryptd_aead_ctx {
	
struct crypto_aead *child;
};


struct cryptd_aead_request_ctx {
	
crypto_completion_t complete;
};

static void cryptd_queue_worker(struct work_struct *work);


static int cryptd_init_queue(struct cryptd_queue *queue, unsigned int max_cpu_qlen) { int cpu; struct cryptd_cpu_queue *cpu_queue; queue->cpu_queue = alloc_percpu(struct cryptd_cpu_queue); if (!queue->cpu_queue) return -ENOMEM; for_each_possible_cpu(cpu) { cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu); crypto_init_queue(&cpu_queue->queue, max_cpu_qlen); INIT_WORK(&cpu_queue->work, cryptd_queue_worker); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
huang yinghuang ying84100.00%1100.00%
Total84100.00%1100.00%


static void cryptd_fini_queue(struct cryptd_queue *queue) { int cpu; struct cryptd_cpu_queue *cpu_queue; for_each_possible_cpu(cpu) { cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu); BUG_ON(cpu_queue->queue.qlen); } free_percpu(queue->cpu_queue); }

Contributors

PersonTokensPropCommitsCommitProp
huang yinghuang ying52100.00%1100.00%
Total52100.00%1100.00%


static int cryptd_enqueue_request(struct cryptd_queue *queue, struct crypto_async_request *request) { int cpu, err; struct cryptd_cpu_queue *cpu_queue; cpu = get_cpu(); cpu_queue = this_cpu_ptr(queue->cpu_queue); err = crypto_enqueue_request(&cpu_queue->queue, request); queue_work_on(cpu, kcrypto_wq, &cpu_queue->work); put_cpu(); return err; }

Contributors

PersonTokensPropCommitsCommitProp
huang yinghuang ying6998.57%150.00%
christoph lameterchristoph lameter11.43%150.00%
Total70100.00%2100.00%

/* Called in workqueue context, do one real cryption work (via * req->complete) and reschedule itself if there are more work to * do. */
static void cryptd_queue_worker(struct work_struct *work) { struct cryptd_cpu_queue *cpu_queue; struct crypto_async_request *req, *backlog; cpu_queue = container_of(work, struct cryptd_cpu_queue, work); /* * Only handle one request at a time to avoid hogging crypto workqueue. * preempt_disable/enable is used to prevent being preempted by * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent * cryptd_enqueue_request() being accessed from software interrupts. */ local_bh_disable(); preempt_disable(); backlog = crypto_get_backlog(&cpu_queue->queue); req = crypto_dequeue_request(&cpu_queue->queue); preempt_enable(); local_bh_enable(); if (!req) return; if (backlog) backlog->complete(backlog, -EINPROGRESS); req->complete(req, 0); if (cpu_queue->queue.qlen) queue_work(kcrypto_wq, &cpu_queue->work); }

Contributors

PersonTokensPropCommitsCommitProp
huang yinghuang ying10993.97%150.00%
jussi kivilinnajussi kivilinna76.03%150.00%
Total116100.00%2100.00%


static inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm) { struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst); return ictx->queue; }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu3692.31%150.00%
huang yinghuang ying37.69%150.00%
Total39100.00%2100.00%


static inline void cryptd_check_internal(struct rtattr **tb, u32 *type, u32 *mask) { struct crypto_attr_type *algt; algt = crypto_get_attr_type(tb); if (IS_ERR(algt)) return; *type |= algt->type & CRYPTO_ALG_INTERNAL; *mask |= algt->mask & CRYPTO_ALG_INTERNAL; }

Contributors

PersonTokensPropCommitsCommitProp
stephan muellerstephan mueller5491.53%150.00%
herbert xuherbert xu58.47%150.00%
Total59100.00%2100.00%


static int cryptd_blkcipher_setkey(struct crypto_ablkcipher *parent, const u8 *key, unsigned int keylen) { struct cryptd_blkcipher_ctx *ctx = crypto_ablkcipher_ctx(parent); struct crypto_blkcipher *child = ctx->child; int err; crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_blkcipher_set_flags(child, crypto_ablkcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); err = crypto_blkcipher_setkey(child, key, keylen); crypto_ablkcipher_set_flags(parent, crypto_blkcipher_get_flags(child) & CRYPTO_TFM_RES_MASK); return err; }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu87100.00%1100.00%
Total87100.00%1100.00%


static void cryptd_blkcipher_crypt(struct ablkcipher_request *req, struct crypto_blkcipher *child, int err, int (*crypt)(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int len)) { struct cryptd_blkcipher_request_ctx *rctx; struct blkcipher_desc desc; rctx = ablkcipher_request_ctx(req); if (unlikely(err == -EINPROGRESS)) goto out; desc.tfm = child; desc.info = req->info; desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; err = crypt(&desc, req->dst, req->src, req->nbytes); req->base.complete = rctx->complete; out: local_bh_disable(); rctx->complete(&req->base, err); local_bh_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu144100.00%2100.00%
Total144100.00%2100.00%


static void cryptd_blkcipher_encrypt(struct crypto_async_request *req, int err) { struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(req->tfm); struct crypto_blkcipher *child = ctx->child; cryptd_blkcipher_crypt(ablkcipher_request_cast(req), child, err, crypto_blkcipher_crt(child)->encrypt); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu54100.00%1100.00%
Total54100.00%1100.00%


static void cryptd_blkcipher_decrypt(struct crypto_async_request *req, int err) { struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(req->tfm); struct crypto_blkcipher *child = ctx->child; cryptd_blkcipher_crypt(ablkcipher_request_cast(req), child, err, crypto_blkcipher_crt(child)->decrypt); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu54100.00%1100.00%
Total54100.00%1100.00%


static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req, crypto_completion_t compl) { struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req); struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); struct cryptd_queue *queue; queue = cryptd_get_queue(crypto_ablkcipher_tfm(tfm)); rctx->complete = req->base.complete; req->base.complete = compl; return cryptd_enqueue_request(queue, &req->base); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu6583.33%250.00%
huang yinghuang ying1114.10%125.00%
mark d. rustadmark d. rustad22.56%125.00%
Total78100.00%4100.00%


static int cryptd_blkcipher_encrypt_enqueue(struct ablkcipher_request *req) { return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_encrypt); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu19100.00%1100.00%
Total19100.00%1100.00%


static int cryptd_blkcipher_decrypt_enqueue(struct ablkcipher_request *req) { return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_decrypt); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu19100.00%1100.00%
Total19100.00%1100.00%


static int cryptd_blkcipher_init_tfm(struct crypto_tfm *tfm) { struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst); struct crypto_spawn *spawn = &ictx->spawn; struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm); struct crypto_blkcipher *cipher; cipher = crypto_spawn_blkcipher(spawn); if (IS_ERR(cipher)) return PTR_ERR(cipher); ctx->child = cipher; tfm->crt_ablkcipher.reqsize = sizeof(struct cryptd_blkcipher_request_ctx); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu97100.00%1100.00%
Total97100.00%1100.00%


static void cryptd_blkcipher_exit_tfm(struct crypto_tfm *tfm) { struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm); crypto_free_blkcipher(ctx->child); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu28100.00%1100.00%
Total28100.00%1100.00%


static int cryptd_init_instance(struct crypto_instance *inst, struct crypto_alg *alg) { if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "cryptd(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) return -ENAMETOOLONG; memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); inst->alg.cra_priority = alg->cra_priority + 50; inst->alg.cra_blocksize = alg->cra_blocksize; inst->alg.cra_alignmask = alg->cra_alignmask; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu91100.00%1100.00%
Total91100.00%1100.00%


static void *cryptd_alloc_instance(struct crypto_alg *alg, unsigned int head, unsigned int tail) { char *p; struct crypto_instance *inst; int err; p = kzalloc(head + sizeof(*inst) + tail, GFP_KERNEL); if (!p) return ERR_PTR(-ENOMEM); inst = (void *)(p + head); err = cryptd_init_instance(inst, alg); if (err) goto out_free_inst; out: return p; out_free_inst: kfree(p); p = ERR_PTR(err); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu10493.69%480.00%
julia lawalljulia lawall76.31%120.00%
Total111100.00%5100.00%


static int cryptd_create_blkcipher(struct crypto_template *tmpl, struct rtattr **tb, struct cryptd_queue *queue) { struct cryptd_instance_ctx *ctx; struct crypto_instance *inst; struct crypto_alg *alg; u32 type = CRYPTO_ALG_TYPE_BLKCIPHER; u32 mask = CRYPTO_ALG_TYPE_MASK; int err; cryptd_check_internal(tb, &type, &mask); alg = crypto_get_attr_alg(tb, type, mask); if (IS_ERR(alg)) return PTR_ERR(alg); inst = cryptd_alloc_instance(alg, 0, sizeof(*ctx)); err = PTR_ERR(inst); if (IS_ERR(inst)) goto out_put_alg; ctx = crypto_instance_ctx(inst); ctx->queue = queue; err = crypto_init_spawn(&ctx->spawn, alg, inst, CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); if (err) goto out_free_inst; type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC; if (alg->cra_flags & CRYPTO_ALG_INTERNAL) type |= CRYPTO_ALG_INTERNAL; inst->alg.cra_flags = type; inst->alg.cra_type = &crypto_ablkcipher_type; inst->alg.cra_ablkcipher.ivsize = alg->cra_blkcipher.ivsize; inst->alg.cra_ablkcipher.min_keysize = alg->cra_blkcipher.min_keysize; inst->alg.cra_ablkcipher.max_keysize = alg->cra_blkcipher.max_keysize; inst->alg.cra_ablkcipher.geniv = alg->cra_blkcipher.geniv; inst->alg.cra_ctxsize = sizeof(struct cryptd_blkcipher_ctx); inst->alg.cra_init = cryptd_blkcipher_init_tfm; inst->alg.cra_exit = cryptd_blkcipher_exit_tfm; inst->alg.cra_ablkcipher.setkey = cryptd_blkcipher_setkey; inst->alg.cra_ablkcipher.encrypt = cryptd_blkcipher_encrypt_enqueue; inst->alg.cra_ablkcipher.decrypt = cryptd_blkcipher_decrypt_enqueue; err = crypto_register_instance(tmpl, inst); if (err) { crypto_drop_spawn(&ctx->spawn); out_free_inst: kfree(inst); } out_put_alg: crypto_mod_put(alg); return err; }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu29385.17%562.50%
stephan muellerstephan mueller4212.21%112.50%
steffen klassertsteffen klassert72.03%112.50%
huang yinghuang ying20.58%112.50%
Total344100.00%8100.00%


static int cryptd_hash_init_tfm(struct crypto_tfm *tfm) { struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); struct hashd_instance_ctx *ictx = crypto_instance_ctx(inst); struct crypto_shash_spawn *spawn = &ictx->spawn; struct cryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm); struct crypto_shash *hash; hash = crypto_spawn_shash(spawn); if (IS_ERR(hash)) return PTR_ERR(hash); ctx->child = hash; crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), sizeof(struct cryptd_hash_request_ctx) + crypto_shash_descsize(hash)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho5855.77%125.00%
herbert xuherbert xu4644.23%375.00%
Total104100.00%4100.00%


static void cryptd_hash_exit_tfm(struct crypto_tfm *tfm) { struct cryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm); crypto_free_shash(ctx->child); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho2071.43%133.33%
huang yinghuang ying725.00%133.33%
herbert xuherbert xu13.57%133.33%
Total28100.00%3100.00%


static int cryptd_hash_setkey(struct crypto_ahash *parent, const u8 *key, unsigned int keylen) { struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(parent); struct crypto_shash *child = ctx->child; int err; crypto_shash_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_shash_set_flags(child, crypto_ahash_get_flags(parent) & CRYPTO_TFM_REQ_MASK); err = crypto_shash_setkey(child, key, keylen); crypto_ahash_set_flags(parent, crypto_shash_get_flags(child) & CRYPTO_TFM_RES_MASK); return err; }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho8193.10%133.33%
herbert xuherbert xu66.90%266.67%
Total87100.00%3100.00%


static int cryptd_hash_enqueue(struct ahash_request *req, crypto_completion_t compl) { struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req); struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); struct cryptd_queue *queue = cryptd_get_queue(crypto_ahash_tfm(tfm)); rctx->complete = req->base.complete; req->base.complete = compl; return cryptd_enqueue_request(queue, &req->base); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho6788.16%133.33%
huang yinghuang ying79.21%133.33%
mark d. rustadmark d. rustad22.63%133.33%
Total76100.00%3100.00%


static void cryptd_hash_init(struct crypto_async_request *req_async, int err) { struct cryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm); struct crypto_shash *child = ctx->child; struct ahash_request *req = ahash_request_cast(req_async); struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req); struct shash_desc *desc = &rctx->desc; if (unlikely(err == -EINPROGRESS)) goto out; desc->tfm = child; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; err = crypto_shash_init(desc); req->base.complete = rctx->complete; out: local_bh_disable(); rctx->complete(&req->base, err); local_bh_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho11187.40%150.00%
herbert xuherbert xu1612.60%150.00%
Total127100.00%2100.00%


static int cryptd_hash_init_enqueue(struct ahash_request *req) { return cryptd_hash_enqueue(req, cryptd_hash_init); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho19100.00%1100.00%
Total19100.00%1100.00%


static void cryptd_hash_update(struct crypto_async_request *req_async, int err) { struct ahash_request *req = ahash_request_cast(req_async); struct cryptd_hash_request_ctx *rctx; rctx = ahash_request_ctx(req); if (unlikely(err == -EINPROGRESS)) goto out; err = shash_ahash_update(req, &rctx->desc); req->base.complete = rctx->complete; out: local_bh_disable(); rctx->complete(&req->base, err); local_bh_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho8795.60%150.00%
herbert xuherbert xu44.40%150.00%
Total91100.00%2100.00%


static int cryptd_hash_update_enqueue(struct ahash_request *req) { return cryptd_hash_enqueue(req, cryptd_hash_update); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho19100.00%1100.00%
Total19100.00%1100.00%


static void cryptd_hash_final(struct crypto_async_request *req_async, int err) { struct ahash_request *req = ahash_request_cast(req_async); struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req); if (unlikely(err == -EINPROGRESS)) goto out; err = crypto_shash_final(&rctx->desc, req->result); req->base.complete = rctx->complete; out: local_bh_disable(); rctx->complete(&req->base, err); local_bh_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho8694.51%150.00%
herbert xuherbert xu55.49%150.00%
Total91100.00%2100.00%


static int cryptd_hash_final_enqueue(struct ahash_request *req) { return cryptd_hash_enqueue(req, cryptd_hash_final); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho19100.00%1100.00%
Total19100.00%1100.00%


static void cryptd_hash_finup(struct crypto_async_request *req_async, int err) { struct ahash_request *req = ahash_request_cast(req_async); struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req); if (unlikely(err == -EINPROGRESS)) goto out; err = shash_ahash_finup(req, &rctx->desc); req->base.complete = rctx->complete; out: local_bh_disable(); rctx->complete(&req->base, err); local_bh_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu89100.00%1100.00%
Total89100.00%1100.00%


static int cryptd_hash_finup_enqueue(struct ahash_request *req) { return cryptd_hash_enqueue(req, cryptd_hash_finup); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu19100.00%1100.00%
Total19100.00%1100.00%


static void cryptd_hash_digest(struct crypto_async_request *req_async, int err) { struct cryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm); struct crypto_shash *child = ctx->child; struct ahash_request *req = ahash_request_cast(req_async); struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req); struct shash_desc *desc = &rctx->desc; if (unlikely(err == -EINPROGRESS)) goto out; desc->tfm = child; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; err = shash_ahash_digest(req, desc); req->base.complete = rctx->complete; out: local_bh_disable(); rctx->complete(&req->base, err); local_bh_enable(); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho11286.82%150.00%
herbert xuherbert xu1713.18%150.00%
Total129100.00%2100.00%


static int cryptd_hash_digest_enqueue(struct ahash_request *req) { return cryptd_hash_enqueue(req, cryptd_hash_digest); }

Contributors

PersonTokensPropCommitsCommitProp
loc holoc ho19100.00%1100.00%
Total19100.00%1100.00%


static int cryptd_hash_export(struct ahash_request *req, void *out) { struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req); return crypto_shash_export(&rctx->desc, out); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu36100.00%1100.00%
Total36100.00%1100.00%


static int cryptd_hash_import(struct ahash_request *req, const void *in) { struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req); return crypto_shash_import(&rctx->desc, in); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu37100.00%1100.00%
Total37100.00%1100.00%


static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, struct cryptd_queue *queue) { struct hashd_instance_ctx *ctx; struct ahash_instance *inst; struct shash_alg *salg; struct crypto_alg *alg; u32 type = 0; u32 mask = 0; int err; cryptd_check_internal(tb, &type, &mask); salg = shash_attr_alg(tb[1], type, mask); if (IS_ERR(salg)) return PTR_ERR(salg); alg = &salg->base; inst = cryptd_alloc_instance(alg, ahash_instance_headroom(), sizeof(*ctx)); err = PTR_ERR(inst); if (IS_ERR(inst)) goto out_put_alg; ctx = ahash_instance_ctx(inst); ctx->queue = queue; err = crypto_init_shash_spawn(&ctx->spawn, salg, ahash_crypto_instance(inst)); if (err) goto out_free_inst; type