Back to home page

LXR

 
 

    


0001 /*
0002  * Crypto user configuration API.
0003  *
0004  * Copyright (C) 2011 secunet Security Networks AG
0005  * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
0006  *
0007  * This program is free software; you can redistribute it and/or modify it
0008  * under the terms and conditions of the GNU General Public License,
0009  * version 2, as published by the Free Software Foundation.
0010  *
0011  * This program is distributed in the hope it will be useful, but WITHOUT
0012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
0014  * more details.
0015  *
0016  * You should have received a copy of the GNU General Public License along with
0017  * this program; if not, write to the Free Software Foundation, Inc.,
0018  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
0019  */
0020 
0021 #include <linux/module.h>
0022 #include <linux/crypto.h>
0023 #include <linux/cryptouser.h>
0024 #include <linux/sched.h>
0025 #include <net/netlink.h>
0026 #include <linux/security.h>
0027 #include <net/net_namespace.h>
0028 #include <crypto/internal/skcipher.h>
0029 #include <crypto/internal/rng.h>
0030 #include <crypto/akcipher.h>
0031 #include <crypto/kpp.h>
0032 
0033 #include "internal.h"
0034 
0035 #define null_terminated(x)  (strnlen(x, sizeof(x)) < sizeof(x))
0036 
0037 static DEFINE_MUTEX(crypto_cfg_mutex);
0038 
0039 /* The crypto netlink socket */
0040 static struct sock *crypto_nlsk;
0041 
0042 struct crypto_dump_info {
0043     struct sk_buff *in_skb;
0044     struct sk_buff *out_skb;
0045     u32 nlmsg_seq;
0046     u16 nlmsg_flags;
0047 };
0048 
0049 static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
0050 {
0051     struct crypto_alg *q, *alg = NULL;
0052 
0053     down_read(&crypto_alg_sem);
0054 
0055     list_for_each_entry(q, &crypto_alg_list, cra_list) {
0056         int match = 0;
0057 
0058         if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
0059             continue;
0060 
0061         if (strlen(p->cru_driver_name))
0062             match = !strcmp(q->cra_driver_name,
0063                     p->cru_driver_name);
0064         else if (!exact)
0065             match = !strcmp(q->cra_name, p->cru_name);
0066 
0067         if (!match)
0068             continue;
0069 
0070         if (unlikely(!crypto_mod_get(q)))
0071             continue;
0072 
0073         alg = q;
0074         break;
0075     }
0076 
0077     up_read(&crypto_alg_sem);
0078 
0079     return alg;
0080 }
0081 
0082 static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
0083 {
0084     struct crypto_report_cipher rcipher;
0085 
0086     strncpy(rcipher.type, "cipher", sizeof(rcipher.type));
0087 
0088     rcipher.blocksize = alg->cra_blocksize;
0089     rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
0090     rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
0091 
0092     if (nla_put(skb, CRYPTOCFGA_REPORT_CIPHER,
0093             sizeof(struct crypto_report_cipher), &rcipher))
0094         goto nla_put_failure;
0095     return 0;
0096 
0097 nla_put_failure:
0098     return -EMSGSIZE;
0099 }
0100 
0101 static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
0102 {
0103     struct crypto_report_comp rcomp;
0104 
0105     strncpy(rcomp.type, "compression", sizeof(rcomp.type));
0106     if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
0107             sizeof(struct crypto_report_comp), &rcomp))
0108         goto nla_put_failure;
0109     return 0;
0110 
0111 nla_put_failure:
0112     return -EMSGSIZE;
0113 }
0114 
0115 static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
0116 {
0117     struct crypto_report_acomp racomp;
0118 
0119     strncpy(racomp.type, "acomp", sizeof(racomp.type));
0120 
0121     if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
0122             sizeof(struct crypto_report_acomp), &racomp))
0123         goto nla_put_failure;
0124     return 0;
0125 
0126 nla_put_failure:
0127     return -EMSGSIZE;
0128 }
0129 
0130 static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
0131 {
0132     struct crypto_report_akcipher rakcipher;
0133 
0134     strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
0135 
0136     if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
0137             sizeof(struct crypto_report_akcipher), &rakcipher))
0138         goto nla_put_failure;
0139     return 0;
0140 
0141 nla_put_failure:
0142     return -EMSGSIZE;
0143 }
0144 
0145 static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
0146 {
0147     struct crypto_report_kpp rkpp;
0148 
0149     strncpy(rkpp.type, "kpp", sizeof(rkpp.type));
0150 
0151     if (nla_put(skb, CRYPTOCFGA_REPORT_KPP,
0152             sizeof(struct crypto_report_kpp), &rkpp))
0153         goto nla_put_failure;
0154     return 0;
0155 
0156 nla_put_failure:
0157     return -EMSGSIZE;
0158 }
0159 
0160 static int crypto_report_one(struct crypto_alg *alg,
0161                  struct crypto_user_alg *ualg, struct sk_buff *skb)
0162 {
0163     strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
0164     strncpy(ualg->cru_driver_name, alg->cra_driver_name,
0165         sizeof(ualg->cru_driver_name));
0166     strncpy(ualg->cru_module_name, module_name(alg->cra_module),
0167         sizeof(ualg->cru_module_name));
0168 
0169     ualg->cru_type = 0;
0170     ualg->cru_mask = 0;
0171     ualg->cru_flags = alg->cra_flags;
0172     ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
0173 
0174     if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
0175         goto nla_put_failure;
0176     if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
0177         struct crypto_report_larval rl;
0178 
0179         strncpy(rl.type, "larval", sizeof(rl.type));
0180         if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
0181                 sizeof(struct crypto_report_larval), &rl))
0182             goto nla_put_failure;
0183         goto out;
0184     }
0185 
0186     if (alg->cra_type && alg->cra_type->report) {
0187         if (alg->cra_type->report(skb, alg))
0188             goto nla_put_failure;
0189 
0190         goto out;
0191     }
0192 
0193     switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
0194     case CRYPTO_ALG_TYPE_CIPHER:
0195         if (crypto_report_cipher(skb, alg))
0196             goto nla_put_failure;
0197 
0198         break;
0199     case CRYPTO_ALG_TYPE_COMPRESS:
0200         if (crypto_report_comp(skb, alg))
0201             goto nla_put_failure;
0202 
0203         break;
0204     case CRYPTO_ALG_TYPE_ACOMPRESS:
0205         if (crypto_report_acomp(skb, alg))
0206             goto nla_put_failure;
0207 
0208         break;
0209     case CRYPTO_ALG_TYPE_AKCIPHER:
0210         if (crypto_report_akcipher(skb, alg))
0211             goto nla_put_failure;
0212 
0213         break;
0214     case CRYPTO_ALG_TYPE_KPP:
0215         if (crypto_report_kpp(skb, alg))
0216             goto nla_put_failure;
0217         break;
0218     }
0219 
0220 out:
0221     return 0;
0222 
0223 nla_put_failure:
0224     return -EMSGSIZE;
0225 }
0226 
0227 static int crypto_report_alg(struct crypto_alg *alg,
0228                  struct crypto_dump_info *info)
0229 {
0230     struct sk_buff *in_skb = info->in_skb;
0231     struct sk_buff *skb = info->out_skb;
0232     struct nlmsghdr *nlh;
0233     struct crypto_user_alg *ualg;
0234     int err = 0;
0235 
0236     nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
0237             CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
0238     if (!nlh) {
0239         err = -EMSGSIZE;
0240         goto out;
0241     }
0242 
0243     ualg = nlmsg_data(nlh);
0244 
0245     err = crypto_report_one(alg, ualg, skb);
0246     if (err) {
0247         nlmsg_cancel(skb, nlh);
0248         goto out;
0249     }
0250 
0251     nlmsg_end(skb, nlh);
0252 
0253 out:
0254     return err;
0255 }
0256 
0257 static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
0258              struct nlattr **attrs)
0259 {
0260     struct crypto_user_alg *p = nlmsg_data(in_nlh);
0261     struct crypto_alg *alg;
0262     struct sk_buff *skb;
0263     struct crypto_dump_info info;
0264     int err;
0265 
0266     if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
0267         return -EINVAL;
0268 
0269     alg = crypto_alg_match(p, 0);
0270     if (!alg)
0271         return -ENOENT;
0272 
0273     err = -ENOMEM;
0274     skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
0275     if (!skb)
0276         goto drop_alg;
0277 
0278     info.in_skb = in_skb;
0279     info.out_skb = skb;
0280     info.nlmsg_seq = in_nlh->nlmsg_seq;
0281     info.nlmsg_flags = 0;
0282 
0283     err = crypto_report_alg(alg, &info);
0284 
0285 drop_alg:
0286     crypto_mod_put(alg);
0287 
0288     if (err)
0289         return err;
0290 
0291     return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
0292 }
0293 
0294 static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
0295 {
0296     struct crypto_alg *alg;
0297     struct crypto_dump_info info;
0298     int err;
0299 
0300     if (cb->args[0])
0301         goto out;
0302 
0303     cb->args[0] = 1;
0304 
0305     info.in_skb = cb->skb;
0306     info.out_skb = skb;
0307     info.nlmsg_seq = cb->nlh->nlmsg_seq;
0308     info.nlmsg_flags = NLM_F_MULTI;
0309 
0310     list_for_each_entry(alg, &crypto_alg_list, cra_list) {
0311         err = crypto_report_alg(alg, &info);
0312         if (err)
0313             goto out_err;
0314     }
0315 
0316 out:
0317     return skb->len;
0318 out_err:
0319     return err;
0320 }
0321 
0322 static int crypto_dump_report_done(struct netlink_callback *cb)
0323 {
0324     return 0;
0325 }
0326 
0327 static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
0328                  struct nlattr **attrs)
0329 {
0330     struct crypto_alg *alg;
0331     struct crypto_user_alg *p = nlmsg_data(nlh);
0332     struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
0333     LIST_HEAD(list);
0334 
0335     if (!netlink_capable(skb, CAP_NET_ADMIN))
0336         return -EPERM;
0337 
0338     if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
0339         return -EINVAL;
0340 
0341     if (priority && !strlen(p->cru_driver_name))
0342         return -EINVAL;
0343 
0344     alg = crypto_alg_match(p, 1);
0345     if (!alg)
0346         return -ENOENT;
0347 
0348     down_write(&crypto_alg_sem);
0349 
0350     crypto_remove_spawns(alg, &list, NULL);
0351 
0352     if (priority)
0353         alg->cra_priority = nla_get_u32(priority);
0354 
0355     up_write(&crypto_alg_sem);
0356 
0357     crypto_mod_put(alg);
0358     crypto_remove_final(&list);
0359 
0360     return 0;
0361 }
0362 
0363 static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
0364               struct nlattr **attrs)
0365 {
0366     struct crypto_alg *alg;
0367     struct crypto_user_alg *p = nlmsg_data(nlh);
0368     int err;
0369 
0370     if (!netlink_capable(skb, CAP_NET_ADMIN))
0371         return -EPERM;
0372 
0373     if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
0374         return -EINVAL;
0375 
0376     alg = crypto_alg_match(p, 1);
0377     if (!alg)
0378         return -ENOENT;
0379 
0380     /* We can not unregister core algorithms such as aes-generic.
0381      * We would loose the reference in the crypto_alg_list to this algorithm
0382      * if we try to unregister. Unregistering such an algorithm without
0383      * removing the module is not possible, so we restrict to crypto
0384      * instances that are build from templates. */
0385     err = -EINVAL;
0386     if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
0387         goto drop_alg;
0388 
0389     err = -EBUSY;
0390     if (atomic_read(&alg->cra_refcnt) > 2)
0391         goto drop_alg;
0392 
0393     err = crypto_unregister_instance((struct crypto_instance *)alg);
0394 
0395 drop_alg:
0396     crypto_mod_put(alg);
0397     return err;
0398 }
0399 
0400 static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
0401               struct nlattr **attrs)
0402 {
0403     int exact = 0;
0404     const char *name;
0405     struct crypto_alg *alg;
0406     struct crypto_user_alg *p = nlmsg_data(nlh);
0407     struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
0408 
0409     if (!netlink_capable(skb, CAP_NET_ADMIN))
0410         return -EPERM;
0411 
0412     if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
0413         return -EINVAL;
0414 
0415     if (strlen(p->cru_driver_name))
0416         exact = 1;
0417 
0418     if (priority && !exact)
0419         return -EINVAL;
0420 
0421     alg = crypto_alg_match(p, exact);
0422     if (alg) {
0423         crypto_mod_put(alg);
0424         return -EEXIST;
0425     }
0426 
0427     if (strlen(p->cru_driver_name))
0428         name = p->cru_driver_name;
0429     else
0430         name = p->cru_name;
0431 
0432     alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
0433     if (IS_ERR(alg))
0434         return PTR_ERR(alg);
0435 
0436     down_write(&crypto_alg_sem);
0437 
0438     if (priority)
0439         alg->cra_priority = nla_get_u32(priority);
0440 
0441     up_write(&crypto_alg_sem);
0442 
0443     crypto_mod_put(alg);
0444 
0445     return 0;
0446 }
0447 
0448 static int crypto_del_rng(struct sk_buff *skb, struct nlmsghdr *nlh,
0449               struct nlattr **attrs)
0450 {
0451     if (!netlink_capable(skb, CAP_NET_ADMIN))
0452         return -EPERM;
0453     return crypto_del_default_rng();
0454 }
0455 
0456 #define MSGSIZE(type) sizeof(struct type)
0457 
0458 static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
0459     [CRYPTO_MSG_NEWALG  - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
0460     [CRYPTO_MSG_DELALG  - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
0461     [CRYPTO_MSG_UPDATEALG   - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
0462     [CRYPTO_MSG_GETALG  - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
0463     [CRYPTO_MSG_DELRNG  - CRYPTO_MSG_BASE] = 0,
0464 };
0465 
0466 static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
0467     [CRYPTOCFGA_PRIORITY_VAL]   = { .type = NLA_U32},
0468 };
0469 
0470 #undef MSGSIZE
0471 
0472 static const struct crypto_link {
0473     int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
0474     int (*dump)(struct sk_buff *, struct netlink_callback *);
0475     int (*done)(struct netlink_callback *);
0476 } crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
0477     [CRYPTO_MSG_NEWALG  - CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
0478     [CRYPTO_MSG_DELALG  - CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
0479     [CRYPTO_MSG_UPDATEALG   - CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
0480     [CRYPTO_MSG_GETALG  - CRYPTO_MSG_BASE] = { .doit = crypto_report,
0481                                .dump = crypto_dump_report,
0482                                .done = crypto_dump_report_done},
0483     [CRYPTO_MSG_DELRNG  - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
0484 };
0485 
0486 static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
0487 {
0488     struct nlattr *attrs[CRYPTOCFGA_MAX+1];
0489     const struct crypto_link *link;
0490     int type, err;
0491 
0492     type = nlh->nlmsg_type;
0493     if (type > CRYPTO_MSG_MAX)
0494         return -EINVAL;
0495 
0496     type -= CRYPTO_MSG_BASE;
0497     link = &crypto_dispatch[type];
0498 
0499     if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
0500         (nlh->nlmsg_flags & NLM_F_DUMP))) {
0501         struct crypto_alg *alg;
0502         u16 dump_alloc = 0;
0503 
0504         if (link->dump == NULL)
0505             return -EINVAL;
0506 
0507         down_read(&crypto_alg_sem);
0508         list_for_each_entry(alg, &crypto_alg_list, cra_list)
0509             dump_alloc += CRYPTO_REPORT_MAXSIZE;
0510 
0511         {
0512             struct netlink_dump_control c = {
0513                 .dump = link->dump,
0514                 .done = link->done,
0515                 .min_dump_alloc = dump_alloc,
0516             };
0517             err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
0518         }
0519         up_read(&crypto_alg_sem);
0520 
0521         return err;
0522     }
0523 
0524     err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
0525               crypto_policy);
0526     if (err < 0)
0527         return err;
0528 
0529     if (link->doit == NULL)
0530         return -EINVAL;
0531 
0532     return link->doit(skb, nlh, attrs);
0533 }
0534 
0535 static void crypto_netlink_rcv(struct sk_buff *skb)
0536 {
0537     mutex_lock(&crypto_cfg_mutex);
0538     netlink_rcv_skb(skb, &crypto_user_rcv_msg);
0539     mutex_unlock(&crypto_cfg_mutex);
0540 }
0541 
0542 static int __init crypto_user_init(void)
0543 {
0544     struct netlink_kernel_cfg cfg = {
0545         .input  = crypto_netlink_rcv,
0546     };
0547 
0548     crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO, &cfg);
0549     if (!crypto_nlsk)
0550         return -ENOMEM;
0551 
0552     return 0;
0553 }
0554 
0555 static void __exit crypto_user_exit(void)
0556 {
0557     netlink_kernel_release(crypto_nlsk);
0558 }
0559 
0560 module_init(crypto_user_init);
0561 module_exit(crypto_user_exit);
0562 MODULE_LICENSE("GPL");
0563 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
0564 MODULE_DESCRIPTION("Crypto userspace configuration API");
0565 MODULE_ALIAS("net-pf-16-proto-21");