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