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