Blame view

crypto/algif_skcipher.c 9.6 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
8ff590903   Herbert Xu   crypto: algif_skc...
2
3
4
5
6
7
8
  /*
   * 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>
   *
e870456d8   Stephan Mueller   crypto: algif_skc...
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   * The following concept of the memory management is used:
   *
   * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is
   * filled by user space with the data submitted via sendpage/sendmsg. Filling
   * up the TX SGL does not cause a crypto operation -- the data will only be
   * tracked by the kernel. Upon receipt of one recvmsg call, the caller must
   * provide a buffer which is tracked with the RX SGL.
   *
   * During the processing of the recvmsg operation, the cipher request is
   * allocated and prepared. As part of the recvmsg operation, the processed
   * TX buffers are extracted from the TX SGL into a separate SGL.
   *
   * After the completion of the crypto operation, the RX SGL and the cipher
   * request is released. The extracted TX SGL parts are released together with
   * the RX SGL release.
8ff590903   Herbert Xu   crypto: algif_skc...
24
25
26
27
28
29
30
31
32
33
34
35
   */
  
  #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>
1b7841404   Ying Xue   net: Remove iocb ...
36
37
  static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
  			    size_t size)
8ff590903   Herbert Xu   crypto: algif_skc...
38
39
40
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
6454c2b83   Herbert Xu   crypto: algif_skc...
41
42
  	struct sock *psk = ask->parent;
  	struct alg_sock *pask = alg_sk(psk);
f8d33fac8   Eric Biggers   crypto: skcipher ...
43
  	struct crypto_skcipher *tfm = pask->private;
0d96e4bab   Herbert Xu   crypto: algif_skc...
44
  	unsigned ivsize = crypto_skcipher_ivsize(tfm);
8ff590903   Herbert Xu   crypto: algif_skc...
45

2d97591ef   Stephan Mueller   crypto: af_alg - ...
46
  	return af_alg_sendmsg(sock, msg, size, ivsize);
a596999b7   Tadeusz Struk   crypto: algif - c...
47
  }
e870456d8   Stephan Mueller   crypto: algif_skc...
48
49
  static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
  			     size_t ignored, int flags)
a596999b7   Tadeusz Struk   crypto: algif - c...
50
51
52
  {
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
ec69bbfb9   Herbert Xu   crypto: algif_skc...
53
54
  	struct sock *psk = ask->parent;
  	struct alg_sock *pask = alg_sk(psk);
2d97591ef   Stephan Mueller   crypto: af_alg - ...
55
  	struct af_alg_ctx *ctx = ask->private;
f8d33fac8   Eric Biggers   crypto: skcipher ...
56
  	struct crypto_skcipher *tfm = pask->private;
5b0fe9552   Herbert Xu   crypto: algif_skc...
57
  	unsigned int bs = crypto_skcipher_chunksize(tfm);
2d97591ef   Stephan Mueller   crypto: af_alg - ...
58
  	struct af_alg_async_req *areq;
e870456d8   Stephan Mueller   crypto: algif_skc...
59
60
  	int err = 0;
  	size_t len = 0;
ec69bbfb9   Herbert Xu   crypto: algif_skc...
61

f3c802a1f   Herbert Xu   crypto: algif_aea...
62
63
  	if (!ctx->init || (ctx->more && ctx->used < bs)) {
  		err = af_alg_wait_for_data(sk, flags, bs);
11edb5559   Stephan Mueller   crypto: af_alg - ...
64
65
66
  		if (err)
  			return err;
  	}
e870456d8   Stephan Mueller   crypto: algif_skc...
67
  	/* Allocate cipher request for current operation. */
2d97591ef   Stephan Mueller   crypto: af_alg - ...
68
69
70
71
  	areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
  				     crypto_skcipher_reqsize(tfm));
  	if (IS_ERR(areq))
  		return PTR_ERR(areq);
a596999b7   Tadeusz Struk   crypto: algif - c...
72

e870456d8   Stephan Mueller   crypto: algif_skc...
73
  	/* convert iovecs of output buffers into RX SGL */
