crypto: af_alg - Add nokey compatibility path
[pandora-kernel.git] / crypto / af_alg.c
1 /*
2  * af_alg: User-space algorithm interface
3  *
4  * This file provides the user-space API for algorithms.
5  *
6  * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  */
14
15 #include <linux/atomic.h>
16 #include <crypto/if_alg.h>
17 #include <linux/crypto.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/list.h>
21 #include <linux/module.h>
22 #include <linux/net.h>
23 #include <linux/rwsem.h>
24 #include <linux/security.h>
25
26 struct alg_type_list {
27         const struct af_alg_type *type;
28         struct list_head list;
29 };
30
31 static atomic_long_t alg_memory_allocated;
32
33 static struct proto alg_proto = {
34         .name                   = "ALG",
35         .owner                  = THIS_MODULE,
36         .memory_allocated       = &alg_memory_allocated,
37         .obj_size               = sizeof(struct alg_sock),
38 };
39
40 static LIST_HEAD(alg_types);
41 static DECLARE_RWSEM(alg_types_sem);
42
43 static const struct af_alg_type *alg_get_type(const char *name)
44 {
45         const struct af_alg_type *type = ERR_PTR(-ENOENT);
46         struct alg_type_list *node;
47
48         down_read(&alg_types_sem);
49         list_for_each_entry(node, &alg_types, list) {
50                 if (strcmp(node->type->name, name))
51                         continue;
52
53                 if (try_module_get(node->type->owner))
54                         type = node->type;
55                 break;
56         }
57         up_read(&alg_types_sem);
58
59         return type;
60 }
61
62 int af_alg_register_type(const struct af_alg_type *type)
63 {
64         struct alg_type_list *node;
65         int err = -EEXIST;
66
67         down_write(&alg_types_sem);
68         list_for_each_entry(node, &alg_types, list) {
69                 if (!strcmp(node->type->name, type->name))
70                         goto unlock;
71         }
72
73         node = kmalloc(sizeof(*node), GFP_KERNEL);
74         err = -ENOMEM;
75         if (!node)
76                 goto unlock;
77
78         type->ops->owner = THIS_MODULE;
79         if (type->ops_nokey)
80                 type->ops_nokey->owner = THIS_MODULE;
81         node->type = type;
82         list_add(&node->list, &alg_types);
83         err = 0;
84
85 unlock:
86         up_write(&alg_types_sem);
87
88         return err;
89 }
90 EXPORT_SYMBOL_GPL(af_alg_register_type);
91
92 int af_alg_unregister_type(const struct af_alg_type *type)
93 {
94         struct alg_type_list *node;
95         int err = -ENOENT;
96
97         down_write(&alg_types_sem);
98         list_for_each_entry(node, &alg_types, list) {
99                 if (strcmp(node->type->name, type->name))
100                         continue;
101
102                 list_del(&node->list);
103                 kfree(node);
104                 err = 0;
105                 break;
106         }
107         up_write(&alg_types_sem);
108
109         return err;
110 }
111 EXPORT_SYMBOL_GPL(af_alg_unregister_type);
112
113 static void alg_do_release(const struct af_alg_type *type, void *private)
114 {
115         if (!type)
116                 return;
117
118         type->release(private);
119         module_put(type->owner);
120 }
121
122 int af_alg_release(struct socket *sock)
123 {
124         if (sock->sk)
125                 sock_put(sock->sk);
126         return 0;
127 }
128 EXPORT_SYMBOL_GPL(af_alg_release);
129
130 void af_alg_release_parent(struct sock *sk)
131 {
132         struct alg_sock *ask = alg_sk(sk);
133         bool last;
134
135         sk = ask->parent;
136         ask = alg_sk(sk);
137
138         lock_sock(sk);
139         last = !--ask->refcnt;
140         release_sock(sk);
141
142         if (last)
143                 sock_put(sk);
144 }
145 EXPORT_SYMBOL_GPL(af_alg_release_parent);
146
147 static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
148 {
149         struct sock *sk = sock->sk;
150         struct alg_sock *ask = alg_sk(sk);
151         struct sockaddr_alg *sa = (void *)uaddr;
152         const struct af_alg_type *type;
153         void *private;
154         int err;
155
156         if (sock->state == SS_CONNECTED)
157                 return -EINVAL;
158
159         if (addr_len != sizeof(*sa))
160                 return -EINVAL;
161
162         sa->salg_type[sizeof(sa->salg_type) - 1] = 0;
163         sa->salg_name[sizeof(sa->salg_name) - 1] = 0;
164
165         type = alg_get_type(sa->salg_type);
166         if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
167                 request_module("algif-%s", sa->salg_type);
168                 type = alg_get_type(sa->salg_type);
169         }
170
171         if (IS_ERR(type))
172                 return PTR_ERR(type);
173
174         private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask);
175         if (IS_ERR(private)) {
176                 module_put(type->owner);
177                 return PTR_ERR(private);
178         }
179
180         err = -EBUSY;
181         lock_sock(sk);
182         if (ask->refcnt)
183                 goto unlock;
184
185         swap(ask->type, type);
186         swap(ask->private, private);
187
188         err = 0;
189
190 unlock:
191         release_sock(sk);
192
193         alg_do_release(type, private);
194
195         return err;
196 }
197
198 static int alg_setkey(struct sock *sk, char __user *ukey,
199                       unsigned int keylen)
200 {
201         struct alg_sock *ask = alg_sk(sk);
202         const struct af_alg_type *type = ask->type;
203         u8 *key;
204         int err;
205
206         key = sock_kmalloc(sk, keylen, GFP_KERNEL);
207         if (!key)
208                 return -ENOMEM;
209
210         err = -EFAULT;
211         if (copy_from_user(key, ukey, keylen))
212                 goto out;
213
214         err = type->setkey(ask->private, key, keylen);
215
216 out:
217         sock_kfree_s(sk, key, keylen);
218
219         return err;
220 }
221
222 static int alg_setsockopt(struct socket *sock, int level, int optname,
223                           char __user *optval, unsigned int optlen)
224 {
225         struct sock *sk = sock->sk;
226         struct alg_sock *ask = alg_sk(sk);
227         const struct af_alg_type *type;
228         int err = -EBUSY;
229
230         lock_sock(sk);
231         if (ask->refcnt)
232                 goto unlock;
233
234         type = ask->type;
235
236         err = -ENOPROTOOPT;
237         if (level != SOL_ALG || !type)
238                 goto unlock;
239
240         switch (optname) {
241         case ALG_SET_KEY:
242                 if (sock->state == SS_CONNECTED)
243                         goto unlock;
244                 if (!type->setkey)
245                         goto unlock;
246
247                 err = alg_setkey(sk, optval, optlen);
248         }
249
250 unlock:
251         release_sock(sk);
252
253         return err;
254 }
255
256 int af_alg_accept(struct sock *sk, struct socket *newsock)
257 {
258         struct alg_sock *ask = alg_sk(sk);
259         const struct af_alg_type *type;
260         struct sock *sk2;
261         int err;
262         bool nokey;
263
264         lock_sock(sk);
265         type = ask->type;
266
267         err = -EINVAL;
268         if (!type)
269                 goto unlock;
270
271         sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto);
272         err = -ENOMEM;
273         if (!sk2)
274                 goto unlock;
275
276         sock_init_data(newsock, sk2);
277         sock_graft(sk2, newsock);
278         security_sk_clone(sk, sk2);
279
280         err = type->accept(ask->private, sk2);
281
282         nokey = err == -ENOKEY;
283         if (nokey && type->accept_nokey)
284                 err = type->accept_nokey(ask->private, sk2);
285
286         if (err)
287                 goto unlock;
288
289         sk2->sk_family = PF_ALG;
290
291         if (nokey || !ask->refcnt++)
292                 sock_hold(sk);
293         alg_sk(sk2)->parent = sk;
294         alg_sk(sk2)->type = type;
295
296         newsock->ops = type->ops;
297         newsock->state = SS_CONNECTED;
298
299         if (nokey)
300                 newsock->ops = type->ops_nokey;
301
302         err = 0;
303
304 unlock:
305         release_sock(sk);
306
307         return err;
308 }
309 EXPORT_SYMBOL_GPL(af_alg_accept);
310
311 static int alg_accept(struct socket *sock, struct socket *newsock, int flags)
312 {
313         return af_alg_accept(sock->sk, newsock);
314 }
315
316 static const struct proto_ops alg_proto_ops = {
317         .family         =       PF_ALG,
318         .owner          =       THIS_MODULE,
319
320         .connect        =       sock_no_connect,
321         .socketpair     =       sock_no_socketpair,
322         .getname        =       sock_no_getname,
323         .ioctl          =       sock_no_ioctl,
324         .listen         =       sock_no_listen,
325         .shutdown       =       sock_no_shutdown,
326         .getsockopt     =       sock_no_getsockopt,
327         .mmap           =       sock_no_mmap,
328         .sendpage       =       sock_no_sendpage,
329         .sendmsg        =       sock_no_sendmsg,
330         .recvmsg        =       sock_no_recvmsg,
331         .poll           =       sock_no_poll,
332
333         .bind           =       alg_bind,
334         .release        =       af_alg_release,
335         .setsockopt     =       alg_setsockopt,
336         .accept         =       alg_accept,
337 };
338
339 static void alg_sock_destruct(struct sock *sk)
340 {
341         struct alg_sock *ask = alg_sk(sk);
342
343         alg_do_release(ask->type, ask->private);
344 }
345
346 static int alg_create(struct net *net, struct socket *sock, int protocol,
347                       int kern)
348 {
349         struct sock *sk;
350         int err;
351
352         if (sock->type != SOCK_SEQPACKET)
353                 return -ESOCKTNOSUPPORT;
354         if (protocol != 0)
355                 return -EPROTONOSUPPORT;
356
357         err = -ENOMEM;
358         sk = sk_alloc(net, PF_ALG, GFP_KERNEL, &alg_proto);
359         if (!sk)
360                 goto out;
361
362         sock->ops = &alg_proto_ops;
363         sock_init_data(sock, sk);
364
365         sk->sk_family = PF_ALG;
366         sk->sk_destruct = alg_sock_destruct;
367
368         return 0;
369 out:
370         return err;
371 }
372
373 static const struct net_proto_family alg_family = {
374         .family =       PF_ALG,
375         .create =       alg_create,
376         .owner  =       THIS_MODULE,
377 };
378
379 int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
380                    int write)
381 {
382         unsigned long from = (unsigned long)addr;
383         unsigned long npages;
384         unsigned off;
385         int err;
386         int i;
387
388         err = -EFAULT;
389         if (!access_ok(write ? VERIFY_READ : VERIFY_WRITE, addr, len))
390                 goto out;
391
392         off = from & ~PAGE_MASK;
393         npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
394         if (npages > ALG_MAX_PAGES)
395                 npages = ALG_MAX_PAGES;
396
397         err = get_user_pages_fast(from, npages, write, sgl->pages);
398         if (err < 0)
399                 goto out;
400
401         npages = err;
402         err = -EINVAL;
403         if (WARN_ON(npages == 0))
404                 goto out;
405
406         err = 0;
407
408         sg_init_table(sgl->sg, npages);
409
410         for (i = 0; i < npages; i++) {
411                 int plen = min_t(int, len, PAGE_SIZE - off);
412
413                 sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
414
415                 off = 0;
416                 len -= plen;
417                 err += plen;
418         }
419
420 out:
421         return err;
422 }
423 EXPORT_SYMBOL_GPL(af_alg_make_sg);
424
425 void af_alg_free_sg(struct af_alg_sgl *sgl)
426 {
427         int i;
428
429         i = 0;
430         do {
431                 put_page(sgl->pages[i]);
432         } while (!sg_is_last(sgl->sg + (i++)));
433 }
434 EXPORT_SYMBOL_GPL(af_alg_free_sg);
435
436 int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
437 {
438         struct cmsghdr *cmsg;
439
440         for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
441                 if (!CMSG_OK(msg, cmsg))
442                         return -EINVAL;
443                 if (cmsg->cmsg_level != SOL_ALG)
444                         continue;
445
446                 switch(cmsg->cmsg_type) {
447                 case ALG_SET_IV:
448                         if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->iv)))
449                                 return -EINVAL;
450                         con->iv = (void *)CMSG_DATA(cmsg);
451                         if (cmsg->cmsg_len < CMSG_LEN(con->iv->ivlen +
452                                                       sizeof(*con->iv)))
453                                 return -EINVAL;
454                         break;
455
456                 case ALG_SET_OP:
457                         if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
458                                 return -EINVAL;
459                         con->op = *(u32 *)CMSG_DATA(cmsg);
460                         break;
461
462                 default:
463                         return -EINVAL;
464                 }
465         }
466
467         return 0;
468 }
469 EXPORT_SYMBOL_GPL(af_alg_cmsg_send);
470
471 int af_alg_wait_for_completion(int err, struct af_alg_completion *completion)
472 {
473         switch (err) {
474         case -EINPROGRESS:
475         case -EBUSY:
476                 wait_for_completion(&completion->completion);
477                 INIT_COMPLETION(completion->completion);
478                 err = completion->err;
479                 break;
480         };
481
482         return err;
483 }
484 EXPORT_SYMBOL_GPL(af_alg_wait_for_completion);
485
486 void af_alg_complete(struct crypto_async_request *req, int err)
487 {
488         struct af_alg_completion *completion = req->data;
489
490         if (err == -EINPROGRESS)
491                 return;
492
493         completion->err = err;
494         complete(&completion->completion);
495 }
496 EXPORT_SYMBOL_GPL(af_alg_complete);
497
498 static int __init af_alg_init(void)
499 {
500         int err = proto_register(&alg_proto, 0);
501
502         if (err)
503                 goto out;
504
505         err = sock_register(&alg_family);
506         if (err != 0)
507                 goto out_unregister_proto;
508
509 out:
510         return err;
511
512 out_unregister_proto:
513         proto_unregister(&alg_proto);
514         goto out;
515 }
516
517 static void __exit af_alg_exit(void)
518 {
519         sock_unregister(PF_ALG);
520         proto_unregister(&alg_proto);
521 }
522
523 module_init(af_alg_init);
524 module_exit(af_alg_exit);
525 MODULE_LICENSE("GPL");
526 MODULE_ALIAS_NETPROTO(AF_ALG);