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