7cf819547   Herbert Xu   crypto: algif_skc...
74
  	err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len);
2d97591ef   Stephan Mueller   crypto: af_alg - ...
75
76
  	if (err)
  		goto free;
a596999b7   Tadeusz Struk   crypto: algif - c...
77

e870456d8   Stephan Mueller   crypto: algif_skc...
78
79
80
81
82
83
84
85
86
87
88
  	/*
  	 * If more buffers are to be expected to be processed, process only
  	 * full block size buffers.
  	 */
  	if (ctx->more || len < ctx->used)
  		len -= len % bs;
  
  	/*
  	 * Create a per request TX SGL for this request which tracks the
  	 * SG entries from the global TX SGL.
  	 */
2d97591ef   Stephan Mueller   crypto: af_alg - ...
89
  	areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
e870456d8   Stephan Mueller   crypto: algif_skc...
90
91
  	if (!areq->tsgl_entries)
  		areq->tsgl_entries = 1;
76e43e37a   Kees Cook   treewide: Use arr...
92
93
  	areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
  						 areq->tsgl_entries),
e870456d8   Stephan Mueller   crypto: algif_skc...
94
95
96
97
98
99
  				  GFP_KERNEL);
  	if (!areq->tsgl) {
  		err = -ENOMEM;
  		goto free;
  	}
  	sg_init_table(areq->tsgl, areq->tsgl_entries);
2d97591ef   Stephan Mueller   crypto: af_alg - ...
100
  	af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
e870456d8   Stephan Mueller   crypto: algif_skc...
101
102
  
  	/* Initialize the crypto operation */
2d97591ef   Stephan Mueller   crypto: af_alg - ...
103
104
105
  	skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
  	skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
  				   areq->first_rsgl.sgl.sg, len, ctx->iv);
e870456d8   Stephan Mueller   crypto: algif_skc...
106
107
108
  
  	if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
  		/* AIO operation */
7d2c3f54e   Stephan Mueller   crypto: af_alg - ...
109
  		sock_hold(sk);
e870456d8   Stephan Mueller   crypto: algif_skc...
110
  		areq->iocb = msg->msg_iocb;
d53c51357   Stephan Mueller   crypto: af_alg - ...
111
112
113
  
  		/* Remember output size that will be generated. */
  		areq->outlen = len;
2d97591ef   Stephan Mueller   crypto: af_alg - ...
114
  		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
e870456d8   Stephan Mueller   crypto: algif_skc...
115
  					      CRYPTO_TFM_REQ_MAY_SLEEP,
2d97591ef   Stephan Mueller   crypto: af_alg - ...
116
117
118
119
  					      af_alg_async_cb, areq);
  		err = ctx->enc ?
  			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
  			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
7d2c3f54e   Stephan Mueller   crypto: af_alg - ...
120
121
  
  		/* AIO operation in progress */
2a05b029c   Herbert Xu   crypto: algif_skc...
122
  		if (err == -EINPROGRESS)
7d2c3f54e   Stephan Mueller   crypto: af_alg - ...
123
  			return -EIOCBQUEUED;
7d2c3f54e   Stephan Mueller   crypto: af_alg - ...
124
125
  
  		sock_put(sk);
e870456d8   Stephan Mueller   crypto: algif_skc...
126
127
  	} else {
  		/* Synchronous operation */
2d97591ef   Stephan Mueller   crypto: af_alg - ...
128
  		skcipher_request_set_callback(&areq->cra_u.skcipher_req,
e870456d8   Stephan Mueller   crypto: algif_skc...
129
130
  					      CRYPTO_TFM_REQ_MAY_SLEEP |
  					      CRYPTO_TFM_REQ_MAY_BACKLOG,
2c3f8b162   Gilad Ben-Yossef   crypto: algif - m...
131
132
  					      crypto_req_done, &ctx->wait);
  		err = crypto_wait_req(ctx->enc ?
2d97591ef   Stephan Mueller   crypto: af_alg - ...
133
134
  			crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
  			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
2c3f8b162   Gilad Ben-Yossef   crypto: algif - m...
135
  						 &ctx->wait);
e870456d8   Stephan Mueller   crypto: algif_skc...
136
  	}
