Blame view

crypto/algif_skcipher.c 21.1 KB
8ff590903   Herbert Xu   crypto: algif_skc...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   * algif_skcipher: User-space interface for skcipher algorithms
   *
   * This file provides the user-space API for symmetric key ciphers.
   *
   * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
   *
   * 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/scatterwalk.h>
  #include <crypto/skcipher.h>
  #include <crypto/if_alg.h>
  #include <linux/init.h>
  #include <linux/list.h>
  #include <linux/kernel.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
21
  #include <linux/sched/signal.h>
8ff590903   Herbert Xu   crypto: algif_skc...
22
23
24
25
26
27
28
29
30
31
32
33
  #include <linux/mm.h>
  #include <linux/module.h>
  #include <linux/net.h>
  #include <net/sock.h>
  
  struct skcipher_sg_list {
  	struct list_head list;
  
  	int cur;
  
  	struct scatterlist sg[0];
  };
dd5045895   Herbert Xu   crypto: algif_skc...
34
35
36
37
  struct skcipher_tfm {
  	struct crypto_skcipher *skcipher;
  	bool has_key;
  };
8ff590903   Herbert Xu   crypto: algif_skc...
38
39
40
41
42
43
44
  struct skcipher_ctx {
  	struct list_head tsgl;
  	struct af_alg_sgl rsgl;
  
  	void *iv;
  
  	struct af_alg_completion completion;
a596999b7   Tadeusz Struk   crypto: algif - c...
45
  	atomic_t inflight;
652d5b8a8   LABBE Corentin   crypto: algif - C...
46
  	size_t used;
8ff590903   Herbert Xu   crypto: algif_skc...
47
48
49
50
51
  
  	unsigned int len;
  	bool more;
  	bool merge;
  	bool enc;
0d96e4bab   Herbert Xu   crypto: algif_skc...
52
  	struct skcipher_request req;
8ff590903   Herbert Xu   crypto: algif_skc...
53
  };
a596999b7   Tadeusz Struk   crypto: algif - c...
54
55
56
57
58
59
60
61
62
63
  struct skcipher_async_rsgl {
  	struct af_alg_sgl sgl;
  	struct list_head list;
  };
  
  struct skcipher_async_req {
  	struct kiocb *iocb;
  	struct skcipher_async_rsgl first_sgl;
  	struct list_head list;
  	struct scatterlist *tsg;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
64
65
  	atomic_t *inflight;
  	struct skcipher_request req;
a596999b7   Tadeusz Struk   crypto: algif - c...
66
  };
e2cffb5f4   Ondrej Kozina   crypto: algif - a...
67
  #define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
8ff590903   Herbert Xu   crypto: algif_skc...
68
  		      sizeof(struct scatterlist) - 1)
a596999b7   Tadeusz Struk   crypto: algif - c...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  static void skcipher_free_async_sgls(struct skcipher_async_req *sreq)
  {
  	struct skcipher_async_rsgl *rsgl, *tmp;
  	struct scatterlist *sgl;
  	struct scatterlist *sg;
  	int i, n;
  
  	list_for_each_entry_safe(rsgl, tmp, &sreq->list, list) {
  		af_alg_free_sg(&rsgl->sgl);
  		if (rsgl != &sreq->first_sgl)
  			kfree(rsgl);
  	}
  	sgl = sreq->tsg;
  	n = sg_nents(sgl);
  	for_each_sg(sgl, sg, n, i)
  		put_page(sg_page(sg));
  
  	kfree(sreq->tsg);
  }
  
  static void skcipher_async_cb(struct crypto_async_request *req, int err)
  {
ec69bbfb9   Herbert Xu   crypto: algif_skc...
91
  	struct skcipher_async_req *sreq = req->data;
a596999b7   Tadeusz Struk   crypto: algif - c...
92
  	struct kiocb *iocb = sreq->iocb;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
93
  	atomic_dec(sreq->inflight);
a596999b7   Tadeusz Struk   crypto: algif - c...
94
  	skcipher_free_async_sgls(sreq);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
95
  	kzfree(sreq);
237dae889   Al Viro   Merge branch 'ioc...
96
  	iocb->ki_complete(iocb, err, err);
a596999b7   Tadeusz Struk   crypto: algif - c...
97
  }
0f6bb83cb   Herbert Xu   crypto: algif_skc...
98
  static inline int skcipher_sndbuf(struct sock *sk)
8ff590903   Herbert Xu   crypto: algif_skc...
99
100
101
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
0f6bb83cb   Herbert Xu   crypto: algif_skc...
102
103
104
105
106
107
108
  	return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
  			  ctx->used, 0);
  }
  
  static inline bool skcipher_writable(struct sock *sk)
  {
  	return PAGE_SIZE <= skcipher_sndbuf(sk);
8ff590903   Herbert Xu   crypto: algif_skc...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  }
  
  static int skcipher_alloc_sgl(struct sock *sk)
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	struct skcipher_sg_list *sgl;
  	struct scatterlist *sg = NULL;
  
  	sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
  	if (!list_empty(&ctx->tsgl))
  		sg = sgl->sg;
  
  	if (!sg || sgl->cur >= MAX_SGL_ENTS) {
  		sgl = sock_kmalloc(sk, sizeof(*sgl) +
  				       sizeof(sgl->sg[0]) * (MAX_SGL_ENTS + 1),
  				   GFP_KERNEL);
  		if (!sgl)
  			return -ENOMEM;
  
  		sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
  		sgl->cur = 0;
  
  		if (sg)
c56f6d127   Dan Williams   crypto: replace s...
133
  			sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
8ff590903   Herbert Xu   crypto: algif_skc...
134
135
136
137
138
139
  
  		list_add_tail(&sgl->list, &ctx->tsgl);
  	}
  
  	return 0;
  }
