Blame view

crypto/cryptd.c 28.6 KB
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
1
2
3
4
5
  /*
   * Software async crypto daemon.
   *
   * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
   *
298c926c6   Adrian Hoban   crypto: cryptd - ...
6
7
8
9
10
11
12
   * 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.
   *
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
13
14
15
16
17
18
19
20
   * 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>
18e33e6d5   Herbert Xu   crypto: hash - Mo...
21
  #include <crypto/internal/hash.h>
298c926c6   Adrian Hoban   crypto: cryptd - ...
22
  #include <crypto/internal/aead.h>
1cac2cbc7   Huang Ying   crypto: cryptd - ...
23
  #include <crypto/cryptd.h>
254eff771   Huang Ying   crypto: cryptd - ...
24
  #include <crypto/crypto_wq.h>
81760ea6a   Herbert Xu   crypto: cryptd - ...
25
  #include <linux/atomic.h>
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
26
27
28
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
29
30
  #include <linux/list.h>
  #include <linux/module.h>
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
31
32
33
  #include <linux/scatterlist.h>
  #include <linux/sched.h>
  #include <linux/slab.h>
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
34

81760ea6a   Herbert Xu   crypto: cryptd - ...
35
  #define CRYPTD_MAX_CPU_QLEN 1000
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
36

254eff771   Huang Ying   crypto: cryptd - ...
37
  struct cryptd_cpu_queue {
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
38
  	struct crypto_queue queue;
254eff771   Huang Ying   crypto: cryptd - ...
39
40
41
42
  	struct work_struct work;
  };
  
  struct cryptd_queue {
a29d8b8e2   Tejun Heo   percpu: add __per...
43
  	struct cryptd_cpu_queue __percpu *cpu_queue;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
44
45
46
47
  };
  
  struct cryptd_instance_ctx {
  	struct crypto_spawn spawn;
254eff771   Huang Ying   crypto: cryptd - ...
48
  	struct cryptd_queue *queue;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
49
  };
46309d893   Herbert Xu   crypto: cryptd - ...
50
51
52
53
  struct hashd_instance_ctx {
  	struct crypto_shash_spawn spawn;
  	struct cryptd_queue *queue;
  };
298c926c6   Adrian Hoban   crypto: cryptd - ...
54
55
56
57
  struct aead_instance_ctx {
  	struct crypto_aead_spawn aead_spawn;
  	struct cryptd_queue *queue;
  };
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
58
  struct cryptd_blkcipher_ctx {
81760ea6a   Herbert Xu   crypto: cryptd - ...
59
  	atomic_t refcnt;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
60
61
62
63
64
65
  	struct crypto_blkcipher *child;
  };
  
  struct cryptd_blkcipher_request_ctx {
  	crypto_completion_t complete;
  };
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
66
  struct cryptd_hash_ctx {
81760ea6a   Herbert Xu   crypto: cryptd - ...
67
  	atomic_t refcnt;
46309d893   Herbert Xu   crypto: cryptd - ...
68
  	struct crypto_shash *child;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
69
70
71
72
  };
  
  struct cryptd_hash_request_ctx {
  	crypto_completion_t complete;
46309d893   Herbert Xu   crypto: cryptd - ...
73
  	struct shash_desc desc;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
74
  };
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
75

298c926c6   Adrian Hoban   crypto: cryptd - ...
76
  struct cryptd_aead_ctx {
81760ea6a   Herbert Xu   crypto: cryptd - ...
77
  	atomic_t refcnt;
298c926c6   Adrian Hoban   crypto: cryptd - ...
78
79
80
81
82
83
  	struct crypto_aead *child;
  };
  
  struct cryptd_aead_request_ctx {
  	crypto_completion_t complete;
  };
254eff771   Huang Ying   crypto: cryptd - ...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  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;
  }
  
  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);
  }
  
  static int cryptd_enqueue_request(struct cryptd_queue *queue,
  				  struct crypto_async_request *request)
  {
  	int cpu, err;
  	struct cryptd_cpu_queue *cpu_queue;
81760ea6a   Herbert Xu   crypto: cryptd - ...
120
121
122
  	struct crypto_tfm *tfm;
  	atomic_t *refcnt;
  	bool may_backlog;
254eff771   Huang Ying   crypto: cryptd - ...
123
124
  
  	cpu = get_cpu();
0b44f4861   Christoph Lameter   this_cpu: Use thi...
125
  	cpu_queue = this_cpu_ptr(queue->cpu_queue);
254eff771   Huang Ying   crypto: cryptd - ...
126
  	err = crypto_enqueue_request(&cpu_queue->queue, request);
81760ea6a   Herbert Xu   crypto: cryptd - ...
127
128
129
130
131
132
  
  	refcnt = crypto_tfm_ctx(request->tfm);
  	may_backlog = request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG;
  
  	if (err == -EBUSY && !may_backlog)
  		goto out_put_cpu;
254eff771   Huang Ying   crypto: cryptd - ...
133
  	queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
81760ea6a   Herbert Xu   crypto: cryptd - ...
134
135
136
137
138
139
140
141
  
  	if (!atomic_read(refcnt))
  		goto out_put_cpu;
  
  	tfm = request->tfm;
  	atomic_inc(refcnt);
  
  out_put_cpu:
254eff771   Huang Ying   crypto: cryptd - ...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  	put_cpu();
  
  	return err;
  }
  
  /* 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);
9efade1b3   Jussi Kivilinna   crypto: cryptd - ...
156
157
158
159
160
161
162
  	/*
  	 * 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();
254eff771   Huang Ying   crypto: cryptd - ...
163
164
165
166
  	preempt_disable();
  	backlog = crypto_get_backlog(&cpu_queue->queue);
  	req = crypto_dequeue_request(&cpu_queue->queue);
  	preempt_enable();
9efade1b3   Jussi Kivilinna   crypto: cryptd - ...
167
  	local_bh_enable();
254eff771   Huang Ying   crypto: cryptd - ...
168
169
170
171
172
173
174
175
176
177
178
179
180
  
  	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);
  }
  
  static inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm)
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
181
182
183
  {
  	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
  	struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
254eff771   Huang Ying   crypto: cryptd - ...
184
  	return ictx->queue;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
185
  }
466a7b9e3   Stephan Mueller   crypto: cryptd - ...
186
187
188
189
190
191
192
193
  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;
f6da32059   Herbert Xu   crypto: cryptd - ...
194

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
195
196
  	*type |= algt->type & CRYPTO_ALG_INTERNAL;
  	*mask |= algt->mask & CRYPTO_ALG_INTERNAL;
466a7b9e3   Stephan Mueller   crypto: cryptd - ...
197
  }
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  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;
  }
  
  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;
81760ea6a   Herbert Xu   crypto: cryptd - ...
223
224
  	struct cryptd_blkcipher_ctx *ctx;
  	struct crypto_ablkcipher *tfm;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
225
  	struct blkcipher_desc desc;
81760ea6a   Herbert Xu   crypto: cryptd - ...
226
  	int refcnt;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
227
228
  
  	rctx = ablkcipher_request_ctx(req);
93aa7f8a1   Herbert Xu   [CRYPTO] cryptd: ...
229
230
  	if (unlikely(err == -EINPROGRESS))
  		goto out;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
231
232
233
234
235
236
237
238
  
  	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;
93aa7f8a1   Herbert Xu   [CRYPTO] cryptd: ...
239
  out:
81760ea6a   Herbert Xu   crypto: cryptd - ...
240
241
242
  	tfm = crypto_ablkcipher_reqtfm(req);
  	ctx = crypto_ablkcipher_ctx(tfm);
  	refcnt = atomic_read(&ctx->refcnt);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
243
  	local_bh_disable();
93aa7f8a1   Herbert Xu   [CRYPTO] cryptd: ...
244
  	rctx->complete(&req->base, err);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
245
  	local_bh_enable();
81760ea6a   Herbert Xu   crypto: cryptd - ...
246
247
248
  
  	if (err != -EINPROGRESS && refcnt && atomic_dec_and_test(&ctx->refcnt))
  		crypto_free_ablkcipher(tfm);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  }
  
  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);
  }
  
  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);
  }
  
  static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
3e3dc25fe   Mark Rustad   crypto: Resolve s...
270
  				    crypto_completion_t compl)
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
271
272
273
  {
  	struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req);
  	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
254eff771   Huang Ying   crypto: cryptd - ...
274
  	struct cryptd_queue *queue;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
275

254eff771   Huang Ying   crypto: cryptd - ...
276
  	queue = cryptd_get_queue(crypto_ablkcipher_tfm(tfm));
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
277
  	rctx->complete = req->base.complete;
3e3dc25fe   Mark Rustad   crypto: Resolve s...
278
  	req->base.complete = compl;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
279

254eff771   Huang Ying   crypto: cryptd - ...
280
  	return cryptd_enqueue_request(queue, &req->base);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  }
  
  static int cryptd_blkcipher_encrypt_enqueue(struct ablkcipher_request *req)
  {
  	return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_encrypt);
  }
  
  static int cryptd_blkcipher_decrypt_enqueue(struct ablkcipher_request *req)
  {
  	return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_decrypt);
  }
  
  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;
  }
  
  static void cryptd_blkcipher_exit_tfm(struct crypto_tfm *tfm)
  {
  	struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
314
315
316
  
  	crypto_free_blkcipher(ctx->child);
  }
9b8c456e0   Herbert Xu   crypto: cryptd - ...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
  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;
  }
0b535adfb   Herbert Xu   crypto: cryptd - ...
333
334
  static void *cryptd_alloc_instance(struct crypto_alg *alg, unsigned int head,
  				   unsigned int tail)
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
335
  {
0b535adfb   Herbert Xu   crypto: cryptd - ...
336
  	char *p;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
337
  	struct crypto_instance *inst;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
338
  	int err;
0b535adfb   Herbert Xu   crypto: cryptd - ...
339
340
341
342
343
  	p = kzalloc(head + sizeof(*inst) + tail, GFP_KERNEL);
  	if (!p)
  		return ERR_PTR(-ENOMEM);
  
  	inst = (void *)(p + head);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
344

9b8c456e0   Herbert Xu   crypto: cryptd - ...
345
346
  	err = cryptd_init_instance(inst, alg);
  	if (err)
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
347
  		goto out_free_inst;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
348
  out:
0b535adfb   Herbert Xu   crypto: cryptd - ...
349
  	return p;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
350
351
  
  out_free_inst:
0b535adfb   Herbert Xu   crypto: cryptd - ...
352
353
  	kfree(p);
  	p = ERR_PTR(err);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
354
355
  	goto out;
  }
9cd899a32   Herbert Xu   crypto: cryptd - ...
356
357
358
  static int cryptd_create_blkcipher(struct crypto_template *tmpl,
  				   struct rtattr **tb,
  				   struct cryptd_queue *queue)
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
359
  {
46309d893   Herbert Xu   crypto: cryptd - ...
360
  	struct cryptd_instance_ctx *ctx;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
361
362
  	struct crypto_instance *inst;
  	struct crypto_alg *alg;
466a7b9e3   Stephan Mueller   crypto: cryptd - ...
363
364
  	u32 type = CRYPTO_ALG_TYPE_BLKCIPHER;
  	u32 mask = CRYPTO_ALG_TYPE_MASK;
46309d893   Herbert Xu   crypto: cryptd - ...
365
  	int err;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
366

466a7b9e3   Stephan Mueller   crypto: cryptd - ...
367
368
369
  	cryptd_check_internal(tb, &type, &mask);
  
  	alg = crypto_get_attr_alg(tb, type, mask);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
370
  	if (IS_ERR(alg))
9cd899a32   Herbert Xu   crypto: cryptd - ...
371
  		return PTR_ERR(alg);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
372

0b535adfb   Herbert Xu   crypto: cryptd - ...
373
  	inst = cryptd_alloc_instance(alg, 0, sizeof(*ctx));
05ed8758f   Steffen Klassert   crypto: cryptd - ...
374
  	err = PTR_ERR(inst);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
375
376
  	if (IS_ERR(inst))
  		goto out_put_alg;
46309d893   Herbert Xu   crypto: cryptd - ...
377
378
379
380
381
382
383
  	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;
466a7b9e3   Stephan Mueller   crypto: cryptd - ...
384
385
386
387
  	type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
  	if (alg->cra_flags & CRYPTO_ALG_INTERNAL)
  		type |= CRYPTO_ALG_INTERNAL;
  	inst->alg.cra_flags = type;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
388
389
390
391
392
  	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;
927eead52   Herbert Xu   [CRYPTO] cryptd: ...
393
  	inst->alg.cra_ablkcipher.geniv = alg->cra_blkcipher.geniv;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
394
395
396
397
398
399
400
401
  	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;
9cd899a32   Herbert Xu   crypto: cryptd - ...
402
403
404
405
406
407
  	err = crypto_register_instance(tmpl, inst);
  	if (err) {
  		crypto_drop_spawn(&ctx->spawn);
  out_free_inst:
  		kfree(inst);
  	}
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
408
409
  out_put_alg:
  	crypto_mod_put(alg);
9cd899a32   Herbert Xu   crypto: cryptd - ...
410
  	return err;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
411
  }
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
412
413
414
  static int cryptd_hash_init_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
46309d893   Herbert Xu   crypto: cryptd - ...
415
416
  	struct hashd_instance_ctx *ictx = crypto_instance_ctx(inst);
  	struct crypto_shash_spawn *spawn = &ictx->spawn;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
417
  	struct cryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
46309d893   Herbert Xu   crypto: cryptd - ...
418
  	struct crypto_shash *hash;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
419

46309d893   Herbert Xu   crypto: cryptd - ...
420
421
422
  	hash = crypto_spawn_shash(spawn);
  	if (IS_ERR(hash))
  		return PTR_ERR(hash);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
423

46309d893   Herbert Xu   crypto: cryptd - ...
424
  	ctx->child = hash;
0d6669e2b   Herbert Xu   crypto: cryptd - ...
425
426
427
  	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
  				 sizeof(struct cryptd_hash_request_ctx) +
  				 crypto_shash_descsize(hash));
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
428
429
430
431
432
433
  	return 0;
  }
  
  static void cryptd_hash_exit_tfm(struct crypto_tfm *tfm)
  {
  	struct cryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
434

46309d893   Herbert Xu   crypto: cryptd - ...
435
  	crypto_free_shash(ctx->child);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
436
437
438
439
440
441
  }
  
  static int cryptd_hash_setkey(struct crypto_ahash *parent,
  				   const u8 *key, unsigned int keylen)
  {
  	struct cryptd_hash_ctx *ctx   = crypto_ahash_ctx(parent);
46309d893   Herbert Xu   crypto: cryptd - ...
442
  	struct crypto_shash *child = ctx->child;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
443
  	int err;
46309d893   Herbert Xu   crypto: cryptd - ...
444
445
446
447
448
449
  	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);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
450
451
452
453
  	return err;
  }
  
  static int cryptd_hash_enqueue(struct ahash_request *req,
3e3dc25fe   Mark Rustad   crypto: Resolve s...
454
  				crypto_completion_t compl)
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
455
456
457
  {
  	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
254eff771   Huang Ying   crypto: cryptd - ...
458
459
  	struct cryptd_queue *queue =
  		cryptd_get_queue(crypto_ahash_tfm(tfm));
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
460
461
  
  	rctx->complete = req->base.complete;
3e3dc25fe   Mark Rustad   crypto: Resolve s...
462
  	req->base.complete = compl;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
463

254eff771   Huang Ying   crypto: cryptd - ...
464
  	return cryptd_enqueue_request(queue, &req->base);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
465
  }
81760ea6a   Herbert Xu   crypto: cryptd - ...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  static void cryptd_hash_complete(struct ahash_request *req, int err)
  {
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
  	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
  	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
  	int refcnt = atomic_read(&ctx->refcnt);
  
  	local_bh_disable();
  	rctx->complete(&req->base, err);
  	local_bh_enable();
  
  	if (err != -EINPROGRESS && refcnt && atomic_dec_and_test(&ctx->refcnt))
  		crypto_free_ahash(tfm);
  }
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
480
481
  static void cryptd_hash_init(struct crypto_async_request *req_async, int err)
  {
46309d893   Herbert Xu   crypto: cryptd - ...
482
483
484
485
486
  	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;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
487
488
489
  
  	if (unlikely(err == -EINPROGRESS))
  		goto out;
46309d893   Herbert Xu   crypto: cryptd - ...
490
491
  	desc->tfm = child;
  	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
492

46309d893   Herbert Xu   crypto: cryptd - ...
493
  	err = crypto_shash_init(desc);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
494
495
496
497
  
  	req->base.complete = rctx->complete;
  
  out:
81760ea6a   Herbert Xu   crypto: cryptd - ...
498
  	cryptd_hash_complete(req, err);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
499
500
501
502
503
504
505
506
507
  }
  
  static int cryptd_hash_init_enqueue(struct ahash_request *req)
  {
  	return cryptd_hash_enqueue(req, cryptd_hash_init);
  }
  
  static void cryptd_hash_update(struct crypto_async_request *req_async, int err)
  {
46309d893   Herbert Xu   crypto: cryptd - ...
508
  	struct ahash_request *req = ahash_request_cast(req_async);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
509
  	struct cryptd_hash_request_ctx *rctx;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
510
511
512
513
514
  
  	rctx = ahash_request_ctx(req);
  
  	if (unlikely(err == -EINPROGRESS))
  		goto out;
46309d893   Herbert Xu   crypto: cryptd - ...
515
  	err = shash_ahash_update(req, &rctx->desc);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
516
517
518
519
  
  	req->base.complete = rctx->complete;
  
  out:
81760ea6a   Herbert Xu   crypto: cryptd - ...
520
  	cryptd_hash_complete(req, err);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
521
522
523
524
525
526
527
528
529
  }
  
  static int cryptd_hash_update_enqueue(struct ahash_request *req)
  {
  	return cryptd_hash_enqueue(req, cryptd_hash_update);
  }
  
  static void cryptd_hash_final(struct crypto_async_request *req_async, int err)
  {
46309d893   Herbert Xu   crypto: cryptd - ...
530
531
  	struct ahash_request *req = ahash_request_cast(req_async);
  	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
532
533
534
  
  	if (unlikely(err == -EINPROGRESS))
  		goto out;
46309d893   Herbert Xu   crypto: cryptd - ...
535
  	err = crypto_shash_final(&rctx->desc, req->result);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
536
537
538
539
  
  	req->base.complete = rctx->complete;
  
  out:
81760ea6a   Herbert Xu   crypto: cryptd - ...
540
  	cryptd_hash_complete(req, err);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
541
542
543
544
545
546
  }
  
  static int cryptd_hash_final_enqueue(struct ahash_request *req)
  {
  	return cryptd_hash_enqueue(req, cryptd_hash_final);
  }
6fba00d17   Herbert Xu   crypto: cryptd - ...
547
548
549
550
551
552
553
554
555
556
557
558
559
  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:
81760ea6a   Herbert Xu   crypto: cryptd - ...
560
  	cryptd_hash_complete(req, err);
6fba00d17   Herbert Xu   crypto: cryptd - ...
561
562
563
564
565
566
  }
  
  static int cryptd_hash_finup_enqueue(struct ahash_request *req)
  {
  	return cryptd_hash_enqueue(req, cryptd_hash_finup);
  }
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
567
568
  static void cryptd_hash_digest(struct crypto_async_request *req_async, int err)
  {
46309d893   Herbert Xu   crypto: cryptd - ...
569
570
571
572
573
  	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;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
574
575
576
  
  	if (unlikely(err == -EINPROGRESS))
  		goto out;
46309d893   Herbert Xu   crypto: cryptd - ...
577
578
  	desc->tfm = child;
  	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
579

46309d893   Herbert Xu   crypto: cryptd - ...
580
  	err = shash_ahash_digest(req, desc);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
581
582
583
584
  
  	req->base.complete = rctx->complete;
  
  out:
81760ea6a   Herbert Xu   crypto: cryptd - ...
585
  	cryptd_hash_complete(req, err);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
586
587
588
589
590
591
  }
  
  static int cryptd_hash_digest_enqueue(struct ahash_request *req)
  {
  	return cryptd_hash_enqueue(req, cryptd_hash_digest);
  }
6fba00d17   Herbert Xu   crypto: cryptd - ...
592
593
594
595
596
597
598
599
600
  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);
  }
  
  static int cryptd_hash_import(struct ahash_request *req, const void *in)
  {
0bd222359   Ard Biesheuvel   crypto: cryptd - ...
601
602
603
604
605
606
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
  	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(tfm);
  	struct shash_desc *desc = cryptd_shash_desc(req);
  
  	desc->tfm = ctx->child;
  	desc->flags = req->base.flags;
6fba00d17   Herbert Xu   crypto: cryptd - ...
607

0bd222359   Ard Biesheuvel   crypto: cryptd - ...
608
  	return crypto_shash_import(desc, in);
6fba00d17   Herbert Xu   crypto: cryptd - ...
609
  }
9cd899a32   Herbert Xu   crypto: cryptd - ...
610
611
  static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
  			      struct cryptd_queue *queue)
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
612
  {
46309d893   Herbert Xu   crypto: cryptd - ...
613
  	struct hashd_instance_ctx *ctx;
0b535adfb   Herbert Xu   crypto: cryptd - ...
614
  	struct ahash_instance *inst;
46309d893   Herbert Xu   crypto: cryptd - ...
615
  	struct shash_alg *salg;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
616
  	struct crypto_alg *alg;
466a7b9e3   Stephan Mueller   crypto: cryptd - ...
617
618
  	u32 type = 0;
  	u32 mask = 0;
46309d893   Herbert Xu   crypto: cryptd - ...
619
  	int err;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
620

466a7b9e3   Stephan Mueller   crypto: cryptd - ...
621
622
623
  	cryptd_check_internal(tb, &type, &mask);
  
  	salg = shash_attr_alg(tb[1], type, mask);
46309d893   Herbert Xu   crypto: cryptd - ...
624
  	if (IS_ERR(salg))
9cd899a32   Herbert Xu   crypto: cryptd - ...
625
  		return PTR_ERR(salg);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
626

46309d893   Herbert Xu   crypto: cryptd - ...
627
  	alg = &salg->base;
0b535adfb   Herbert Xu   crypto: cryptd - ...
628
629
  	inst = cryptd_alloc_instance(alg, ahash_instance_headroom(),
  				     sizeof(*ctx));
05ed8758f   Steffen Klassert   crypto: cryptd - ...
630
  	err = PTR_ERR(inst);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
631
632
  	if (IS_ERR(inst))
  		goto out_put_alg;
0b535adfb   Herbert Xu   crypto: cryptd - ...
633
  	ctx = ahash_instance_ctx(inst);
46309d893   Herbert Xu   crypto: cryptd - ...
634
  	ctx->queue = queue;
0b535adfb   Herbert Xu   crypto: cryptd - ...
635
636
  	err = crypto_init_shash_spawn(&ctx->spawn, salg,
  				      ahash_crypto_instance(inst));
46309d893   Herbert Xu   crypto: cryptd - ...
637
638
  	if (err)
  		goto out_free_inst;
466a7b9e3   Stephan Mueller   crypto: cryptd - ...
639
640
641
642
  	type = CRYPTO_ALG_ASYNC;
  	if (alg->cra_flags & CRYPTO_ALG_INTERNAL)
  		type |= CRYPTO_ALG_INTERNAL;
  	inst->alg.halg.base.cra_flags = type;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
643

0b535adfb   Herbert Xu   crypto: cryptd - ...
644
  	inst->alg.halg.digestsize = salg->digestsize;
1a0783402   Wang, Rui Y   crypto: cryptd - ...
645
  	inst->alg.halg.statesize = salg->statesize;
0b535adfb   Herbert Xu   crypto: cryptd - ...
646
  	inst->alg.halg.base.cra_ctxsize = sizeof(struct cryptd_hash_ctx);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
647

0b535adfb   Herbert Xu   crypto: cryptd - ...
648
649
  	inst->alg.halg.base.cra_init = cryptd_hash_init_tfm;
  	inst->alg.halg.base.cra_exit = cryptd_hash_exit_tfm;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
650

0b535adfb   Herbert Xu   crypto: cryptd - ...
651
652
653
  	inst->alg.init   = cryptd_hash_init_enqueue;
  	inst->alg.update = cryptd_hash_update_enqueue;
  	inst->alg.final  = cryptd_hash_final_enqueue;
6fba00d17   Herbert Xu   crypto: cryptd - ...
654
655
656
  	inst->alg.finup  = cryptd_hash_finup_enqueue;
  	inst->alg.export = cryptd_hash_export;
  	inst->alg.import = cryptd_hash_import;
0b535adfb   Herbert Xu   crypto: cryptd - ...
657
658
  	inst->alg.setkey = cryptd_hash_setkey;
  	inst->alg.digest = cryptd_hash_digest_enqueue;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
659

0b535adfb   Herbert Xu   crypto: cryptd - ...
660
  	err = ahash_register_instance(tmpl, inst);
9cd899a32   Herbert Xu   crypto: cryptd - ...
661
662
663
664
665
  	if (err) {
  		crypto_drop_shash(&ctx->spawn);
  out_free_inst:
  		kfree(inst);
  	}
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
666
667
  out_put_alg:
  	crypto_mod_put(alg);
9cd899a32   Herbert Xu   crypto: cryptd - ...
668
  	return err;
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
669
  }
92b9876bd   Herbert Xu   crypto: cryptd - ...
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
  static int cryptd_aead_setkey(struct crypto_aead *parent,
  			      const u8 *key, unsigned int keylen)
  {
  	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent);
  	struct crypto_aead *child = ctx->child;
  
  	return crypto_aead_setkey(child, key, keylen);
  }
  
  static int cryptd_aead_setauthsize(struct crypto_aead *parent,
  				   unsigned int authsize)
  {
  	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(parent);
  	struct crypto_aead *child = ctx->child;
  
  	return crypto_aead_setauthsize(child, authsize);
  }
298c926c6   Adrian Hoban   crypto: cryptd - ...
687
688
689
690
691
692
  static void cryptd_aead_crypt(struct aead_request *req,
  			struct crypto_aead *child,
  			int err,
  			int (*crypt)(struct aead_request *req))
  {
  	struct cryptd_aead_request_ctx *rctx;
81760ea6a   Herbert Xu   crypto: cryptd - ...
693
  	struct cryptd_aead_ctx *ctx;
ec9f2006f   Herbert Xu   crypto: cryptd - ...
694
  	crypto_completion_t compl;
81760ea6a   Herbert Xu   crypto: cryptd - ...
695
696
  	struct crypto_aead *tfm;
  	int refcnt;
ec9f2006f   Herbert Xu   crypto: cryptd - ...
697

298c926c6   Adrian Hoban   crypto: cryptd - ...
698
  	rctx = aead_request_ctx(req);
ec9f2006f   Herbert Xu   crypto: cryptd - ...
699
  	compl = rctx->complete;
298c926c6   Adrian Hoban   crypto: cryptd - ...
700

31bd44e76   Herbert Xu   crypto: cryptd - ...
701
  	tfm = crypto_aead_reqtfm(req);
298c926c6   Adrian Hoban   crypto: cryptd - ...
702
703
704
705
  	if (unlikely(err == -EINPROGRESS))
  		goto out;
  	aead_request_set_tfm(req, child);
  	err = crypt( req );
81760ea6a   Herbert Xu   crypto: cryptd - ...
706

298c926c6   Adrian Hoban   crypto: cryptd - ...
707
  out:
81760ea6a   Herbert Xu   crypto: cryptd - ...
708
709
  	ctx = crypto_aead_ctx(tfm);
  	refcnt = atomic_read(&ctx->refcnt);
298c926c6   Adrian Hoban   crypto: cryptd - ...
710
  	local_bh_disable();
ec9f2006f   Herbert Xu   crypto: cryptd - ...
711
  	compl(&req->base, err);
298c926c6   Adrian Hoban   crypto: cryptd - ...
712
  	local_bh_enable();
81760ea6a   Herbert Xu   crypto: cryptd - ...
713
714
715
  
  	if (err != -EINPROGRESS && refcnt && atomic_dec_and_test(&ctx->refcnt))
  		crypto_free_aead(tfm);
298c926c6   Adrian Hoban   crypto: cryptd - ...
716
717
718
719
720
721
722
723
724
  }
  
  static void cryptd_aead_encrypt(struct crypto_async_request *areq, int err)
  {
  	struct cryptd_aead_ctx *ctx = crypto_tfm_ctx(areq->tfm);
  	struct crypto_aead *child = ctx->child;
  	struct aead_request *req;
  
  	req = container_of(areq, struct aead_request, base);
ba3749a71   Herbert Xu   crypto: cryptd - ...
725
  	cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->encrypt);
298c926c6   Adrian Hoban   crypto: cryptd - ...
726
727
728
729
730
731
732
733
734
  }
  
  static void cryptd_aead_decrypt(struct crypto_async_request *areq, int err)
  {
  	struct cryptd_aead_ctx *ctx = crypto_tfm_ctx(areq->tfm);
  	struct crypto_aead *child = ctx->child;
  	struct aead_request *req;
  
  	req = container_of(areq, struct aead_request, base);
ba3749a71   Herbert Xu   crypto: cryptd - ...
735
  	cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->decrypt);
298c926c6   Adrian Hoban   crypto: cryptd - ...
736
737
738
  }
  
  static int cryptd_aead_enqueue(struct aead_request *req,
3e3dc25fe   Mark Rustad   crypto: Resolve s...
739
  				    crypto_completion_t compl)
298c926c6   Adrian Hoban   crypto: cryptd - ...
740
741
742
743
744
745
  {
  	struct cryptd_aead_request_ctx *rctx = aead_request_ctx(req);
  	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
  	struct cryptd_queue *queue = cryptd_get_queue(crypto_aead_tfm(tfm));
  
  	rctx->complete = req->base.complete;
3e3dc25fe   Mark Rustad   crypto: Resolve s...
746
  	req->base.complete = compl;
298c926c6   Adrian Hoban   crypto: cryptd - ...
747
748
749
750
751
752
753
754
755
756
757
758
  	return cryptd_enqueue_request(queue, &req->base);
  }
  
  static int cryptd_aead_encrypt_enqueue(struct aead_request *req)
  {
  	return cryptd_aead_enqueue(req, cryptd_aead_encrypt );
  }
  
  static int cryptd_aead_decrypt_enqueue(struct aead_request *req)
  {
  	return cryptd_aead_enqueue(req, cryptd_aead_decrypt );
  }
f614e546f   Herbert Xu   crypto: cryptd - ...
759
  static int cryptd_aead_init_tfm(struct crypto_aead *tfm)
298c926c6   Adrian Hoban   crypto: cryptd - ...
760
  {
f614e546f   Herbert Xu   crypto: cryptd - ...
761
762
  	struct aead_instance *inst = aead_alg_instance(tfm);
  	struct aead_instance_ctx *ictx = aead_instance_ctx(inst);
298c926c6   Adrian Hoban   crypto: cryptd - ...
763
  	struct crypto_aead_spawn *spawn = &ictx->aead_spawn;
f614e546f   Herbert Xu   crypto: cryptd - ...
764
  	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm);
298c926c6   Adrian Hoban   crypto: cryptd - ...
765
766
767
768
769
  	struct crypto_aead *cipher;
  
  	cipher = crypto_spawn_aead(spawn);
  	if (IS_ERR(cipher))
  		return PTR_ERR(cipher);
298c926c6   Adrian Hoban   crypto: cryptd - ...
770
  	ctx->child = cipher;
ec9f2006f   Herbert Xu   crypto: cryptd - ...
771
772
773
  	crypto_aead_set_reqsize(
  		tfm, max((unsigned)sizeof(struct cryptd_aead_request_ctx),
  			 crypto_aead_reqsize(cipher)));
298c926c6   Adrian Hoban   crypto: cryptd - ...
774
775
  	return 0;
  }
f614e546f   Herbert Xu   crypto: cryptd - ...
776
  static void cryptd_aead_exit_tfm(struct crypto_aead *tfm)
298c926c6   Adrian Hoban   crypto: cryptd - ...
777
  {
f614e546f   Herbert Xu   crypto: cryptd - ...
778
  	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(tfm);
298c926c6   Adrian Hoban   crypto: cryptd - ...
779
780
781
782
783
784
785
786
  	crypto_free_aead(ctx->child);
  }
  
  static int cryptd_create_aead(struct crypto_template *tmpl,
  		              struct rtattr **tb,
  			      struct cryptd_queue *queue)
  {
  	struct aead_instance_ctx *ctx;
f614e546f   Herbert Xu   crypto: cryptd - ...
787
788
  	struct aead_instance *inst;
  	struct aead_alg *alg;
9b8c456e0   Herbert Xu   crypto: cryptd - ...
789
790
  	const char *name;
  	u32 type = 0;
ec9f2006f   Herbert Xu   crypto: cryptd - ...
791
  	u32 mask = CRYPTO_ALG_ASYNC;
298c926c6   Adrian Hoban   crypto: cryptd - ...
792
  	int err;
466a7b9e3   Stephan Mueller   crypto: cryptd - ...
793
  	cryptd_check_internal(tb, &type, &mask);
9b8c456e0   Herbert Xu   crypto: cryptd - ...
794
795
796
  	name = crypto_attr_alg_name(tb[1]);
  	if (IS_ERR(name))
  		return PTR_ERR(name);
298c926c6   Adrian Hoban   crypto: cryptd - ...
797

9b8c456e0   Herbert Xu   crypto: cryptd - ...
798
799
800
  	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
  	if (!inst)
  		return -ENOMEM;
298c926c6   Adrian Hoban   crypto: cryptd - ...
801

f614e546f   Herbert Xu   crypto: cryptd - ...
802
  	ctx = aead_instance_ctx(inst);
298c926c6   Adrian Hoban   crypto: cryptd - ...
803
  	ctx->queue = queue;
f614e546f   Herbert Xu   crypto: cryptd - ...
804
  	crypto_set_aead_spawn(&ctx->aead_spawn, aead_crypto_instance(inst));
9b8c456e0   Herbert Xu   crypto: cryptd - ...
805
  	err = crypto_grab_aead(&ctx->aead_spawn, name, type, mask);
298c926c6   Adrian Hoban   crypto: cryptd - ...
806
807
  	if (err)
  		goto out_free_inst;
f614e546f   Herbert Xu   crypto: cryptd - ...
808
809
  	alg = crypto_spawn_aead_alg(&ctx->aead_spawn);
  	err = cryptd_init_instance(aead_crypto_instance(inst), &alg->base);
9b8c456e0   Herbert Xu   crypto: cryptd - ...
810
811
  	if (err)
  		goto out_drop_aead;
f614e546f   Herbert Xu   crypto: cryptd - ...
812
  	inst->alg.base.cra_flags = CRYPTO_ALG_ASYNC |
5e4b8c1fc   Herbert Xu   crypto: aead - Re...
813
  				   (alg->base.cra_flags & CRYPTO_ALG_INTERNAL);
f614e546f   Herbert Xu   crypto: cryptd - ...
814
  	inst->alg.base.cra_ctxsize = sizeof(struct cryptd_aead_ctx);
298c926c6   Adrian Hoban   crypto: cryptd - ...
815

f614e546f   Herbert Xu   crypto: cryptd - ...
816
817
818
819
820
821
822
823
824
825
826
  	inst->alg.ivsize = crypto_aead_alg_ivsize(alg);
  	inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
  
  	inst->alg.init = cryptd_aead_init_tfm;
  	inst->alg.exit = cryptd_aead_exit_tfm;
  	inst->alg.setkey = cryptd_aead_setkey;
  	inst->alg.setauthsize = cryptd_aead_setauthsize;
  	inst->alg.encrypt = cryptd_aead_encrypt_enqueue;
  	inst->alg.decrypt = cryptd_aead_decrypt_enqueue;
  
  	err = aead_register_instance(tmpl, inst);
298c926c6   Adrian Hoban   crypto: cryptd - ...
827
  	if (err) {
9b8c456e0   Herbert Xu   crypto: cryptd - ...
828
829
  out_drop_aead:
  		crypto_drop_aead(&ctx->aead_spawn);
298c926c6   Adrian Hoban   crypto: cryptd - ...
830
831
832
  out_free_inst:
  		kfree(inst);
  	}
298c926c6   Adrian Hoban   crypto: cryptd - ...
833
834
  	return err;
  }
254eff771   Huang Ying   crypto: cryptd - ...
835
  static struct cryptd_queue queue;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
836

9cd899a32   Herbert Xu   crypto: cryptd - ...
837
  static int cryptd_create(struct crypto_template *tmpl, struct rtattr **tb)
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
838
839
840
841
842
  {
  	struct crypto_attr_type *algt;
  
  	algt = crypto_get_attr_type(tb);
  	if (IS_ERR(algt))
9cd899a32   Herbert Xu   crypto: cryptd - ...
843
  		return PTR_ERR(algt);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
844
845
846
  
  	switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
  	case CRYPTO_ALG_TYPE_BLKCIPHER:
9cd899a32   Herbert Xu   crypto: cryptd - ...
847
  		return cryptd_create_blkcipher(tmpl, tb, &queue);
b8a28251c   Loc Ho   [CRYPTO] cryptd: ...
848
  	case CRYPTO_ALG_TYPE_DIGEST:
9cd899a32   Herbert Xu   crypto: cryptd - ...
849
  		return cryptd_create_hash(tmpl, tb, &queue);
298c926c6   Adrian Hoban   crypto: cryptd - ...
850
851
  	case CRYPTO_ALG_TYPE_AEAD:
  		return cryptd_create_aead(tmpl, tb, &queue);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
852
  	}
9cd899a32   Herbert Xu   crypto: cryptd - ...
853
  	return -EINVAL;
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
854
855
856
857
858
  }
  
  static void cryptd_free(struct crypto_instance *inst)
  {
  	struct cryptd_instance_ctx *ctx = crypto_instance_ctx(inst);
0b535adfb   Herbert Xu   crypto: cryptd - ...
859
  	struct hashd_instance_ctx *hctx = crypto_instance_ctx(inst);
298c926c6   Adrian Hoban   crypto: cryptd - ...
860
  	struct aead_instance_ctx *aead_ctx = crypto_instance_ctx(inst);
0b535adfb   Herbert Xu   crypto: cryptd - ...
861
862
863
864
865
866
  
  	switch (inst->alg.cra_flags & CRYPTO_ALG_TYPE_MASK) {
  	case CRYPTO_ALG_TYPE_AHASH:
  		crypto_drop_shash(&hctx->spawn);
  		kfree(ahash_instance(inst));
  		return;
298c926c6   Adrian Hoban   crypto: cryptd - ...
867
  	case CRYPTO_ALG_TYPE_AEAD:
f614e546f   Herbert Xu   crypto: cryptd - ...
868
869
  		crypto_drop_aead(&aead_ctx->aead_spawn);
  		kfree(aead_instance(inst));
298c926c6   Adrian Hoban   crypto: cryptd - ...
870
871
872
873
  		return;
  	default:
  		crypto_drop_spawn(&ctx->spawn);
  		kfree(inst);
0b535adfb   Herbert Xu   crypto: cryptd - ...
874
  	}
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
875
876
877
878
  }
  
  static struct crypto_template cryptd_tmpl = {
  	.name = "cryptd",
9cd899a32   Herbert Xu   crypto: cryptd - ...
879
  	.create = cryptd_create,
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
880
881
882
  	.free = cryptd_free,
  	.module = THIS_MODULE,
  };
1cac2cbc7   Huang Ying   crypto: cryptd - ...
883
884
885
886
  struct cryptd_ablkcipher *cryptd_alloc_ablkcipher(const char *alg_name,
  						  u32 type, u32 mask)
  {
  	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
81760ea6a   Herbert Xu   crypto: cryptd - ...
887
  	struct cryptd_blkcipher_ctx *ctx;
505fd21d6   Huang Ying   crypto: cryptd - ...
888
  	struct crypto_tfm *tfm;
1cac2cbc7   Huang Ying   crypto: cryptd - ...
889
890
891
892
  
  	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
  		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
  		return ERR_PTR(-EINVAL);
c012a79d0   Alexander Kuleshov   crypto: cryptod -...
893
  	type = crypto_skcipher_type(type);
505fd21d6   Huang Ying   crypto: cryptd - ...
894
895
896
  	mask &= ~CRYPTO_ALG_TYPE_MASK;
  	mask |= (CRYPTO_ALG_GENIV | CRYPTO_ALG_TYPE_BLKCIPHER_MASK);
  	tfm = crypto_alloc_base(cryptd_alg_name, type, mask);
1cac2cbc7   Huang Ying   crypto: cryptd - ...
897
898
  	if (IS_ERR(tfm))
  		return ERR_CAST(tfm);
505fd21d6   Huang Ying   crypto: cryptd - ...
899
900
  	if (tfm->__crt_alg->cra_module != THIS_MODULE) {
  		crypto_free_tfm(tfm);
1cac2cbc7   Huang Ying   crypto: cryptd - ...
901
902
  		return ERR_PTR(-EINVAL);
  	}
81760ea6a   Herbert Xu   crypto: cryptd - ...
903
904
  	ctx = crypto_tfm_ctx(tfm);
  	atomic_set(&ctx->refcnt, 1);
505fd21d6   Huang Ying   crypto: cryptd - ...
905
  	return __cryptd_ablkcipher_cast(__crypto_ablkcipher_cast(tfm));
1cac2cbc7   Huang Ying   crypto: cryptd - ...
906
907
908
909
910
911
912
913
914
  }
  EXPORT_SYMBOL_GPL(cryptd_alloc_ablkcipher);
  
  struct crypto_blkcipher *cryptd_ablkcipher_child(struct cryptd_ablkcipher *tfm)
  {
  	struct cryptd_blkcipher_ctx *ctx = crypto_ablkcipher_ctx(&tfm->base);
  	return ctx->child;
  }
  EXPORT_SYMBOL_GPL(cryptd_ablkcipher_child);
81760ea6a   Herbert Xu   crypto: cryptd - ...
915
916
917
918
919
920
921
  bool cryptd_ablkcipher_queued(struct cryptd_ablkcipher *tfm)
  {
  	struct cryptd_blkcipher_ctx *ctx = crypto_ablkcipher_ctx(&tfm->base);
  
  	return atomic_read(&ctx->refcnt) - 1;
  }
  EXPORT_SYMBOL_GPL(cryptd_ablkcipher_queued);
1cac2cbc7   Huang Ying   crypto: cryptd - ...
922
923
  void cryptd_free_ablkcipher(struct cryptd_ablkcipher *tfm)
  {
81760ea6a   Herbert Xu   crypto: cryptd - ...
924
925
926
927
  	struct cryptd_blkcipher_ctx *ctx = crypto_ablkcipher_ctx(&tfm->base);
  
  	if (atomic_dec_and_test(&ctx->refcnt))
  		crypto_free_ablkcipher(&tfm->base);
1cac2cbc7   Huang Ying   crypto: cryptd - ...
928
929
  }
  EXPORT_SYMBOL_GPL(cryptd_free_ablkcipher);
ace136636   Huang Ying   crypto: cryptd - ...
930
931
932
933
  struct cryptd_ahash *cryptd_alloc_ahash(const char *alg_name,
  					u32 type, u32 mask)
  {
  	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
81760ea6a   Herbert Xu   crypto: cryptd - ...
934
  	struct cryptd_hash_ctx *ctx;
ace136636   Huang Ying   crypto: cryptd - ...
935
936
937
938
939
940
941
942
943
944
945
946
  	struct crypto_ahash *tfm;
  
  	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
  		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
  		return ERR_PTR(-EINVAL);
  	tfm = crypto_alloc_ahash(cryptd_alg_name, type, mask);
  	if (IS_ERR(tfm))
  		return ERR_CAST(tfm);
  	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
  		crypto_free_ahash(tfm);
  		return ERR_PTR(-EINVAL);
  	}
81760ea6a   Herbert Xu   crypto: cryptd - ...
947
948
  	ctx = crypto_ahash_ctx(tfm);
  	atomic_set(&ctx->refcnt, 1);
ace136636   Huang Ying   crypto: cryptd - ...
949
950
951
952
953
954
955
956
957
958
959
  	return __cryptd_ahash_cast(tfm);
  }
  EXPORT_SYMBOL_GPL(cryptd_alloc_ahash);
  
  struct crypto_shash *cryptd_ahash_child(struct cryptd_ahash *tfm)
  {
  	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
  
  	return ctx->child;
  }
  EXPORT_SYMBOL_GPL(cryptd_ahash_child);
0e1227d35   Huang Ying   crypto: ghash - A...
960
961
962
963
964
965
  struct shash_desc *cryptd_shash_desc(struct ahash_request *req)
  {
  	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
  	return &rctx->desc;
  }
  EXPORT_SYMBOL_GPL(cryptd_shash_desc);
81760ea6a   Herbert Xu   crypto: cryptd - ...
966
967
968
969
970
971
972
  bool cryptd_ahash_queued(struct cryptd_ahash *tfm)
  {
  	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
  
  	return atomic_read(&ctx->refcnt) - 1;
  }
  EXPORT_SYMBOL_GPL(cryptd_ahash_queued);
ace136636   Huang Ying   crypto: cryptd - ...
973
974
  void cryptd_free_ahash(struct cryptd_ahash *tfm)
  {
81760ea6a   Herbert Xu   crypto: cryptd - ...
975
976
977
978
  	struct cryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
  
  	if (atomic_dec_and_test(&ctx->refcnt))
  		crypto_free_ahash(&tfm->base);
ace136636   Huang Ying   crypto: cryptd - ...
979
980
  }
  EXPORT_SYMBOL_GPL(cryptd_free_ahash);
298c926c6   Adrian Hoban   crypto: cryptd - ...
981
982
983
984
  struct cryptd_aead *cryptd_alloc_aead(const char *alg_name,
  						  u32 type, u32 mask)
  {
  	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
81760ea6a   Herbert Xu   crypto: cryptd - ...
985
  	struct cryptd_aead_ctx *ctx;
298c926c6   Adrian Hoban   crypto: cryptd - ...
986
987
988
989
990
991
992
993
994
995
996
997
  	struct crypto_aead *tfm;
  
  	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
  		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
  		return ERR_PTR(-EINVAL);
  	tfm = crypto_alloc_aead(cryptd_alg_name, type, mask);
  	if (IS_ERR(tfm))
  		return ERR_CAST(tfm);
  	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
  		crypto_free_aead(tfm);
  		return ERR_PTR(-EINVAL);
  	}
81760ea6a   Herbert Xu   crypto: cryptd - ...
998
999
1000
  
  	ctx = crypto_aead_ctx(tfm);
  	atomic_set(&ctx->refcnt, 1);
298c926c6   Adrian Hoban   crypto: cryptd - ...
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
  	return __cryptd_aead_cast(tfm);
  }
  EXPORT_SYMBOL_GPL(cryptd_alloc_aead);
  
  struct crypto_aead *cryptd_aead_child(struct cryptd_aead *tfm)
  {
  	struct cryptd_aead_ctx *ctx;
  	ctx = crypto_aead_ctx(&tfm->base);
  	return ctx->child;
  }
  EXPORT_SYMBOL_GPL(cryptd_aead_child);
81760ea6a   Herbert Xu   crypto: cryptd - ...
1012
1013
1014
1015
1016
1017
1018
  bool cryptd_aead_queued(struct cryptd_aead *tfm)
  {
  	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(&tfm->base);
  
  	return atomic_read(&ctx->refcnt) - 1;
  }
  EXPORT_SYMBOL_GPL(cryptd_aead_queued);
298c926c6   Adrian Hoban   crypto: cryptd - ...
1019
1020
  void cryptd_free_aead(struct cryptd_aead *tfm)
  {
81760ea6a   Herbert Xu   crypto: cryptd - ...
1021
1022
1023
1024
  	struct cryptd_aead_ctx *ctx = crypto_aead_ctx(&tfm->base);
  
  	if (atomic_dec_and_test(&ctx->refcnt))
  		crypto_free_aead(&tfm->base);
298c926c6   Adrian Hoban   crypto: cryptd - ...
1025
1026
  }
  EXPORT_SYMBOL_GPL(cryptd_free_aead);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
1027
1028
1029
  static int __init cryptd_init(void)
  {
  	int err;
254eff771   Huang Ying   crypto: cryptd - ...
1030
  	err = cryptd_init_queue(&queue, CRYPTD_MAX_CPU_QLEN);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
1031
1032
1033
1034
1035
  	if (err)
  		return err;
  
  	err = crypto_register_template(&cryptd_tmpl);
  	if (err)
254eff771   Huang Ying   crypto: cryptd - ...
1036
  		cryptd_fini_queue(&queue);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
1037
1038
1039
1040
1041
1042
  
  	return err;
  }
  
  static void __exit cryptd_exit(void)
  {
254eff771   Huang Ying   crypto: cryptd - ...
1043
  	cryptd_fini_queue(&queue);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
1044
1045
  	crypto_unregister_template(&cryptd_tmpl);
  }
b2bac6acf   Herbert Xu   crypto: cryptd - ...
1046
  subsys_initcall(cryptd_init);
124b53d02   Herbert Xu   [CRYPTO] cryptd: ...
1047
1048
1049
1050
  module_exit(cryptd_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Software async crypto daemon");
4943ba16b   Kees Cook   crypto: include c...
1051
  MODULE_ALIAS_CRYPTO("cryptd");