033f46b3c   tadeusz.struk@intel.com   crypto: algif - e...
137

e870456d8   Stephan Mueller   crypto: algif_skc...
138

a596999b7   Tadeusz Struk   crypto: algif - c...
139
  free:
7d2c3f54e   Stephan Mueller   crypto: af_alg - ...
140
  	af_alg_free_resources(areq);
e870456d8   Stephan Mueller   crypto: algif_skc...
141
142
  
  	return err ? err : len;
a596999b7   Tadeusz Struk   crypto: algif - c...
143
  }
e870456d8   Stephan Mueller   crypto: algif_skc...
144
145
  static int skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
  			    size_t ignored, int flags)
8ff590903   Herbert Xu   crypto: algif_skc...
146
147
  {
  	struct sock *sk = sock->sk;
e870456d8   Stephan Mueller   crypto: algif_skc...
148
  	int ret = 0;
8ff590903   Herbert Xu   crypto: algif_skc...
149
150
  
  	lock_sock(sk);
01e97e651   Al Viro   new helper: msg_d...
151
  	while (msg_data_left(msg)) {
e870456d8   Stephan Mueller   crypto: algif_skc...
152
153
154
155
156
157
158
  		int err = _skcipher_recvmsg(sock, msg, ignored, flags);
  
  		/*
  		 * This error covers -EIOCBQUEUED which implies that we can
  		 * only handle one AIO request. If the caller wants to have
  		 * multiple AIO requests in parallel, he must make multiple
  		 * separate AIO calls.
5703c826b   Stephan Mueller   crypto: algif - r...
159
160
  		 *
  		 * Also return the error if no data has been processed so far.
e870456d8   Stephan Mueller   crypto: algif_skc...
161
162
  		 */
  		if (err <= 0) {
5703c826b   Stephan Mueller   crypto: algif - r...
163
  			if (err == -EIOCBQUEUED || !ret)
e870456d8   Stephan Mueller   crypto: algif_skc...
164
165
  				ret = err;
  			goto out;
1d10eb2f1   Al Viro   crypto: switch af...
166
  		}
e870456d8   Stephan Mueller   crypto: algif_skc...
167
  		ret += err;
8ff590903   Herbert Xu   crypto: algif_skc...
168
  	}
e870456d8   Stephan Mueller   crypto: algif_skc...
169
  out:
2d97591ef   Stephan Mueller   crypto: af_alg - ...
170
  	af_alg_wmem_wakeup(sk);
8ff590903   Herbert Xu   crypto: algif_skc...
171
  	release_sock(sk);
e870456d8   Stephan Mueller   crypto: algif_skc...
172
  	return ret;
a596999b7   Tadeusz Struk   crypto: algif - c...
173
  }
8ff590903   Herbert Xu   crypto: algif_skc...
174

8ff590903   Herbert Xu   crypto: algif_skc...
175
176
177
178
179
180
181
182
183
  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,
8ff590903   Herbert Xu   crypto: algif_skc...
184
185
186
  	.mmap		=	sock_no_mmap,
  	.bind		=	sock_no_bind,
  	.accept		=	sock_no_accept,
8ff590903   Herbert Xu   crypto: algif_skc...
187
188
189
  
  	.release	=	af_alg_release,
  	.sendmsg	=	skcipher_sendmsg,
2d97591ef   Stephan Mueller   crypto: af_alg - ...
190
  	.sendpage	=	af_alg_sendpage,
8ff590903   Herbert Xu   crypto: algif_skc...
191
  	.recvmsg	=	skcipher_recvmsg,
a11e1d432   Linus Torvalds   Revert changes to...
192
  	.poll		=	af_alg_poll,
8ff590903   Herbert Xu   crypto: algif_skc...
193
  };