652d5b8a8   LABBE Corentin   crypto: algif - C...
140
  static void skcipher_pull_sgl(struct sock *sk, size_t used, int put)
8ff590903   Herbert Xu   crypto: algif_skc...
141
142
143
144
145
146
147
148
149
150
151
152
153
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	struct skcipher_sg_list *sgl;
  	struct scatterlist *sg;
  	int i;
  
  	while (!list_empty(&ctx->tsgl)) {
  		sgl = list_first_entry(&ctx->tsgl, struct skcipher_sg_list,
  				       list);
  		sg = sgl->sg;
  
  		for (i = 0; i < sgl->cur; i++) {
652d5b8a8   LABBE Corentin   crypto: algif - C...
154
  			size_t plen = min_t(size_t, used, sg[i].length);
8ff590903   Herbert Xu   crypto: algif_skc...
155
156
157
158
159
160
161
162
163
164
165
166
  
  			if (!sg_page(sg + i))
  				continue;
  
  			sg[i].length -= plen;
  			sg[i].offset += plen;
  
  			used -= plen;
  			ctx->used -= plen;
  
  			if (sg[i].length)
  				return;
a596999b7   Tadeusz Struk   crypto: algif - c...
167
168
  			if (put)
  				put_page(sg_page(sg + i));
8ff590903   Herbert Xu   crypto: algif_skc...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  			sg_assign_page(sg + i, NULL);
  		}
  
  		list_del(&sgl->list);
  		sock_kfree_s(sk, sgl,
  			     sizeof(*sgl) + sizeof(sgl->sg[0]) *
  					    (MAX_SGL_ENTS + 1));
  	}
  
  	if (!ctx->used)
  		ctx->merge = 0;
  }
  
  static void skcipher_free_sgl(struct sock *sk)
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
a596999b7   Tadeusz Struk   crypto: algif - c...
186
  	skcipher_pull_sgl(sk, ctx->used, 1);
8ff590903   Herbert Xu   crypto: algif_skc...
187
188
189
190
  }
  
  static int skcipher_wait_for_wmem(struct sock *sk, unsigned flags)
  {
d9dc8b0f8   WANG Cong   net: fix sleeping...
191
  	DEFINE_WAIT_FUNC(wait, woken_wake_function);
8ff590903   Herbert Xu   crypto: algif_skc...
192
  	int err = -ERESTARTSYS;
d9dc8b0f8   WANG Cong   net: fix sleeping...
193
  	long timeout;
8ff590903   Herbert Xu   crypto: algif_skc...
194
195
196
  
  	if (flags & MSG_DONTWAIT)
  		return -EAGAIN;
9cd3e072b   Eric Dumazet   net: rename SOCK_...
197
  	sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
8ff590903   Herbert Xu   crypto: algif_skc...
198

d9dc8b0f8   WANG Cong   net: fix sleeping...
199
  	add_wait_queue(sk_sleep(sk), &wait);
8ff590903   Herbert Xu   crypto: algif_skc...
200
201
202
  	for (;;) {
  		if (signal_pending(current))
  			break;
8ff590903   Herbert Xu   crypto: algif_skc...
203
  		timeout = MAX_SCHEDULE_TIMEOUT;
d9dc8b0f8   WANG Cong   net: fix sleeping...
204
  		if (sk_wait_event(sk, &timeout, skcipher_writable(sk), &wait)) {
8ff590903   Herbert Xu   crypto: algif_skc...
205
206
207
208
  			err = 0;
  			break;
  		}
  	}
d9dc8b0f8   WANG Cong   net: fix sleeping...
209
  	remove_wait_queue(sk_sleep(sk), &wait);
8ff590903   Herbert Xu   crypto: algif_skc...
210
211
212
213
214
215
216
217
218
219
220
221
222
  
  	return err;
  }
  
  static void skcipher_wmem_wakeup(struct sock *sk)
  {
  	struct socket_wq *wq;
  
  	if (!skcipher_writable(sk))
  		return;
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
1ce0bf50a   Herbert Xu   net: Generalise w...
223
  	if (skwq_has_sleeper(wq))
8ff590903   Herbert Xu   crypto: algif_skc...
224
225
226
227
228
229
230
231
232
  		wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
  							   POLLRDNORM |
  							   POLLRDBAND);
  	sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
  	rcu_read_unlock();
  }
  
  static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
  {
d9dc8b0f8   WANG Cong   net: fix sleeping...
233
  	DEFINE_WAIT_FUNC(wait, woken_wake_function);
8ff590903   Herbert Xu   crypto: algif_skc...
234
235
236
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	long timeout;
8ff590903   Herbert Xu   crypto: algif_skc...
237
238
239
240
241
  	int err = -ERESTARTSYS;
  
  	if (flags & MSG_DONTWAIT) {
  		return -EAGAIN;
  	}
9cd3e072b   Eric Dumazet   net: rename SOCK_...
242
  	sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
8ff590903   Herbert Xu   crypto: algif_skc...
243

d9dc8b0f8   WANG Cong   net: fix sleeping...
244
  	add_wait_queue(sk_sleep(sk), &wait);
8ff590903   Herbert Xu   crypto: algif_skc...
245
246
247
  	for (;;) {
  		if (signal_pending(current))
  			break;
8ff590903   Herbert Xu   crypto: algif_skc...
248
  		timeout = MAX_SCHEDULE_TIMEOUT;
d9dc8b0f8   WANG Cong   net: fix sleeping...
249
  		if (sk_wait_event(sk, &timeout, ctx->used, &wait)) {
8ff590903   Herbert Xu   crypto: algif_skc...
250
251
252
253
  			err = 0;
  			break;
  		}
  	}
d9dc8b0f8   WANG Cong   net: fix sleeping...
254
  	remove_wait_queue(sk_sleep(sk), &wait);
8ff590903   Herbert Xu   crypto: algif_skc...
255

9cd3e072b   Eric Dumazet   net: rename SOCK_...
256
  	sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
8ff590903   Herbert Xu   crypto: algif_skc...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  
  	return err;
  }
  
  static void skcipher_data_wakeup(struct sock *sk)
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	struct socket_wq *wq;
  
  	if (!ctx->used)
  		return;
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
1ce0bf50a   Herbert Xu   net: Generalise w...
272
  	if (skwq_has_sleeper(wq))
