Blame view

crypto/algif_skcipher.c 9.75 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;
d7835f2b8   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

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

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

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

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

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