a0fa2d037   Herbert Xu   crypto: algif_skc...
194
195
  static int skcipher_check_key(struct socket *sock)
  {
1822793a5   Herbert Xu   crypto: algif_skc...
196
  	int err = 0;
a0fa2d037   Herbert Xu   crypto: algif_skc...
197
198
  	struct sock *psk;
  	struct alg_sock *pask;
f8d33fac8   Eric Biggers   crypto: skcipher ...
199
  	struct crypto_skcipher *tfm;
a0fa2d037   Herbert Xu   crypto: algif_skc...
200
201
  	struct sock *sk = sock->sk;
  	struct alg_sock *ask = alg_sk(sk);
1822793a5   Herbert Xu   crypto: algif_skc...
202
  	lock_sock(sk);
34c86f4c4   Herbert Xu   crypto: af_alg - ...
203
  	if (!atomic_read(&ask->nokey_refcnt))
1822793a5   Herbert Xu   crypto: algif_skc...
204
  		goto unlock_child;
a0fa2d037   Herbert Xu   crypto: algif_skc...
205
206
207
208
209
210
  
  	psk = ask->parent;
  	pask = alg_sk(ask->parent);
  	tfm = pask->private;
  
  	err = -ENOKEY;
1822793a5   Herbert Xu   crypto: algif_skc...
211
  	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
f8d33fac8   Eric Biggers   crypto: skcipher ...
212
  	if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
a0fa2d037   Herbert Xu   crypto: algif_skc...
213
  		goto unlock;
34c86f4c4   Herbert Xu   crypto: af_alg - ...
214
215
  	atomic_dec(&pask->nokey_refcnt);
  	atomic_set(&ask->nokey_refcnt, 0);
a0fa2d037   Herbert Xu   crypto: algif_skc...
216
217
218
219
220
  
  	err = 0;
  
  unlock:
  	release_sock(psk);
1822793a5   Herbert Xu   crypto: algif_skc...
221
222
  unlock_child:
  	release_sock(sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  
  	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;
2d97591ef   Stephan Mueller   crypto: af_alg - ...
247
  	return af_alg_sendpage(sock, page, offset, size, flags);
a0fa2d037   Herbert Xu   crypto: algif_skc...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  }
  
  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,
a0fa2d037   Herbert Xu   crypto: algif_skc...
271
272
273
  	.mmap		=	sock_no_mmap,
  	.bind		=	sock_no_bind,
  	.accept		=	sock_no_accept,
a0fa2d037   Herbert Xu   crypto: algif_skc...
274
275
276
277
278
  
  	.release	=	af_alg_release,
  	.sendmsg	=	skcipher_sendmsg_nokey,
  	.sendpage	=	skcipher_sendpage_nokey,
  	.recvmsg	=	skcipher_recvmsg_nokey,
a11e1d432   Linus Torvalds   Revert changes to...
279
  	.poll		=	af_alg_poll,
a0fa2d037   Herbert Xu   crypto: algif_skc...
280
  };
8ff590903   Herbert Xu   crypto: algif_skc...
281
282
  static void *skcipher_bind(const char *name, u32 type, u32 mask)
  {
f8d33fac8   Eric Biggers   crypto: skcipher ...
283
  	return crypto_alloc_skcipher(name, type, mask);
8ff590903   Herbert Xu   crypto: algif_skc...
284
285
286
287
  }
  
  static void skcipher_release(void *private)
  {
f8d33fac8   Eric Biggers   crypto: skcipher ...
288
  	crypto_free_skcipher(private);
8ff590903   Herbert Xu   crypto: algif_skc...
289
290
291
292
  }
  
  static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
  {
f8d33fac8   Eric Biggers   crypto: skcipher ...
293
  	return crypto_skcipher_setkey(private, key, keylen);
8ff590903   Herbert Xu   crypto: algif_skc...
294
295
296
297
298
  }
  
  static void skcipher_sock_destruct(struct sock *sk)
  {
  	struct alg_sock *ask = alg_sk(sk);
2d97591ef   Stephan Mueller   crypto: af_alg - ...
299
  	struct af_alg_ctx *ctx = ask->private;
e870456d8   Stephan Mueller   crypto: algif_skc...
300
301
  	struct sock *psk = ask->parent;
  	struct alg_sock *pask = alg_sk(psk);
f8d33fac8   Eric Biggers   crypto: skcipher ...
302
  	struct crypto_skcipher *tfm = pask->private;
a596999b7   Tadeusz Struk   crypto: algif - c...
303

2d97591ef   Stephan Mueller   crypto: af_alg - ...
304
  	af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
0d96e4bab   Herbert Xu   crypto: algif_skc...
305
  	sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
8ff590903   Herbert Xu   crypto: algif_skc...
306
307
308
  	sock_kfree_s(sk, ctx, ctx->len);
  	af_alg_release_parent(sk);
  }