8ff590903   Herbert Xu   crypto: algif_skc...
273
274
275
276
277
278
  		wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
  							   POLLRDNORM |
  							   POLLRDBAND);
  	sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
  	rcu_read_unlock();
  }
1b7841404   Ying Xue   net: Remove iocb ...
279
280
  static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
  			    size_t size)
8ff590903   Herbert Xu   crypto: algif_skc...
281
282
283
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
6454c2b83   Herbert Xu   crypto: algif_skc...
284
285
  	struct sock *psk = ask->parent;
  	struct alg_sock *pask = alg_sk(psk);
8ff590903   Herbert Xu   crypto: algif_skc...
286
  	struct skcipher_ctx *ctx = ask->private;
6454c2b83   Herbert Xu   crypto: algif_skc...
287
288
  	struct skcipher_tfm *skc = pask->private;
  	struct crypto_skcipher *tfm = skc->skcipher;
0d96e4bab   Herbert Xu   crypto: algif_skc...
289
  	unsigned ivsize = crypto_skcipher_ivsize(tfm);
8ff590903   Herbert Xu   crypto: algif_skc...
290
291
292
293
  	struct skcipher_sg_list *sgl;
  	struct af_alg_control con = {};
  	long copied = 0;
  	bool enc = 0;
f26b7b805   Stephan Mueller   crypto: algif_skc...
294
  	bool init = 0;
8ff590903   Herbert Xu   crypto: algif_skc...
295
296
297
298
299
300
301
  	int err;
  	int i;
  
  	if (msg->msg_controllen) {
  		err = af_alg_cmsg_send(msg, &con);
  		if (err)
  			return err;
f26b7b805   Stephan Mueller   crypto: algif_skc...
302
  		init = 1;
8ff590903   Herbert Xu   crypto: algif_skc...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  		switch (con.op) {
  		case ALG_OP_ENCRYPT:
  			enc = 1;
  			break;
  		case ALG_OP_DECRYPT:
  			enc = 0;
  			break;
  		default:
  			return -EINVAL;
  		}
  
  		if (con.iv && con.iv->ivlen != ivsize)
  			return -EINVAL;
  	}
  
  	err = -EINVAL;
  
  	lock_sock(sk);
  	if (!ctx->more && ctx->used)
  		goto unlock;
f26b7b805   Stephan Mueller   crypto: algif_skc...
323
  	if (init) {
8ff590903   Herbert Xu   crypto: algif_skc...
324
325
326
327
  		ctx->enc = enc;
  		if (con.iv)
  			memcpy(ctx->iv, con.iv->iv, ivsize);
  	}
8ff590903   Herbert Xu   crypto: algif_skc...
328
329
330
  	while (size) {
  		struct scatterlist *sg;
  		unsigned long len = size;
652d5b8a8   LABBE Corentin   crypto: algif - C...
331
  		size_t plen;
8ff590903   Herbert Xu   crypto: algif_skc...
332
333
334
335
336
337
338
  
  		if (ctx->merge) {
  			sgl = list_entry(ctx->tsgl.prev,
  					 struct skcipher_sg_list, list);
  			sg = sgl->sg + sgl->cur - 1;
  			len = min_t(unsigned long, len,
  				    PAGE_SIZE - sg->offset - sg->length);
6ce8e9ce5   Al Viro   new helper: memcp...
339
340
341
  			err = memcpy_from_msg(page_address(sg_page(sg)) +
  					      sg->offset + sg->length,
  					      msg, len);
8ff590903   Herbert Xu   crypto: algif_skc...
342
343
344
345
346
347
348
349
350
351
  			if (err)
  				goto unlock;
  
  			sg->length += len;
  			ctx->merge = (sg->offset + sg->length) &
  				     (PAGE_SIZE - 1);
  
  			ctx->used += len;
  			copied += len;
  			size -= len;
8ff590903   Herbert Xu   crypto: algif_skc...
352
353
  			continue;
  		}
0f6bb83cb   Herbert Xu   crypto: algif_skc...
354
  		if (!skcipher_writable(sk)) {
8ff590903   Herbert Xu   crypto: algif_skc...
355
356
357
  			err = skcipher_wait_for_wmem(sk, msg->msg_flags);
  			if (err)
  				goto unlock;
8ff590903   Herbert Xu   crypto: algif_skc...
358
  		}
0f6bb83cb   Herbert Xu   crypto: algif_skc...
359
  		len = min_t(unsigned long, len, skcipher_sndbuf(sk));
8ff590903   Herbert Xu   crypto: algif_skc...
360
361
362
363
364
365
366
  
  		err = skcipher_alloc_sgl(sk);
  		if (err)
  			goto unlock;
  
  		sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
  		sg = sgl->sg;
202736d99   Herbert Xu   crypto: algif_skc...
367
368
  		if (sgl->cur)
  			sg_unmark_end(sg + sgl->cur - 1);
8ff590903   Herbert Xu   crypto: algif_skc...
369
370
  		do {
  			i = sgl->cur;
652d5b8a8   LABBE Corentin   crypto: algif - C...
371
  			plen = min_t(size_t, len, PAGE_SIZE);
8ff590903   Herbert Xu   crypto: algif_skc...
372
373
374
375
376
  
  			sg_assign_page(sg + i, alloc_page(GFP_KERNEL));
  			err = -ENOMEM;
  			if (!sg_page(sg + i))
  				goto unlock;
6ce8e9ce5   Al Viro   new helper: memcp...
377
378
  			err = memcpy_from_msg(page_address(sg_page(sg + i)),
  					      msg, plen);
8ff590903   Herbert Xu   crypto: algif_skc...
379
380
381
382
383
384
385
386
387
388
389
  			if (err) {
  				__free_page(sg_page(sg + i));
  				sg_assign_page(sg + i, NULL);
  				goto unlock;
  			}
  
  			sg[i].length = plen;
  			len -= plen;
  			ctx->used += plen;
  			copied += plen;
  			size -= plen;
8ff590903   Herbert Xu   crypto: algif_skc...
390
391
  			sgl->cur++;
  		} while (len && sgl->cur < MAX_SGL_ENTS);
0f477b655   Tadeusz Struk   crypto: algif - M...
392
393
  		if (!size)
  			sg_mark_end(sg + sgl->cur - 1);
8ff590903   Herbert Xu   crypto: algif_skc...
394
395
396
397
398
399
  		ctx->merge = plen & (PAGE_SIZE - 1);
  	}
  
  	err = 0;
  
  	ctx->more = msg->msg_flags & MSG_MORE;
