x86/smpboot: Init apic mapping before usage
[cascardo/linux.git] / crypto / crypto_user.c
1 /*
2  * Crypto user configuration API.
3  *
4  * Copyright (C) 2011 secunet Security Networks AG
5  * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <linux/module.h>
22 #include <linux/crypto.h>
23 #include <linux/cryptouser.h>
24 #include <linux/sched.h>
25 #include <net/netlink.h>
26 #include <linux/security.h>
27 #include <net/net_namespace.h>
28 #include <crypto/internal/skcipher.h>
29 #include <crypto/internal/rng.h>
30 #include <crypto/akcipher.h>
31 #include <crypto/kpp.h>
32
33 #include "internal.h"
34
35 #define null_terminated(x)      (strnlen(x, sizeof(x)) < sizeof(x))
36
37 static DEFINE_MUTEX(crypto_cfg_mutex);
38
39 /* The crypto netlink socket */
40 static struct sock *crypto_nlsk;
41
42 struct crypto_dump_info {
43         struct sk_buff *in_skb;
44         struct sk_buff *out_skb;
45         u32 nlmsg_seq;
46         u16 nlmsg_flags;
47 };
48
49 static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
50 {
51         struct crypto_alg *q, *alg = NULL;
52
53         down_read(&crypto_alg_sem);
54
55         list_for_each_entry(q, &crypto_alg_list, cra_list) {
56                 int match = 0;
57
58                 if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
59                         continue;
60
61                 if (strlen(p->cru_driver_name))
62                         match = !strcmp(q->cra_driver_name,
63                                         p->cru_driver_name);
64                 else if (!exact)
65                         match = !strcmp(q->cra_name, p->cru_name);
66
67                 if (!match)
68                         continue;
69
70                 if (unlikely(!crypto_mod_get(q)))
71                         continue;
72
73                 alg = q;
74                 break;
75         }
76
77         up_read(&crypto_alg_sem);
78
79         return alg;
80 }
81
82 static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
83 {
84         struct crypto_report_cipher rcipher;
85
86         strncpy(rcipher.type, "cipher", sizeof(rcipher.type));
87
88         rcipher.blocksize = alg->cra_blocksize;
89         rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
90         rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
91
92         if (nla_put(skb, CRYPTOCFGA_REPORT_CIPHER,
93                     sizeof(struct crypto_report_cipher), &rcipher))
94                 goto nla_put_failure;
95         return 0;
96
97 nla_put_failure:
98         return -EMSGSIZE;
99 }
100
101 static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
102 {
103         struct crypto_report_comp rcomp;
104
105         strncpy(rcomp.type, "compression", sizeof(rcomp.type));
106         if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
107                     sizeof(struct crypto_report_comp), &rcomp))
108                 goto nla_put_failure;
109         return 0;
110
111 nla_put_failure:
112         return -EMSGSIZE;
113 }
114
115 static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
116 {
117         struct crypto_report_akcipher rakcipher;
118
119         strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
120
121         if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
122                     sizeof(struct crypto_report_akcipher), &rakcipher))
123                 goto nla_put_failure;
124         return 0;
125
126 nla_put_failure:
127         return -EMSGSIZE;
128 }
129
130 static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
131 {
132         struct crypto_report_kpp rkpp;
133
134         strncpy(rkpp.type, "kpp", sizeof(rkpp.type));
135
136         if (nla_put(skb, CRYPTOCFGA_REPORT_KPP,
137                     sizeof(struct crypto_report_kpp), &rkpp))
138                 goto nla_put_failure;
139         return 0;
140
141 nla_put_failure:
142         return -EMSGSIZE;
143 }
144
145 static int crypto_report_one(struct crypto_alg *alg,
146                              struct crypto_user_alg *ualg, struct sk_buff *skb)
147 {
148         strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
149         strncpy(ualg->cru_driver_name, alg->cra_driver_name,
150                 sizeof(ualg->cru_driver_name));
151         strncpy(ualg->cru_module_name, module_name(alg->cra_module),
152                 sizeof(ualg->cru_module_name));
153
154         ualg->cru_type = 0;
155         ualg->cru_mask = 0;
156         ualg->cru_flags = alg->cra_flags;
157         ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
158
159         if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
160                 goto nla_put_failure;
161         if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
162                 struct crypto_report_larval rl;
163
164                 strncpy(rl.type, "larval", sizeof(rl.type));
165                 if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
166                             sizeof(struct crypto_report_larval), &rl))
167                         goto nla_put_failure;
168                 goto out;
169         }
170
171         if (alg->cra_type && alg->cra_type->report) {
172                 if (alg->cra_type->report(skb, alg))
173                         goto nla_put_failure;
174
175                 goto out;
176         }
177
178         switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
179         case CRYPTO_ALG_TYPE_CIPHER:
180                 if (crypto_report_cipher(skb, alg))
181                         goto nla_put_failure;
182
183                 break;
184         case CRYPTO_ALG_TYPE_COMPRESS:
185                 if (crypto_report_comp(skb, alg))
186                         goto nla_put_failure;
187
188                 break;
189
190         case CRYPTO_ALG_TYPE_AKCIPHER:
191                 if (crypto_report_akcipher(skb, alg))
192                         goto nla_put_failure;
193
194                 break;
195         case CRYPTO_ALG_TYPE_KPP:
196                 if (crypto_report_kpp(skb, alg))
197                         goto nla_put_failure;
198                 break;
199         }
200
201 out:
202         return 0;
203
204 nla_put_failure:
205         return -EMSGSIZE;
206 }
207
208 static int crypto_report_alg(struct crypto_alg *alg,
209                              struct crypto_dump_info *info)
210 {
211         struct sk_buff *in_skb = info->in_skb;
212         struct sk_buff *skb = info->out_skb;
213         struct nlmsghdr *nlh;
214         struct crypto_user_alg *ualg;
215         int err = 0;
216
217         nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
218                         CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
219         if (!nlh) {
220                 err = -EMSGSIZE;
221                 goto out;
222         }
223
224         ualg = nlmsg_data(nlh);
225
226         err = crypto_report_one(alg, ualg, skb);
227         if (err) {
228                 nlmsg_cancel(skb, nlh);
229                 goto out;
230         }
231
232         nlmsg_end(skb, nlh);
233
234 out:
235         return err;
236 }
237
238 static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
239                          struct nlattr **attrs)
240 {
241         struct crypto_user_alg *p = nlmsg_data(in_nlh);
242         struct crypto_alg *alg;
243         struct sk_buff *skb;
244         struct crypto_dump_info info;
245         int err;
246
247         if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
248                 return -EINVAL;
249
250         alg = crypto_alg_match(p, 0);
251         if (!alg)
252                 return -ENOENT;
253
254         err = -ENOMEM;
255         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
256         if (!skb)
257                 goto drop_alg;
258
259         info.in_skb = in_skb;
260         info.out_skb = skb;
261         info.nlmsg_seq = in_nlh->nlmsg_seq;
262         info.nlmsg_flags = 0;
263
264         err = crypto_report_alg(alg, &info);
265
266 drop_alg:
267         crypto_mod_put(alg);
268
269         if (err)
270                 return err;
271
272         return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
273 }
274
275 static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
276 {
277         struct crypto_alg *alg;
278         struct crypto_dump_info info;
279         int err;
280
281         if (cb->args[0])
282                 goto out;
283
284         cb->args[0] = 1;
285
286         info.in_skb = cb->skb;
287         info.out_skb = skb;
288         info.nlmsg_seq = cb->nlh->nlmsg_seq;
289         info.nlmsg_flags = NLM_F_MULTI;
290
291         list_for_each_entry(alg, &crypto_alg_list, cra_list) {
292                 err = crypto_report_alg(alg, &info);
293                 if (err)
294                         goto out_err;
295         }
296
297 out:
298         return skb->len;
299 out_err:
300         return err;
301 }
302
303 static int crypto_dump_report_done(struct netlink_callback *cb)
304 {
305         return 0;
306 }
307
308 static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
309                              struct nlattr **attrs)
310 {
311         struct crypto_alg *alg;
312         struct crypto_user_alg *p = nlmsg_data(nlh);
313         struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
314         LIST_HEAD(list);
315
316         if (!netlink_capable(skb, CAP_NET_ADMIN))
317                 return -EPERM;
318
319         if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
320                 return -EINVAL;
321
322         if (priority && !strlen(p->cru_driver_name))
323                 return -EINVAL;
324
325         alg = crypto_alg_match(p, 1);
326         if (!alg)
327                 return -ENOENT;
328
329         down_write(&crypto_alg_sem);
330
331         crypto_remove_spawns(alg, &list, NULL);
332
333         if (priority)
334                 alg->cra_priority = nla_get_u32(priority);
335
336         up_write(&crypto_alg_sem);
337
338         crypto_mod_put(alg);
339         crypto_remove_final(&list);
340
341         return 0;
342 }
343
344 static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
345                           struct nlattr **attrs)
346 {
347         struct crypto_alg *alg;
348         struct crypto_user_alg *p = nlmsg_data(nlh);
349         int err;
350
351         if (!netlink_capable(skb, CAP_NET_ADMIN))
352                 return -EPERM;
353
354         if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
355                 return -EINVAL;
356
357         alg = crypto_alg_match(p, 1);
358         if (!alg)
359                 return -ENOENT;
360
361         /* We can not unregister core algorithms such as aes-generic.
362          * We would loose the reference in the crypto_alg_list to this algorithm
363          * if we try to unregister. Unregistering such an algorithm without
364          * removing the module is not possible, so we restrict to crypto
365          * instances that are build from templates. */
366         err = -EINVAL;
367         if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
368                 goto drop_alg;
369
370         err = -EBUSY;
371         if (atomic_read(&alg->cra_refcnt) > 2)
372                 goto drop_alg;
373
374         err = crypto_unregister_instance((struct crypto_instance *)alg);
375
376 drop_alg:
377         crypto_mod_put(alg);
378         return err;
379 }
380
381 static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
382                           struct nlattr **attrs)
383 {
384         int exact = 0;
385         const char *name;
386         struct crypto_alg *alg;
387         struct crypto_user_alg *p = nlmsg_data(nlh);
388         struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
389
390         if (!netlink_capable(skb, CAP_NET_ADMIN))
391                 return -EPERM;
392
393         if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
394                 return -EINVAL;
395
396         if (strlen(p->cru_driver_name))
397                 exact = 1;
398
399         if (priority && !exact)
400                 return -EINVAL;
401
402         alg = crypto_alg_match(p, exact);
403         if (alg) {
404                 crypto_mod_put(alg);
405                 return -EEXIST;
406         }
407
408         if (strlen(p->cru_driver_name))
409                 name = p->cru_driver_name;
410         else
411                 name = p->cru_name;
412
413         alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
414         if (IS_ERR(alg))
415                 return PTR_ERR(alg);
416
417         down_write(&crypto_alg_sem);
418
419         if (priority)
420                 alg->cra_priority = nla_get_u32(priority);
421
422         up_write(&crypto_alg_sem);
423
424         crypto_mod_put(alg);
425
426         return 0;
427 }
428
429 static int crypto_del_rng(struct sk_buff *skb, struct nlmsghdr *nlh,
430                           struct nlattr **attrs)
431 {
432         if (!netlink_capable(skb, CAP_NET_ADMIN))
433                 return -EPERM;
434         return crypto_del_default_rng();
435 }
436
437 #define MSGSIZE(type) sizeof(struct type)
438
439 static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
440         [CRYPTO_MSG_NEWALG      - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
441         [CRYPTO_MSG_DELALG      - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
442         [CRYPTO_MSG_UPDATEALG   - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
443         [CRYPTO_MSG_GETALG      - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
444         [CRYPTO_MSG_DELRNG      - CRYPTO_MSG_BASE] = 0,
445 };
446
447 static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
448         [CRYPTOCFGA_PRIORITY_VAL]   = { .type = NLA_U32},
449 };
450
451 #undef MSGSIZE
452
453 static const struct crypto_link {
454         int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
455         int (*dump)(struct sk_buff *, struct netlink_callback *);
456         int (*done)(struct netlink_callback *);
457 } crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
458         [CRYPTO_MSG_NEWALG      - CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
459         [CRYPTO_MSG_DELALG      - CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
460         [CRYPTO_MSG_UPDATEALG   - CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
461         [CRYPTO_MSG_GETALG      - CRYPTO_MSG_BASE] = { .doit = crypto_report,
462                                                        .dump = crypto_dump_report,
463                                                        .done = crypto_dump_report_done},
464         [CRYPTO_MSG_DELRNG      - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
465 };
466
467 static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
468 {
469         struct nlattr *attrs[CRYPTOCFGA_MAX+1];
470         const struct crypto_link *link;
471         int type, err;
472
473         type = nlh->nlmsg_type;
474         if (type > CRYPTO_MSG_MAX)
475                 return -EINVAL;
476
477         type -= CRYPTO_MSG_BASE;
478         link = &crypto_dispatch[type];
479
480         if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
481             (nlh->nlmsg_flags & NLM_F_DUMP))) {
482                 struct crypto_alg *alg;
483                 u16 dump_alloc = 0;
484
485                 if (link->dump == NULL)
486                         return -EINVAL;
487
488                 down_read(&crypto_alg_sem);
489                 list_for_each_entry(alg, &crypto_alg_list, cra_list)
490                         dump_alloc += CRYPTO_REPORT_MAXSIZE;
491
492                 {
493                         struct netlink_dump_control c = {
494                                 .dump = link->dump,
495                                 .done = link->done,
496                                 .min_dump_alloc = dump_alloc,
497                         };
498                         err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
499                 }
500                 up_read(&crypto_alg_sem);
501
502                 return err;
503         }
504
505         err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
506                           crypto_policy);
507         if (err < 0)
508                 return err;
509
510         if (link->doit == NULL)
511                 return -EINVAL;
512
513         return link->doit(skb, nlh, attrs);
514 }
515
516 static void crypto_netlink_rcv(struct sk_buff *skb)
517 {
518         mutex_lock(&crypto_cfg_mutex);
519         netlink_rcv_skb(skb, &crypto_user_rcv_msg);
520         mutex_unlock(&crypto_cfg_mutex);
521 }
522
523 static int __init crypto_user_init(void)
524 {
525         struct netlink_kernel_cfg cfg = {
526                 .input  = crypto_netlink_rcv,
527         };
528
529         crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO, &cfg);
530         if (!crypto_nlsk)
531                 return -ENOMEM;
532
533         return 0;
534 }
535
536 static void __exit crypto_user_exit(void)
537 {
538         netlink_kernel_release(crypto_nlsk);
539 }
540
541 module_init(crypto_user_init);
542 module_exit(crypto_user_exit);
543 MODULE_LICENSE("GPL");
544 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
545 MODULE_DESCRIPTION("Crypto userspace configuration API");
546 MODULE_ALIAS("net-pf-16-proto-21");