d7b65aee1   Herbert Xu   crypto: algif_skc...
309
  static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
8ff590903   Herbert Xu   crypto: algif_skc...
310
  {
2d97591ef   Stephan Mueller   crypto: af_alg - ...
311
  	struct af_alg_ctx *ctx;
8ff590903   Herbert Xu   crypto: algif_skc...
312
  	struct alg_sock *ask = alg_sk(sk);
f8d33fac8   Eric Biggers   crypto: skcipher ...
313
  	struct crypto_skcipher *tfm = private;
e870456d8   Stephan Mueller   crypto: algif_skc...
314
  	unsigned int len = sizeof(*ctx);
8ff590903   Herbert Xu   crypto: algif_skc...
315
316
317
318
  
  	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
  	if (!ctx)
  		return -ENOMEM;
21dfbcd1f   Ondrej Mosnacek   crypto: algif_aea...
319
  	memset(ctx, 0, len);
8ff590903   Herbert Xu   crypto: algif_skc...
320

f8d33fac8   Eric Biggers   crypto: skcipher ...
321
  	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(tfm),
8ff590903   Herbert Xu   crypto: algif_skc...
322
323
324
325
326
  			       GFP_KERNEL);
  	if (!ctx->iv) {
  		sock_kfree_s(sk, ctx, len);
  		return -ENOMEM;
  	}
f8d33fac8   Eric Biggers   crypto: skcipher ...
327
  	memset(ctx->iv, 0, crypto_skcipher_ivsize(tfm));
8ff590903   Herbert Xu   crypto: algif_skc...
328

e870456d8   Stephan Mueller   crypto: algif_skc...
329
  	INIT_LIST_HEAD(&ctx->tsgl_list);
8ff590903   Herbert Xu   crypto: algif_skc...
330
  	ctx->len = len;
2c3f8b162   Gilad Ben-Yossef   crypto: algif - m...
331
  	crypto_init_wait(&ctx->wait);
8ff590903   Herbert Xu   crypto: algif_skc...
332
333
  
  	ask->private = ctx;
8ff590903   Herbert Xu   crypto: algif_skc...
334
335
336
337
  	sk->sk_destruct = skcipher_sock_destruct;
  
  	return 0;
  }
a0fa2d037   Herbert Xu   crypto: algif_skc...
338
339
  static int skcipher_accept_parent(void *private, struct sock *sk)
  {
f8d33fac8   Eric Biggers   crypto: skcipher ...
340
  	struct crypto_skcipher *tfm = private;
a0fa2d037   Herbert Xu   crypto: algif_skc...
341

f8d33fac8   Eric Biggers   crypto: skcipher ...
342
  	if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
a0fa2d037   Herbert Xu   crypto: algif_skc...
343
  		return -ENOKEY;
d7b65aee1   Herbert Xu   crypto: algif_skc...
344
  	return skcipher_accept_parent_nokey(private, sk);
a0fa2d037   Herbert Xu   crypto: algif_skc...
345
  }
8ff590903   Herbert Xu   crypto: algif_skc...
346
347
348
349
350
  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...
351
  	.accept_nokey	=	skcipher_accept_parent_nokey,
8ff590903   Herbert Xu   crypto: algif_skc...
352
  	.ops		=	&algif_skcipher_ops,
a0fa2d037   Herbert Xu   crypto: algif_skc...
353
  	.ops_nokey	=	&algif_skcipher_ops_nokey,
8ff590903   Herbert Xu   crypto: algif_skc...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  	.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");