8ff590903   Herbert Xu   crypto: algif_skc...
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  
  unlock:
  	skcipher_data_wakeup(sk);
  	release_sock(sk);
  
  	return copied ?: err;
  }
  
  static ssize_t skcipher_sendpage(struct socket *sock, struct page *page,
  				 int offset, size_t size, int flags)
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	struct skcipher_sg_list *sgl;
  	int err = -EINVAL;
8ff590903   Herbert Xu   crypto: algif_skc...
416

d3f7d56a7   Shawn Landden   net: update consu...
417
418
  	if (flags & MSG_SENDPAGE_NOTLAST)
  		flags |= MSG_MORE;
8ff590903   Herbert Xu   crypto: algif_skc...
419
420
421
422
423
424
  	lock_sock(sk);
  	if (!ctx->more && ctx->used)
  		goto unlock;
  
  	if (!size)
  		goto done;
0f6bb83cb   Herbert Xu   crypto: algif_skc...
425
  	if (!skcipher_writable(sk)) {
8ff590903   Herbert Xu   crypto: algif_skc...
426
427
428
  		err = skcipher_wait_for_wmem(sk, flags);
  		if (err)
  			goto unlock;
8ff590903   Herbert Xu   crypto: algif_skc...
429
430
431
432
433
434
435
436
  	}
  
  	err = skcipher_alloc_sgl(sk);
  	if (err)
  		goto unlock;
  
  	ctx->merge = 0;
  	sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
0f477b655   Tadeusz Struk   crypto: algif - M...
437
438
439
440
  	if (sgl->cur)
  		sg_unmark_end(sgl->sg + sgl->cur - 1);
  
  	sg_mark_end(sgl->sg + sgl->cur);
8ff590903   Herbert Xu   crypto: algif_skc...
441
442
443
444
445
446
447
  	get_page(page);
  	sg_set_page(sgl->sg + sgl->cur, page, size, offset);
  	sgl->cur++;
  	ctx->used += size;
  
  done:
  	ctx->more = flags & MSG_MORE;
8ff590903   Herbert Xu   crypto: algif_skc...
448
449
450
451
452
453
454
  
  unlock:
  	skcipher_data_wakeup(sk);
  	release_sock(sk);
  
  	return err ?: size;
  }
a596999b7   Tadeusz Struk   crypto: algif - c...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
  static int skcipher_all_sg_nents(struct skcipher_ctx *ctx)
  {
  	struct skcipher_sg_list *sgl;
  	struct scatterlist *sg;
  	int nents = 0;
  
  	list_for_each_entry(sgl, &ctx->tsgl, list) {
  		sg = sgl->sg;
  
  		while (!sg->length)
  			sg++;
  
  		nents += sg_nents(sg);
  	}
  	return nents;
  }
  
  static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
  				  int flags)
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
477
478
  	struct sock *psk = ask->parent;
  	struct alg_sock *pask = alg_sk(psk);
a596999b7   Tadeusz Struk   crypto: algif - c...
479
  	struct skcipher_ctx *ctx = ask->private;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
480
481
  	struct skcipher_tfm *skc = pask->private;
  	struct crypto_skcipher *tfm = skc->skcipher;
a596999b7   Tadeusz Struk   crypto: algif - c...
482
483
484
  	struct skcipher_sg_list *sgl;
  	struct scatterlist *sg;
  	struct skcipher_async_req *sreq;
0d96e4bab   Herbert Xu   crypto: algif_skc...
485
  	struct skcipher_request *req;
a596999b7   Tadeusz Struk   crypto: algif - c...
486
  	struct skcipher_async_rsgl *last_rsgl = NULL;
6454c2b83   Herbert Xu   crypto: algif_skc...
487
  	unsigned int txbufs = 0, len = 0, tx_nents;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
488
489
  	unsigned int reqsize = crypto_skcipher_reqsize(tfm);
  	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
a596999b7   Tadeusz Struk   crypto: algif - c...
490
  	int err = -ENOMEM;
033f46b3c   tadeusz.struk@intel.com   crypto: algif - e...
491
  	bool mark = false;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
492
  	char *iv;
a596999b7   Tadeusz Struk   crypto: algif - c...
493

