Blame view

crypto/algif_skcipher.c 21 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
21
22
23
24
25
26
27
28
29
30
31
32
  /*
   * 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>
  #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...
33
34
35
36
  struct skcipher_tfm {
  	struct crypto_skcipher *skcipher;
  	bool has_key;
  };
8ff590903   Herbert Xu   crypto: algif_skc...
37
38
39
40
41
42
43
  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...
44
  	atomic_t inflight;
652d5b8a8   LABBE Corentin   crypto: algif - C...
45
  	size_t used;
8ff590903   Herbert Xu   crypto: algif_skc...
46
47
48
49
50
  
  	unsigned int len;
  	bool more;
  	bool merge;
  	bool enc;
0d96e4bab   Herbert Xu   crypto: algif_skc...
51
  	struct skcipher_request req;
8ff590903   Herbert Xu   crypto: algif_skc...
52
  };
a596999b7   Tadeusz Struk   crypto: algif - c...
53
54
55
56
57
58
59
60
61
62
  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...
63
64
  	atomic_t *inflight;
  	struct skcipher_request req;
a596999b7   Tadeusz Struk   crypto: algif - c...
65
  };
e2cffb5f4   Ondrej Kozina   crypto: algif - a...
66
  #define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
8ff590903   Herbert Xu   crypto: algif_skc...
67
  		      sizeof(struct scatterlist) - 1)
a596999b7   Tadeusz Struk   crypto: algif - c...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  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...
90
  	struct skcipher_async_req *sreq = req->data;
a596999b7   Tadeusz Struk   crypto: algif - c...
91
  	struct kiocb *iocb = sreq->iocb;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
92
  	atomic_dec(sreq->inflight);
a596999b7   Tadeusz Struk   crypto: algif - c...
93
  	skcipher_free_async_sgls(sreq);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
94
  	kzfree(sreq);
237dae889   Al Viro   Merge branch 'ioc...
95
  	iocb->ki_complete(iocb, err, err);
a596999b7   Tadeusz Struk   crypto: algif - c...
96
  }
0f6bb83cb   Herbert Xu   crypto: algif_skc...
97
  static inline int skcipher_sndbuf(struct sock *sk)
8ff590903   Herbert Xu   crypto: algif_skc...
98
99
100
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
0f6bb83cb   Herbert Xu   crypto: algif_skc...
101
102
103
104
105
106
107
  	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...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  }
  
  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...
132
  			sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
8ff590903   Herbert Xu   crypto: algif_skc...
133
134
135
136
137
138
  
  		list_add_tail(&sgl->list, &ctx->tsgl);
  	}
  
  	return 0;
  }
652d5b8a8   LABBE Corentin   crypto: algif - C...
139
  static void skcipher_pull_sgl(struct sock *sk, size_t used, int put)
8ff590903   Herbert Xu   crypto: algif_skc...
140
141
142
143
144
145
146
147
148
149
150
151
152
  {
  	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...
153
  			size_t plen = min_t(size_t, used, sg[i].length);
8ff590903   Herbert Xu   crypto: algif_skc...
154
155
156
157
158
159
160
161
162
163
164
165
  
  			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...
166
167
  			if (put)
  				put_page(sg_page(sg + i));
8ff590903   Herbert Xu   crypto: algif_skc...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  			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...
185
  	skcipher_pull_sgl(sk, ctx->used, 1);
8ff590903   Herbert Xu   crypto: algif_skc...
186
187
188
189
190
191
192
193
194
195
  }
  
  static int skcipher_wait_for_wmem(struct sock *sk, unsigned flags)
  {
  	long timeout;
  	DEFINE_WAIT(wait);
  	int err = -ERESTARTSYS;
  
  	if (flags & MSG_DONTWAIT)
  		return -EAGAIN;
9cd3e072b   Eric Dumazet   net: rename SOCK_...
196
  	sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
8ff590903   Herbert Xu   crypto: algif_skc...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  
  	for (;;) {
  		if (signal_pending(current))
  			break;
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  		timeout = MAX_SCHEDULE_TIMEOUT;
  		if (sk_wait_event(sk, &timeout, skcipher_writable(sk))) {
  			err = 0;
  			break;
  		}
  	}
  	finish_wait(sk_sleep(sk), &wait);
  
  	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...
222
  	if (skwq_has_sleeper(wq))
8ff590903   Herbert Xu   crypto: algif_skc...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  		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)
  {
  	struct alg_sock *ask = alg_sk(sk);
  	struct skcipher_ctx *ctx = ask->private;
  	long timeout;
  	DEFINE_WAIT(wait);
  	int err = -ERESTARTSYS;
  
  	if (flags & MSG_DONTWAIT) {
  		return -EAGAIN;
  	}
9cd3e072b   Eric Dumazet   net: rename SOCK_...
241
  	sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
8ff590903   Herbert Xu   crypto: algif_skc...
242
243
244
245
246
247
248
249
250
251
252
253
  
  	for (;;) {
  		if (signal_pending(current))
  			break;
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  		timeout = MAX_SCHEDULE_TIMEOUT;
  		if (sk_wait_event(sk, &timeout, ctx->used)) {
  			err = 0;
  			break;
  		}
  	}
  	finish_wait(sk_sleep(sk), &wait);
9cd3e072b   Eric Dumazet   net: rename SOCK_...
254
  	sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
8ff590903   Herbert Xu   crypto: algif_skc...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  
  	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...
270
  	if (skwq_has_sleeper(wq))
8ff590903   Herbert Xu   crypto: algif_skc...
271
272
273
274
275
276
  		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 ...
277
278
  static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
  			    size_t size)
8ff590903   Herbert Xu   crypto: algif_skc...
279
280
281
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
6454c2b83   Herbert Xu   crypto: algif_skc...
282
283
  	struct sock *psk = ask->parent;
  	struct alg_sock *pask = alg_sk(psk);
8ff590903   Herbert Xu   crypto: algif_skc...
284
  	struct skcipher_ctx *ctx = ask->private;
6454c2b83   Herbert Xu   crypto: algif_skc...
285
286
  	struct skcipher_tfm *skc = pask->private;
  	struct crypto_skcipher *tfm = skc->skcipher;
0d96e4bab   Herbert Xu   crypto: algif_skc...
287
  	unsigned ivsize = crypto_skcipher_ivsize(tfm);
8ff590903   Herbert Xu   crypto: algif_skc...
288
289
290
291
  	struct skcipher_sg_list *sgl;
  	struct af_alg_control con = {};
  	long copied = 0;
  	bool enc = 0;
f26b7b805   Stephan Mueller   crypto: algif_skc...
292
  	bool init = 0;
8ff590903   Herbert Xu   crypto: algif_skc...
293
294
295
296
297
298
299
  	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...
300
  		init = 1;
8ff590903   Herbert Xu   crypto: algif_skc...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  		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...
321
  	if (init) {
8ff590903   Herbert Xu   crypto: algif_skc...
322
323
324
325
  		ctx->enc = enc;
  		if (con.iv)
  			memcpy(ctx->iv, con.iv->iv, ivsize);
  	}
8ff590903   Herbert Xu   crypto: algif_skc...
326
327
328
  	while (size) {
  		struct scatterlist *sg;
  		unsigned long len = size;
652d5b8a8   LABBE Corentin   crypto: algif - C...
329
  		size_t plen;
8ff590903   Herbert Xu   crypto: algif_skc...
330
331
332
333
334
335
336
  
  		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...
337
338
339
  			err = memcpy_from_msg(page_address(sg_page(sg)) +
  					      sg->offset + sg->length,
  					      msg, len);
8ff590903   Herbert Xu   crypto: algif_skc...
340
341
342
343
344
345
346
347
348
349
  			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...
350
351
  			continue;
  		}
0f6bb83cb   Herbert Xu   crypto: algif_skc...
352
  		if (!skcipher_writable(sk)) {
8ff590903   Herbert Xu   crypto: algif_skc...
353
354
355
  			err = skcipher_wait_for_wmem(sk, msg->msg_flags);
  			if (err)
  				goto unlock;
8ff590903   Herbert Xu   crypto: algif_skc...
356
  		}
0f6bb83cb   Herbert Xu   crypto: algif_skc...
357
  		len = min_t(unsigned long, len, skcipher_sndbuf(sk));
8ff590903   Herbert Xu   crypto: algif_skc...
358
359
360
361
362
363
364
  
  		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...
365
366
  		if (sgl->cur)
  			sg_unmark_end(sg + sgl->cur - 1);
8ff590903   Herbert Xu   crypto: algif_skc...
367
368
  		do {
  			i = sgl->cur;
652d5b8a8   LABBE Corentin   crypto: algif - C...
369
  			plen = min_t(size_t, len, PAGE_SIZE);
8ff590903   Herbert Xu   crypto: algif_skc...
370
371
372
373
374
  
  			sg_assign_page(sg + i, alloc_page(GFP_KERNEL));
  			err = -ENOMEM;
  			if (!sg_page(sg + i))
  				goto unlock;
6ce8e9ce5   Al Viro   new helper: memcp...
375
376
  			err = memcpy_from_msg(page_address(sg_page(sg + i)),
  					      msg, plen);
8ff590903   Herbert Xu   crypto: algif_skc...
377
378
379
380
381
382
383
384
385
386
387
  			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...
388
389
  			sgl->cur++;
  		} while (len && sgl->cur < MAX_SGL_ENTS);
0f477b655   Tadeusz Struk   crypto: algif - M...
390
391
  		if (!size)
  			sg_mark_end(sg + sgl->cur - 1);
8ff590903   Herbert Xu   crypto: algif_skc...
392
393
394
395
396
397
  		ctx->merge = plen & (PAGE_SIZE - 1);
  	}
  
  	err = 0;
  
  	ctx->more = msg->msg_flags & MSG_MORE;
8ff590903   Herbert Xu   crypto: algif_skc...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  
  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...
414

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

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

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

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

1d10eb2f1   Al Viro   crypto: switch af...
637
638
639
  		err = -EINVAL;
  		if (!used)
  			goto free;
8ff590903   Herbert Xu   crypto: algif_skc...
640

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

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

1d10eb2f1   Al Viro   crypto: switch af...
658
659
  		if (err)
  			goto unlock;
8ff590903   Herbert Xu   crypto: algif_skc...
660

1d10eb2f1   Al Viro   crypto: switch af...
661
  		copied += used;
a596999b7   Tadeusz Struk   crypto: algif - c...
662
  		skcipher_pull_sgl(sk, used, 1);
1d10eb2f1   Al Viro   crypto: switch af...
663
  		iov_iter_advance(&msg->msg_iter, used);
8ff590903   Herbert Xu   crypto: algif_skc...
664
665
666
667
668
669
670
671
672
673
  	}
  
  	err = 0;
  
  unlock:
  	skcipher_wmem_wakeup(sk);
  	release_sock(sk);
  
  	return copied ?: err;
  }
a596999b7   Tadeusz Struk   crypto: algif - c...
674
675
676
677
678
679
680
  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...
681
682
683
684
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
  
  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...
723
724
  static int skcipher_check_key(struct socket *sock)
  {
1822793a5   Herbert Xu   crypto: algif_skc...
725
  	int err = 0;
a0fa2d037   Herbert Xu   crypto: algif_skc...
726
727
728
729
730
  	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...
731
  	lock_sock(sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
732
  	if (ask->refcnt)
1822793a5   Herbert Xu   crypto: algif_skc...
733
  		goto unlock_child;
a0fa2d037   Herbert Xu   crypto: algif_skc...
734
735
736
737
738
739
  
  	psk = ask->parent;
  	pask = alg_sk(ask->parent);
  	tfm = pask->private;
  
  	err = -ENOKEY;
1822793a5   Herbert Xu   crypto: algif_skc...
740
  	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
a0fa2d037   Herbert Xu   crypto: algif_skc...
741
742
743
744
745
746
747
748
749
750
751
752
753
  	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...
754
755
  unlock_child:
  	release_sock(sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
756
757
758
759
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
  
  	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...
817
818
  static void *skcipher_bind(const char *name, u32 type, u32 mask)
  {
dd5045895   Herbert Xu   crypto: algif_skc...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
  	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...
835
836
837
838
  }
  
  static void skcipher_release(void *private)
  {
dd5045895   Herbert Xu   crypto: algif_skc...
839
840
841
842
  	struct skcipher_tfm *tfm = private;
  
  	crypto_free_skcipher(tfm->skcipher);
  	kfree(tfm);
8ff590903   Herbert Xu   crypto: algif_skc...
843
844
845
846
  }
  
  static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
  {
dd5045895   Herbert Xu   crypto: algif_skc...
847
848
849
850
851
852
853
  	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...
854
  }
a596999b7   Tadeusz Struk   crypto: algif - c...
855
856
857
858
859
860
861
862
863
  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...
864
865
866
867
  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...
868
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
8ff590903   Herbert Xu   crypto: algif_skc...
869

a596999b7   Tadeusz Struk   crypto: algif - c...
870
871
  	if (atomic_read(&ctx->inflight))
  		skcipher_wait(sk);
8ff590903   Herbert Xu   crypto: algif_skc...
872
  	skcipher_free_sgl(sk);
0d96e4bab   Herbert Xu   crypto: algif_skc...
873
  	sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
8ff590903   Herbert Xu   crypto: algif_skc...
874
875
876
  	sock_kfree_s(sk, ctx, ctx->len);
  	af_alg_release_parent(sk);
  }
d7b65aee1   Herbert Xu   crypto: algif_skc...
877
  static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
8ff590903   Herbert Xu   crypto: algif_skc...
878
879
880
  {
  	struct skcipher_ctx *ctx;
  	struct alg_sock *ask = alg_sk(sk);
dd5045895   Herbert Xu   crypto: algif_skc...
881
882
883
  	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...
884
885
886
887
  
  	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
  	if (!ctx)
  		return -ENOMEM;
dd5045895   Herbert Xu   crypto: algif_skc...
888
  	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
8ff590903   Herbert Xu   crypto: algif_skc...
889
890
891
892
893
  			       GFP_KERNEL);
  	if (!ctx->iv) {
  		sock_kfree_s(sk, ctx, len);
  		return -ENOMEM;
  	}
dd5045895   Herbert Xu   crypto: algif_skc...
894
  	memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
8ff590903   Herbert Xu   crypto: algif_skc...
895
896
897
898
899
900
901
  
  	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...
902
  	atomic_set(&ctx->inflight, 0);
8ff590903   Herbert Xu   crypto: algif_skc...
903
904
905
  	af_alg_init_completion(&ctx->completion);
  
  	ask->private = ctx;
dd5045895   Herbert Xu   crypto: algif_skc...
906
  	skcipher_request_set_tfm(&ctx->req, skcipher);
dad419970   Herbert Xu   crypto: algif_skc...
907
908
  	skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_SLEEP |
  						 CRYPTO_TFM_REQ_MAY_BACKLOG,
0d96e4bab   Herbert Xu   crypto: algif_skc...
909
  				      af_alg_complete, &ctx->completion);
8ff590903   Herbert Xu   crypto: algif_skc...
910
911
912
913
914
  
  	sk->sk_destruct = skcipher_sock_destruct;
  
  	return 0;
  }
a0fa2d037   Herbert Xu   crypto: algif_skc...
915
916
917
  static int skcipher_accept_parent(void *private, struct sock *sk)
  {
  	struct skcipher_tfm *tfm = private;
6e8d8ecf4   Herbert Xu   crypto: algif_skc...
918
  	if (!tfm->has_key && crypto_skcipher_has_setkey(tfm->skcipher))
a0fa2d037   Herbert Xu   crypto: algif_skc...
919
  		return -ENOKEY;
d7b65aee1   Herbert Xu   crypto: algif_skc...
920
  	return skcipher_accept_parent_nokey(private, sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
921
  }
8ff590903   Herbert Xu   crypto: algif_skc...
922
923
924
925
926
  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...
927
  	.accept_nokey	=	skcipher_accept_parent_nokey,
8ff590903   Herbert Xu   crypto: algif_skc...
928
  	.ops		=	&algif_skcipher_ops,
a0fa2d037   Herbert Xu   crypto: algif_skc...
929
  	.ops_nokey	=	&algif_skcipher_ops_nokey,
8ff590903   Herbert Xu   crypto: algif_skc...
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
  	.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");