ec69bbfb9   Herbert Xu   crypto: algif_skc...
494
495
496
  	sreq = kzalloc(sizeof(*sreq) + reqsize + ivsize, GFP_KERNEL);
  	if (unlikely(!sreq))
  		goto out;
a596999b7   Tadeusz Struk   crypto: algif - c...
497

ec69bbfb9   Herbert Xu   crypto: algif_skc...
498
499
  	req = &sreq->req;
  	iv = (char *)(req + 1) + reqsize;
a596999b7   Tadeusz Struk   crypto: algif - c...
500
  	sreq->iocb = msg->msg_iocb;
a596999b7   Tadeusz Struk   crypto: algif - c...
501
  	INIT_LIST_HEAD(&sreq->list);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
502
503
504
  	sreq->inflight = &ctx->inflight;
  
  	lock_sock(sk);
6454c2b83   Herbert Xu   crypto: algif_skc...
505
  	tx_nents = skcipher_all_sg_nents(ctx);
a596999b7   Tadeusz Struk   crypto: algif - c...
506
  	sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
507
  	if (unlikely(!sreq->tsg))
a596999b7   Tadeusz Struk   crypto: algif - c...
508
  		goto unlock;
a596999b7   Tadeusz Struk   crypto: algif - c...
509
  	sg_init_table(sreq->tsg, tx_nents);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
510
511
  	memcpy(iv, ctx->iv, ivsize);
  	skcipher_request_set_tfm(req, tfm);
dad419970   Herbert Xu   crypto: algif_skc...
512
  	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
ec69bbfb9   Herbert Xu   crypto: algif_skc...
513
  				      skcipher_async_cb, sreq);
a596999b7   Tadeusz Struk   crypto: algif - c...
514
515
516
  
  	while (iov_iter_count(&msg->msg_iter)) {
  		struct skcipher_async_rsgl *rsgl;
ac110f495   tadeusz.struk@intel.com   crypto: algif - f...
517
  		int used;
a596999b7   Tadeusz Struk   crypto: algif - c...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  
  		if (!ctx->used) {
  			err = skcipher_wait_for_data(sk, flags);
  			if (err)
  				goto free;
  		}
  		sgl = list_first_entry(&ctx->tsgl,
  				       struct skcipher_sg_list, list);
  		sg = sgl->sg;
  
  		while (!sg->length)
  			sg++;
  
  		used = min_t(unsigned long, ctx->used,
  			     iov_iter_count(&msg->msg_iter));
  		used = min_t(unsigned long, used, sg->length);
033f46b3c   tadeusz.struk@intel.com   crypto: algif - e...
534
  		if (txbufs == tx_nents) {
a596999b7   Tadeusz Struk   crypto: algif - c...
535
536
537
538
539
540
  			struct scatterlist *tmp;
  			int x;
  			/* Ran out of tx slots in async request
  			 * need to expand */
  			tmp = kcalloc(tx_nents * 2, sizeof(*tmp),
  				      GFP_KERNEL);
e2c1b8233   Pan Bian   crypto: algif_skc...
541
542
  			if (!tmp) {
  				err = -ENOMEM;
a596999b7   Tadeusz Struk   crypto: algif - c...
543
  				goto free;
e2c1b8233   Pan Bian   crypto: algif_skc...
544
  			}
a596999b7   Tadeusz Struk   crypto: algif - c...
545
546
547
548
549
550
551
552
553
  
  			sg_init_table(tmp, tx_nents * 2);
  			for (x = 0; x < tx_nents; x++)
  				sg_set_page(&tmp[x], sg_page(&sreq->tsg[x]),
  					    sreq->tsg[x].length,
  					    sreq->tsg[x].offset);
  			kfree(sreq->tsg);
  			sreq->tsg = tmp;
  			tx_nents *= 2;
033f46b3c   tadeusz.struk@intel.com   crypto: algif - e...
554
  			mark = true;
a596999b7   Tadeusz Struk   crypto: algif - c...
555
556
557
  		}
  		/* Need to take over the tx sgl from ctx
  		 * to the asynch req - these sgls will be freed later */
033f46b3c   tadeusz.struk@intel.com   crypto: algif - e...
558
  		sg_set_page(sreq->tsg + txbufs++, sg_page(sg), sg->length,
a596999b7   Tadeusz Struk   crypto: algif - c...
559
560
561
562
563
564
  			    sg->offset);
  
  		if (list_empty(&sreq->list)) {
  			rsgl = &sreq->first_sgl;
  			list_add_tail(&rsgl->list, &sreq->list);
  		} else {
82d929207   Tadeusz Struk   crypto: algif - u...
565
  			rsgl = kmalloc(sizeof(*rsgl), GFP_KERNEL);
a596999b7   Tadeusz Struk   crypto: algif - c...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
  			if (!rsgl) {
  				err = -ENOMEM;
  				goto free;
  			}
  			list_add_tail(&rsgl->list, &sreq->list);
  		}
  
  		used = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, used);
  		err = used;
  		if (used < 0)
  			goto free;
  		if (last_rsgl)
  			af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl);
  
  		last_rsgl = rsgl;
  		len += used;
  		skcipher_pull_sgl(sk, used, 0);
  		iov_iter_advance(&msg->msg_iter, used);
  	}
033f46b3c   tadeusz.struk@intel.com   crypto: algif - e...
585
586
  	if (mark)
  		sg_mark_end(sreq->tsg + txbufs - 1);
0d96e4bab   Herbert Xu   crypto: algif_skc...
587
  	skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
ec69bbfb9   Herbert Xu   crypto: algif_skc...
588
  				   len, iv);
0d96e4bab   Herbert Xu   crypto: algif_skc...
589
590
  	err = ctx->enc ? crypto_skcipher_encrypt(req) :
  			 crypto_skcipher_decrypt(req);
a596999b7   Tadeusz Struk   crypto: algif - c...
591
592
593
  	if (err == -EINPROGRESS) {
  		atomic_inc(&ctx->inflight);
  		err = -EIOCBQUEUED;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
594
  		sreq = NULL;
a596999b7   Tadeusz Struk   crypto: algif - c...
595
596
597
598
  		goto unlock;
  	}
  free:
  	skcipher_free_async_sgls(sreq);
a596999b7   Tadeusz Struk   crypto: algif - c...
599
600
601
  unlock:
  	skcipher_wmem_wakeup(sk);
  	release_sock(sk);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
602
603
  	kzfree(sreq);
  out:
a596999b7   Tadeusz Struk   crypto: algif - c...
604
605
606
607
608
  	return err;
  }
  
  static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
  				 int flags)
8ff590903   Herbert Xu   crypto: algif_skc...
609
610
611
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
6454c2b83   Herbert Xu   crypto: algif_skc...
612
613
  	struct sock *psk = ask->parent;
  	struct alg_sock *pask = alg_sk(psk);
8ff590903   Herbert Xu   crypto: algif_skc...
614
  	struct skcipher_ctx *ctx = ask->private;
6454c2b83   Herbert Xu   crypto: algif_skc...
615
616
617
  	struct skcipher_tfm *skc = pask->private;
  	struct crypto_skcipher *tfm = skc->skcipher;
  	unsigned bs = crypto_skcipher_blocksize(tfm);
8ff590903   Herbert Xu   crypto: algif_skc...
618
619
  	struct skcipher_sg_list *sgl;
  	struct scatterlist *sg;
8ff590903   Herbert Xu   crypto: algif_skc...
620
621
622
623
624
  	int err = -EAGAIN;
  	int used;
  	long copied = 0;
  
  	lock_sock(sk);
01e97e651   Al Viro   new helper: msg_d...
625
  	while (msg_data_left(msg)) {
9399f0c51   Linus Torvalds   crypto: fix af_al...
626
  		if (!ctx->used) {
1d10eb2f1   Al Viro   crypto: switch af...
627
628
  			err = skcipher_wait_for_data(sk, flags);
  			if (err)
bc97e57eb   Herbert Xu   crypto: algif_skc...
629
  				goto unlock;
1d10eb2f1   Al Viro   crypto: switch af...
630
  		}
01e97e651   Al Viro   new helper: msg_d...
631
  		used = min_t(unsigned long, ctx->used, msg_data_left(msg));
1d10eb2f1   Al Viro   crypto: switch af...
632
633
634
635
636
  
  		used = af_alg_make_sg(&ctx->rsgl, &msg->msg_iter, used);
  		err = used;
  		if (err < 0)
  			goto unlock;
bc97e57eb   Herbert Xu   crypto: algif_skc...
637

1d10eb2f1   Al Viro   crypto: switch af...
638
639
  		if (ctx->more || used < ctx->used)
  			used -= used % bs;
8ff590903   Herbert Xu   crypto: algif_skc...
640

1d10eb2f1   Al Viro   crypto: switch af...
641
642
643
  		err = -EINVAL;
  		if (!used)
  			goto free;
8ff590903   Herbert Xu   crypto: algif_skc...
644

4f0414e54   Herbert Xu   crypto: algif_skc...
645
646
647
648
649
650
  		sgl = list_first_entry(&ctx->tsgl,
  				       struct skcipher_sg_list, list);
  		sg = sgl->sg;
  
  		while (!sg->length)
  			sg++;
0d96e4bab   Herbert Xu   crypto: algif_skc...
651
652
  		skcipher_request_set_crypt(&ctx->req, sg, ctx->rsgl.sg, used,
  					   ctx->iv);
8ff590903   Herbert Xu   crypto: algif_skc...
653

1d10eb2f1   Al Viro   crypto: switch af...
654
  		err = af_alg_wait_for_completion(
8ff590903   Herbert Xu   crypto: algif_skc...
655
  				ctx->enc ?
0d96e4bab   Herbert Xu   crypto: algif_skc...
656
657
  					crypto_skcipher_encrypt(&ctx->req) :
  					crypto_skcipher_decrypt(&ctx->req),
8ff590903   Herbert Xu   crypto: algif_skc...
658
  				&ctx->completion);
bc97e57eb   Herbert Xu   crypto: algif_skc...
659
  free:
1d10eb2f1   Al Viro   crypto: switch af...
660
  		af_alg_free_sg(&ctx->rsgl);
8ff590903   Herbert Xu   crypto: algif_skc...
661

1d10eb2f1   Al Viro   crypto: switch af...
662
663
  		if (err)
  			goto unlock;
8ff590903   Herbert Xu   crypto: algif_skc...
664

1d10eb2f1   Al Viro   crypto: switch af...
665
  		copied += used;
a596999b7   Tadeusz Struk   crypto: algif - c...
666
  		skcipher_pull_sgl(sk, used, 1);
1d10eb2f1   Al Viro   crypto: switch af...
667
  		iov_iter_advance(&msg->msg_iter, used);
8ff590903   Herbert Xu   crypto: algif_skc...
668
669
670
671
672
673
674
675
676
677
  	}
  
  	err = 0;
  
  unlock:
  	skcipher_wmem_wakeup(sk);
  	release_sock(sk);
  
  	return copied ?: err;
  }
a596999b7   Tadeusz Struk   crypto: algif - c...
678
679
680
681
682
683
684
  static int skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
  			    size_t ignored, int flags)
  {
  	return (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) ?
  		skcipher_recvmsg_async(sock, msg, flags) :
  		skcipher_recvmsg_sync(sock, msg, flags);
  }
8ff590903   Herbert Xu   crypto: algif_skc...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
  
  static unsigned int skcipher_poll(struct file *file, struct socket *sock,
  				  poll_table *wait)
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	unsigned int mask;
  
  	sock_poll_wait(file, sk_sleep(sk), wait);
  	mask = 0;
  
  	if (ctx->used)
  		mask |= POLLIN | POLLRDNORM;
  
  	if (skcipher_writable(sk))
  		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
  
  	return mask;
  }
  
  static struct proto_ops algif_skcipher_ops = {
  	.family		=	PF_ALG,
  
  	.connect	=	sock_no_connect,
  	.socketpair	=	sock_no_socketpair,
  	.getname	=	sock_no_getname,
  	.ioctl		=	sock_no_ioctl,
  	.listen		=	sock_no_listen,
  	.shutdown	=	sock_no_shutdown,
  	.getsockopt	=	sock_no_getsockopt,
  	.mmap		=	sock_no_mmap,
  	.bind		=	sock_no_bind,
  	.accept		=	sock_no_accept,
  	.setsockopt	=	sock_no_setsockopt,
  
  	.release	=	af_alg_release,
  	.sendmsg	=	skcipher_sendmsg,
  	.sendpage	=	skcipher_sendpage,
  	.recvmsg	=	skcipher_recvmsg,
  	.poll		=	skcipher_poll,
  };
a0fa2d037   Herbert Xu   crypto: algif_skc...
727
728
  static int skcipher_check_key(struct socket *sock)
  {
1822793a5   Herbert Xu   crypto: algif_skc...
729
  	int err = 0;
a0fa2d037   Herbert Xu   crypto: algif_skc...
730
731
732
733
734
  	struct sock *psk;
  	struct alg_sock *pask;
  	struct skcipher_tfm *tfm;
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
1822793a5   Herbert Xu   crypto: algif_skc...
735
  	lock_sock(sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
736
  	if (ask->refcnt)
1822793a5   Herbert Xu   crypto: algif_skc...
737
  		goto unlock_child;
a0fa2d037   Herbert Xu   crypto: algif_skc...
738
739
740
741
742
743
  
  	psk = ask->parent;
  	pask = alg_sk(ask->parent);
  	tfm = pask->private;
  
  	err = -ENOKEY;
1822793a5   Herbert Xu   crypto: algif_skc...
744
  	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
a0fa2d037   Herbert Xu   crypto: algif_skc...
745
746
747
748
749
750
751
752
753
754
755
756
757
  	if (!tfm->has_key)
  		goto unlock;
  
  	if (!pask->refcnt++)
  		sock_hold(psk);
  
  	ask->refcnt = 1;
  	sock_put(psk);
  
  	err = 0;
  
  unlock:
  	release_sock(psk);
1822793a5   Herbert Xu   crypto: algif_skc...
758
759
  unlock_child:
  	release_sock(sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  
  	return err;
  }
  
  static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
  				  size_t size)
  {
  	int err;
  
  	err = skcipher_check_key(sock);
  	if (err)
  		return err;
  
  	return skcipher_sendmsg(sock, msg, size);
  }
  
  static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
  				       int offset, size_t size, int flags)
  {
  	int err;
  
  	err = skcipher_check_key(sock);
  	if (err)
  		return err;
  
  	return skcipher_sendpage(sock, page, offset, size, flags);
  }
  
  static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
  				  size_t ignored, int flags)
  {
  	int err;
  
  	err = skcipher_check_key(sock);
  	if (err)
  		return err;
  
  	return skcipher_recvmsg(sock, msg, ignored, flags);
  }
  
  static struct proto_ops algif_skcipher_ops_nokey = {
  	.family		=	PF_ALG,
  
  	.connect	=	sock_no_connect,
  	.socketpair	=	sock_no_socketpair,
  	.getname	=	sock_no_getname,
  	.ioctl		=	sock_no_ioctl,
  	.listen		=	sock_no_listen,
  	.shutdown	=	sock_no_shutdown,
  	.getsockopt	=	sock_no_getsockopt,
  	.mmap		=	sock_no_mmap,
  	.bind		=	sock_no_bind,
  	.accept		=	sock_no_accept,
  	.setsockopt	=	sock_no_setsockopt,
  
  	.release	=	af_alg_release,
  	.sendmsg	=	skcipher_sendmsg_nokey,
  	.sendpage	=	skcipher_sendpage_nokey,
  	.recvmsg	=	skcipher_recvmsg_nokey,
  	.poll		=	skcipher_poll,
  };
8ff590903   Herbert Xu   crypto: algif_skc...
821
822
  static void *skcipher_bind(const char *name, u32 type, u32 mask)
  {
dd5045895   Herbert Xu   crypto: algif_skc...
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
  	struct skcipher_tfm *tfm;
  	struct crypto_skcipher *skcipher;
  
  	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
  	if (!tfm)
  		return ERR_PTR(-ENOMEM);
  
  	skcipher = crypto_alloc_skcipher(name, type, mask);
  	if (IS_ERR(skcipher)) {
  		kfree(tfm);
  		return ERR_CAST(skcipher);
  	}
  
  	tfm->skcipher = skcipher;
  
  	return tfm;
8ff590903   Herbert Xu   crypto: algif_skc...
839
840
841
842
  }
  
  static void skcipher_release(void *private)
  {
dd5045895   Herbert Xu   crypto: algif_skc...
843
844
845
846
  	struct skcipher_tfm *tfm = private;
  
  	crypto_free_skcipher(tfm->skcipher);
  	kfree(tfm);
8ff590903   Herbert Xu   crypto: algif_skc...
847
848
849
850
  }
  
  static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
  {
dd5045895   Herbert Xu   crypto: algif_skc...
851
852
853
854
855
856
857
  	struct skcipher_tfm *tfm = private;
  	int err;
  
  	err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
  	tfm->has_key = !err;
  
  	return err;
8ff590903   Herbert Xu   crypto: algif_skc...
858
  }
a596999b7   Tadeusz Struk   crypto: algif - c...
859
860
861
862
863
864
865
866
867
  static void skcipher_wait(struct sock *sk)
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	int ctr = 0;
  
  	while (atomic_read(&ctx->inflight) && ctr++ < 100)
  		msleep(100);
  }
8ff590903   Herbert Xu   crypto: algif_skc...
868
869
870
871
  static void skcipher_sock_destruct(struct sock *sk)
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
0d96e4bab   Herbert Xu   crypto: algif_skc...
872
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
8ff590903   Herbert Xu   crypto: algif_skc...
873

a596999b7   Tadeusz Struk   crypto: algif - c...
874
875
  	if (atomic_read(&ctx->inflight))
  		skcipher_wait(sk);
8ff590903   Herbert Xu   crypto: algif_skc...
876
  	skcipher_free_sgl(sk);
0d96e4bab   Herbert Xu   crypto: algif_skc...
877
  	sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
8ff590903   Herbert Xu   crypto: algif_skc...
878
879
880
  	sock_kfree_s(sk, ctx, ctx->len);
  	af_alg_release_parent(sk);
  }
d7b65aee1   Herbert Xu   crypto: algif_skc...
881
  static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
8ff590903   Herbert Xu   crypto: algif_skc...
882
883
884
  {
  	struct skcipher_ctx *ctx;
  	struct alg_sock *ask = alg_sk(sk);
dd5045895   Herbert Xu   crypto: algif_skc...
885
886
887
  	struct skcipher_tfm *tfm = private;
  	struct crypto_skcipher *skcipher = tfm->skcipher;
  	unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
8ff590903   Herbert Xu   crypto: algif_skc...
888
889
890
891
  
  	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
  	if (!ctx)
  		return -ENOMEM;
dd5045895   Herbert Xu   crypto: algif_skc...
892
  	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
8ff590903   Herbert Xu   crypto: algif_skc...
893
894
895
896
897
  			       GFP_KERNEL);
  	if (!ctx->iv) {
  		sock_kfree_s(sk, ctx, len);
  		return -ENOMEM;
  	}
dd5045895   Herbert Xu   crypto: algif_skc...
898
  	memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
8ff590903   Herbert Xu   crypto: algif_skc...
899
900
901
902
903
904
905
  
  	INIT_LIST_HEAD(&ctx->tsgl);
  	ctx->len = len;
  	ctx->used = 0;
  	ctx->more = 0;
  	ctx->merge = 0;
  	ctx->enc = 0;
a596999b7   Tadeusz Struk   crypto: algif - c...
906
  	atomic_set(&ctx->inflight, 0);
8ff590903   Herbert Xu   crypto: algif_skc...
907
908
909
  	af_alg_init_completion(&ctx->completion);
  
  	ask->private = ctx;
dd5045895   Herbert Xu   crypto: algif_skc...
910
  	skcipher_request_set_tfm(&ctx->req, skcipher);
dad419970   Herbert Xu   crypto: algif_skc...
911
912
  	skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_SLEEP |
  						 CRYPTO_TFM_REQ_MAY_BACKLOG,
0d96e4bab   Herbert Xu   crypto: algif_skc...
913
  				      af_alg_complete, &ctx->completion);
8ff590903   Herbert Xu   crypto: algif_skc...
914
915
916
917
918
  
  	sk->sk_destruct = skcipher_sock_destruct;
  
  	return 0;
  }
a0fa2d037   Herbert Xu   crypto: algif_skc...
919
920
921
  static int skcipher_accept_parent(void *private, struct sock *sk)
  {
  	struct skcipher_tfm *tfm = private;
6e8d8ecf4   Herbert Xu   crypto: algif_skc...
922
  	if (!tfm->has_key && crypto_skcipher_has_setkey(tfm->skcipher))
a0fa2d037   Herbert Xu   crypto: algif_skc...
923
  		return -ENOKEY;
d7b65aee1   Herbert Xu   crypto: algif_skc...
924
  	return skcipher_accept_parent_nokey(private, sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
925
  }
8ff590903   Herbert Xu   crypto: algif_skc...
926
927
928
929
930
  static const struct af_alg_type algif_type_skcipher = {
  	.bind		=	skcipher_bind,
  	.release	=	skcipher_release,
  	.setkey		=	skcipher_setkey,
  	.accept		=	skcipher_accept_parent,
a0fa2d037   Herbert Xu   crypto: algif_skc...
931
  	.accept_nokey	=	skcipher_accept_parent_nokey,
8ff590903   Herbert Xu   crypto: algif_skc...
932
  	.ops		=	&algif_skcipher_ops,
a0fa2d037   Herbert Xu   crypto: algif_skc...
933
  	.ops_nokey	=	&algif_skcipher_ops_nokey,
8ff590903   Herbert Xu   crypto: algif_skc...
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
  	.name		=	"skcipher",
  	.owner		=	THIS_MODULE
  };
  
  static int __init algif_skcipher_init(void)
  {
  	return af_alg_register_type(&algif_type_skcipher);
  }
  
  static void __exit algif_skcipher_exit(void)
  {
  	int err = af_alg_unregister_type(&algif_type_skcipher);
  	BUG_ON(err);
  }
  
  module_init(algif_skcipher_init);
  module_exit(algif_skcipher_exit);
  MODULE_LICENSE("GPL");