Blame view

crypto/crypto_user.c 13.1 KB
a38f7907b   Steffen Klassert   crypto: Add users...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   * Crypto user configuration API.
   *
   * Copyright (C) 2011 secunet Security Networks AG
   * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms and conditions of the GNU General Public License,
   * version 2, as published by the Free Software Foundation.
   *
   * This program is distributed in the hope it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License along with
   * this program; if not, write to the Free Software Foundation, Inc.,
   * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   */
  
  #include <linux/module.h>
  #include <linux/crypto.h>
  #include <linux/cryptouser.h>
1e1229940   Steffen Klassert   crypto: user - Fi...
24
  #include <linux/sched.h>
a38f7907b   Steffen Klassert   crypto: Add users...
25
26
27
  #include <net/netlink.h>
  #include <linux/security.h>
  #include <net/net_namespace.h>
1e1229940   Steffen Klassert   crypto: user - Fi...
28
  #include <crypto/internal/skcipher.h>
9aa867e46   Herbert Xu   crypto: user - Ad...
29
  #include <crypto/internal/rng.h>
3c339ab83   Tadeusz Struk   crypto: akcipher ...
30
  #include <crypto/akcipher.h>
4e5f2c400   Salvatore Benedetto   crypto: kpp - Key...
31
  #include <crypto/kpp.h>
1e1229940   Steffen Klassert   crypto: user - Fi...
32

a38f7907b   Steffen Klassert   crypto: Add users...
33
  #include "internal.h"
8fd61d342   Mathias Krause   crypto: user - en...
34
  #define null_terminated(x)	(strnlen(x, sizeof(x)) < sizeof(x))
66ce0b0f2   Jussi Kivilinna   crypto: crypto_us...
35
  static DEFINE_MUTEX(crypto_cfg_mutex);
a38f7907b   Steffen Klassert   crypto: Add users...
36
37
38
39
40
41
42
43
44
45
46
47
48
  
  /* The crypto netlink socket */
  static struct sock *crypto_nlsk;
  
  struct crypto_dump_info {
  	struct sk_buff *in_skb;
  	struct sk_buff *out_skb;
  	u32 nlmsg_seq;
  	u16 nlmsg_flags;
  };
  
  static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
  {
a38f7907b   Steffen Klassert   crypto: Add users...
49
50
51
  	struct crypto_alg *q, *alg = NULL;
  
  	down_read(&crypto_alg_sem);
a38f7907b   Steffen Klassert   crypto: Add users...
52
  	list_for_each_entry(q, &crypto_alg_list, cra_list) {
e6ea64ece   Herbert Xu   crypto: user - In...
53
  		int match = 0;
a38f7907b   Steffen Klassert   crypto: Add users...
54
55
56
57
58
59
60
61
62
  
  		if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
  			continue;
  
  		if (strlen(p->cru_driver_name))
  			match = !strcmp(q->cra_driver_name,
  					p->cru_driver_name);
  		else if (!exact)
  			match = !strcmp(q->cra_name, p->cru_name);
016baaa11   Herbert Xu   crypto: user - Fi...
63
64
65
66
67
68
69
70
  		if (!match)
  			continue;
  
  		if (unlikely(!crypto_mod_get(q)))
  			continue;
  
  		alg = q;
  		break;
a38f7907b   Steffen Klassert   crypto: Add users...
71
72
73
74
75
76
  	}
  
  	up_read(&crypto_alg_sem);
  
  	return alg;
  }
07a5fa4ab   Steffen Klassert   crypto: Add users...
77
78
79
  static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_cipher rcipher;
a0f044f02   Eric Biggers   crypto: user - fi...
80
  	strncpy(rcipher.type, "cipher", sizeof(rcipher.type));
07a5fa4ab   Steffen Klassert   crypto: Add users...
81
82
83
84
  
  	rcipher.blocksize = alg->cra_blocksize;
  	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
  	rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
6662df33f   David S. Miller   crypto: Stop usin...
85
86
87
  	if (nla_put(skb, CRYPTOCFGA_REPORT_CIPHER,
  		    sizeof(struct crypto_report_cipher), &rcipher))
  		goto nla_put_failure;
07a5fa4ab   Steffen Klassert   crypto: Add users...
88
89
90
91
92
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
540b97c1d   Steffen Klassert   crypto: Add users...
93
94
95
  static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_comp rcomp;
a0f044f02   Eric Biggers   crypto: user - fi...
96
  	strncpy(rcomp.type, "compression", sizeof(rcomp.type));
6662df33f   David S. Miller   crypto: Stop usin...
97
98
99
  	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
  		    sizeof(struct crypto_report_comp), &rcomp))
  		goto nla_put_failure;
540b97c1d   Steffen Klassert   crypto: Add users...
100
101
102
103
104
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
2ebda74fd   Giovanni Cabiddu   crypto: acomp - a...
105
106
107
  static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_acomp racomp;
a0f044f02   Eric Biggers   crypto: user - fi...
108
  	strncpy(racomp.type, "acomp", sizeof(racomp.type));
2ebda74fd   Giovanni Cabiddu   crypto: acomp - a...
109
110
111
112
113
114
115
116
117
  
  	if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
  		    sizeof(struct crypto_report_acomp), &racomp))
  		goto nla_put_failure;
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
3c339ab83   Tadeusz Struk   crypto: akcipher ...
118
119
120
  static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_akcipher rakcipher;
a0f044f02   Eric Biggers   crypto: user - fi...
121
  	strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
3c339ab83   Tadeusz Struk   crypto: akcipher ...
122
123
124
125
126
127
128
129
130
  
  	if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
  		    sizeof(struct crypto_report_akcipher), &rakcipher))
  		goto nla_put_failure;
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
4e5f2c400   Salvatore Benedetto   crypto: kpp - Key...
131
132
133
  static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_kpp rkpp;
a0f044f02   Eric Biggers   crypto: user - fi...
134
  	strncpy(rkpp.type, "kpp", sizeof(rkpp.type));
4e5f2c400   Salvatore Benedetto   crypto: kpp - Key...
135
136
137
138
139
140
141
142
143
  
  	if (nla_put(skb, CRYPTOCFGA_REPORT_KPP,
  		    sizeof(struct crypto_report_kpp), &rkpp))
  		goto nla_put_failure;
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
a38f7907b   Steffen Klassert   crypto: Add users...
144
145
146
  static int crypto_report_one(struct crypto_alg *alg,
  			     struct crypto_user_alg *ualg, struct sk_buff *skb)
  {
a0f044f02   Eric Biggers   crypto: user - fi...
147
148
  	strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
  	strncpy(ualg->cru_driver_name, alg->cra_driver_name,
9a5467bf7   Mathias Krause   crypto: user - fi...
149
  		sizeof(ualg->cru_driver_name));
a0f044f02   Eric Biggers   crypto: user - fi...
150
  	strncpy(ualg->cru_module_name, module_name(alg->cra_module),
9a5467bf7   Mathias Krause   crypto: user - fi...
151
152
153
154
  		sizeof(ualg->cru_module_name));
  
  	ualg->cru_type = 0;
  	ualg->cru_mask = 0;
a38f7907b   Steffen Klassert   crypto: Add users...
155
  	ualg->cru_flags = alg->cra_flags;
ce8614a31   Eric Biggers   crypto: algapi - ...
156
  	ualg->cru_refcnt = refcount_read(&alg->cra_refcnt);
a38f7907b   Steffen Klassert   crypto: Add users...
157

6662df33f   David S. Miller   crypto: Stop usin...
158
159
  	if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
  		goto nla_put_failure;
6c5a86f52   Steffen Klassert   crypto: Add users...
160
161
  	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
  		struct crypto_report_larval rl;
a0f044f02   Eric Biggers   crypto: user - fi...
162
  		strncpy(rl.type, "larval", sizeof(rl.type));
6662df33f   David S. Miller   crypto: Stop usin...
163
164
165
  		if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
  			    sizeof(struct crypto_report_larval), &rl))
  			goto nla_put_failure;
6c5a86f52   Steffen Klassert   crypto: Add users...
166
167
  		goto out;
  	}
b6aa63c09   Steffen Klassert   crypto: Add a rep...
168
169
170
  	if (alg->cra_type && alg->cra_type->report) {
  		if (alg->cra_type->report(skb, alg))
  			goto nla_put_failure;
07a5fa4ab   Steffen Klassert   crypto: Add users...
171
172
173
174
175
176
177
178
179
180
  
  		goto out;
  	}
  
  	switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
  	case CRYPTO_ALG_TYPE_CIPHER:
  		if (crypto_report_cipher(skb, alg))
  			goto nla_put_failure;
  
  		break;
540b97c1d   Steffen Klassert   crypto: Add users...
181
182
183
184
185
  	case CRYPTO_ALG_TYPE_COMPRESS:
  		if (crypto_report_comp(skb, alg))
  			goto nla_put_failure;
  
  		break;
2ebda74fd   Giovanni Cabiddu   crypto: acomp - a...
186
187
188
  	case CRYPTO_ALG_TYPE_ACOMPRESS:
  		if (crypto_report_acomp(skb, alg))
  			goto nla_put_failure;
3c339ab83   Tadeusz Struk   crypto: akcipher ...
189

2ebda74fd   Giovanni Cabiddu   crypto: acomp - a...
190
  		break;
3c339ab83   Tadeusz Struk   crypto: akcipher ...
191
192
193
194
195
  	case CRYPTO_ALG_TYPE_AKCIPHER:
  		if (crypto_report_akcipher(skb, alg))
  			goto nla_put_failure;
  
  		break;
4e5f2c400   Salvatore Benedetto   crypto: kpp - Key...
196
197
198
199
  	case CRYPTO_ALG_TYPE_KPP:
  		if (crypto_report_kpp(skb, alg))
  			goto nla_put_failure;
  		break;
b6aa63c09   Steffen Klassert   crypto: Add a rep...
200
  	}
6c5a86f52   Steffen Klassert   crypto: Add users...
201
  out:
a38f7907b   Steffen Klassert   crypto: Add users...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
  
  static int crypto_report_alg(struct crypto_alg *alg,
  			     struct crypto_dump_info *info)
  {
  	struct sk_buff *in_skb = info->in_skb;
  	struct sk_buff *skb = info->out_skb;
  	struct nlmsghdr *nlh;
  	struct crypto_user_alg *ualg;
  	int err = 0;
15e473046   Eric W. Biederman   netlink: Rename p...
216
  	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
a38f7907b   Steffen Klassert   crypto: Add users...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  			CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
  	if (!nlh) {
  		err = -EMSGSIZE;
  		goto out;
  	}
  
  	ualg = nlmsg_data(nlh);
  
  	err = crypto_report_one(alg, ualg, skb);
  	if (err) {
  		nlmsg_cancel(skb, nlh);
  		goto out;
  	}
  
  	nlmsg_end(skb, nlh);
  
  out:
  	return err;
  }
  
  static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
  			 struct nlattr **attrs)
  {
  	struct crypto_user_alg *p = nlmsg_data(in_nlh);
  	struct crypto_alg *alg;
  	struct sk_buff *skb;
  	struct crypto_dump_info info;
  	int err;
8fd61d342   Mathias Krause   crypto: user - en...
245
246
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
5d4a5e770   Herbert Xu   crypto: user - Al...
247
  	alg = crypto_alg_match(p, 0);
a38f7907b   Steffen Klassert   crypto: Add users...
248
249
  	if (!alg)
  		return -ENOENT;
016baaa11   Herbert Xu   crypto: user - Fi...
250
  	err = -ENOMEM;
9a69b7ae7   Jia-Ju Bai   crypto: user - Re...
251
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
a38f7907b   Steffen Klassert   crypto: Add users...
252
  	if (!skb)
016baaa11   Herbert Xu   crypto: user - Fi...
253
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
254
255
256
257
258
259
260
  
  	info.in_skb = in_skb;
  	info.out_skb = skb;
  	info.nlmsg_seq = in_nlh->nlmsg_seq;
  	info.nlmsg_flags = 0;
  
  	err = crypto_report_alg(alg, &info);
016baaa11   Herbert Xu   crypto: user - Fi...
261
262
263
  
  drop_alg:
  	crypto_mod_put(alg);
a38f7907b   Steffen Klassert   crypto: Add users...
264
265
  	if (err)
  		return err;
15e473046   Eric W. Biederman   netlink: Rename p...
266
  	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
a38f7907b   Steffen Klassert   crypto: Add users...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  }
  
  static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	struct crypto_alg *alg;
  	struct crypto_dump_info info;
  	int err;
  
  	if (cb->args[0])
  		goto out;
  
  	cb->args[0] = 1;
  
  	info.in_skb = cb->skb;
  	info.out_skb = skb;
  	info.nlmsg_seq = cb->nlh->nlmsg_seq;
  	info.nlmsg_flags = NLM_F_MULTI;
  
  	list_for_each_entry(alg, &crypto_alg_list, cra_list) {
  		err = crypto_report_alg(alg, &info);
  		if (err)
  			goto out_err;
  	}
  
  out:
  	return skb->len;
  out_err:
  	return err;
  }
  
  static int crypto_dump_report_done(struct netlink_callback *cb)
  {
  	return 0;
  }
  
  static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
  			     struct nlattr **attrs)
  {
  	struct crypto_alg *alg;
  	struct crypto_user_alg *p = nlmsg_data(nlh);
  	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
  	LIST_HEAD(list);
639b4ac69   Linus Torvalds   Merge git://git.k...
309
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
c568398aa   Matthias-Christian Ott   crypto: user - Al...
310
  		return -EPERM;
8fd61d342   Mathias Krause   crypto: user - en...
311
312
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  	if (priority && !strlen(p->cru_driver_name))
  		return -EINVAL;
  
  	alg = crypto_alg_match(p, 1);
  	if (!alg)
  		return -ENOENT;
  
  	down_write(&crypto_alg_sem);
  
  	crypto_remove_spawns(alg, &list, NULL);
  
  	if (priority)
  		alg->cra_priority = nla_get_u32(priority);
  
  	up_write(&crypto_alg_sem);
016baaa11   Herbert Xu   crypto: user - Fi...
328
  	crypto_mod_put(alg);
a38f7907b   Steffen Klassert   crypto: Add users...
329
330
331
332
333
334
335
336
337
338
  	crypto_remove_final(&list);
  
  	return 0;
  }
  
  static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
  			  struct nlattr **attrs)
  {
  	struct crypto_alg *alg;
  	struct crypto_user_alg *p = nlmsg_data(nlh);
016baaa11   Herbert Xu   crypto: user - Fi...
339
  	int err;
a38f7907b   Steffen Klassert   crypto: Add users...
340

639b4ac69   Linus Torvalds   Merge git://git.k...
341
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
c568398aa   Matthias-Christian Ott   crypto: user - Al...
342
  		return -EPERM;
8fd61d342   Mathias Krause   crypto: user - en...
343
344
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
345
346
347
348
349
350
351
352
353
  	alg = crypto_alg_match(p, 1);
  	if (!alg)
  		return -ENOENT;
  
  	/* We can not unregister core algorithms such as aes-generic.
  	 * We would loose the reference in the crypto_alg_list to this algorithm
  	 * if we try to unregister. Unregistering such an algorithm without
  	 * removing the module is not possible, so we restrict to crypto
  	 * instances that are build from templates. */
016baaa11   Herbert Xu   crypto: user - Fi...
354
  	err = -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
355
  	if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
016baaa11   Herbert Xu   crypto: user - Fi...
356
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
357

016baaa11   Herbert Xu   crypto: user - Fi...
358
  	err = -EBUSY;
ce8614a31   Eric Biggers   crypto: algapi - ...
359
  	if (refcount_read(&alg->cra_refcnt) > 2)
016baaa11   Herbert Xu   crypto: user - Fi...
360
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
361

016baaa11   Herbert Xu   crypto: user - Fi...
362
363
364
365
366
  	err = crypto_unregister_instance((struct crypto_instance *)alg);
  
  drop_alg:
  	crypto_mod_put(alg);
  	return err;
a38f7907b   Steffen Klassert   crypto: Add users...
367
368
369
370
371
  }
  
  static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
  			  struct nlattr **attrs)
  {
0cfdec7a6   Jesper Juhl   crypto: In crypto...
372
  	int exact = 0;
a38f7907b   Steffen Klassert   crypto: Add users...
373
374
375
376
  	const char *name;
  	struct crypto_alg *alg;
  	struct crypto_user_alg *p = nlmsg_data(nlh);
  	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
639b4ac69   Linus Torvalds   Merge git://git.k...
377
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
c568398aa   Matthias-Christian Ott   crypto: user - Al...
378
  		return -EPERM;
8fd61d342   Mathias Krause   crypto: user - en...
379
380
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
381
382
383
384
385
386
387
  	if (strlen(p->cru_driver_name))
  		exact = 1;
  
  	if (priority && !exact)
  		return -EINVAL;
  
  	alg = crypto_alg_match(p, exact);
016baaa11   Herbert Xu   crypto: user - Fi...
388
389
  	if (alg) {
  		crypto_mod_put(alg);
a38f7907b   Steffen Klassert   crypto: Add users...
390
  		return -EEXIST;
016baaa11   Herbert Xu   crypto: user - Fi...
391
  	}
a38f7907b   Steffen Klassert   crypto: Add users...
392
393
394
395
396
  
  	if (strlen(p->cru_driver_name))
  		name = p->cru_driver_name;
  	else
  		name = p->cru_name;
6cf80a296   Herbert Xu   crypto: user - Re...
397
  	alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
a38f7907b   Steffen Klassert   crypto: Add users...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  	if (IS_ERR(alg))
  		return PTR_ERR(alg);
  
  	down_write(&crypto_alg_sem);
  
  	if (priority)
  		alg->cra_priority = nla_get_u32(priority);
  
  	up_write(&crypto_alg_sem);
  
  	crypto_mod_put(alg);
  
  	return 0;
  }
9aa867e46   Herbert Xu   crypto: user - Ad...
412
413
414
415
416
417
418
  static int crypto_del_rng(struct sk_buff *skb, struct nlmsghdr *nlh,
  			  struct nlattr **attrs)
  {
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
  		return -EPERM;
  	return crypto_del_default_rng();
  }
a38f7907b   Steffen Klassert   crypto: Add users...
419
420
421
422
423
424
  #define MSGSIZE(type) sizeof(struct type)
  
  static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
  	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
  	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
  	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
055ddaace   Mathias Krause   crypto: user - re...
425
  	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
9aa867e46   Herbert Xu   crypto: user - Ad...
426
  	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = 0,
a38f7907b   Steffen Klassert   crypto: Add users...
427
428
429
430
431
432
433
  };
  
  static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
  	[CRYPTOCFGA_PRIORITY_VAL]   = { .type = NLA_U32},
  };
  
  #undef MSGSIZE
a84fb791c   Mathias Krause   crypto: user - co...
434
  static const struct crypto_link {
a38f7907b   Steffen Klassert   crypto: Add users...
435
436
437
438
439
440
441
442
443
444
  	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
  	int (*dump)(struct sk_buff *, struct netlink_callback *);
  	int (*done)(struct netlink_callback *);
  } crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
  	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
  	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
  	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
  	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = { .doit = crypto_report,
  						       .dump = crypto_dump_report,
  						       .done = crypto_dump_report_done},
9aa867e46   Herbert Xu   crypto: user - Ad...
445
  	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
a38f7907b   Steffen Klassert   crypto: Add users...
446
  };
2d4bc9336   Johannes Berg   netlink: extended...
447
448
  static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
  			       struct netlink_ext_ack *extack)
a38f7907b   Steffen Klassert   crypto: Add users...
449
450
  {
  	struct nlattr *attrs[CRYPTOCFGA_MAX+1];
a84fb791c   Mathias Krause   crypto: user - co...
451
  	const struct crypto_link *link;
a38f7907b   Steffen Klassert   crypto: Add users...
452
453
454
455
456
457
458
459
  	int type, err;
  
  	type = nlh->nlmsg_type;
  	if (type > CRYPTO_MSG_MAX)
  		return -EINVAL;
  
  	type -= CRYPTO_MSG_BASE;
  	link = &crypto_dispatch[type];
a38f7907b   Steffen Klassert   crypto: Add users...
460
461
  	if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
  	    (nlh->nlmsg_flags & NLM_F_DUMP))) {
5219a5342   Steffen Klassert   crypto: user - Fi...
462
463
  		struct crypto_alg *alg;
  		u16 dump_alloc = 0;
a38f7907b   Steffen Klassert   crypto: Add users...
464
465
  		if (link->dump == NULL)
  			return -EINVAL;
5219a5342   Steffen Klassert   crypto: user - Fi...
466

63e41ebc6   Mathias Krause   crypto: user - lo...
467
  		down_read(&crypto_alg_sem);
5219a5342   Steffen Klassert   crypto: user - Fi...
468
469
  		list_for_each_entry(alg, &crypto_alg_list, cra_list)
  			dump_alloc += CRYPTO_REPORT_MAXSIZE;
80d326fab   Pablo Neira Ayuso   netlink: add netl...
470
471
472
473
  		{
  			struct netlink_dump_control c = {
  				.dump = link->dump,
  				.done = link->done,
5219a5342   Steffen Klassert   crypto: user - Fi...
474
  				.min_dump_alloc = dump_alloc,
80d326fab   Pablo Neira Ayuso   netlink: add netl...
475
  			};
63e41ebc6   Mathias Krause   crypto: user - lo...
476
  			err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
80d326fab   Pablo Neira Ayuso   netlink: add netl...
477
  		}
63e41ebc6   Mathias Krause   crypto: user - lo...
478
479
480
  		up_read(&crypto_alg_sem);
  
  		return err;
a38f7907b   Steffen Klassert   crypto: Add users...
481
  	}
fd2efd93b   Herbert Xu   Revert "crypto: u...
482
  	err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
fe52145f9   Johannes Berg   netlink: pass ext...
483
  			  crypto_policy, extack);
fd2efd93b   Herbert Xu   Revert "crypto: u...
484
485
  	if (err < 0)
  		return err;
a38f7907b   Steffen Klassert   crypto: Add users...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
  
  	if (link->doit == NULL)
  		return -EINVAL;
  
  	return link->doit(skb, nlh, attrs);
  }
  
  static void crypto_netlink_rcv(struct sk_buff *skb)
  {
  	mutex_lock(&crypto_cfg_mutex);
  	netlink_rcv_skb(skb, &crypto_user_rcv_msg);
  	mutex_unlock(&crypto_cfg_mutex);
  }
  
  static int __init crypto_user_init(void)
  {
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
502
503
504
  	struct netlink_kernel_cfg cfg = {
  		.input	= crypto_netlink_rcv,
  	};
9f00d9776   Pablo Neira Ayuso   netlink: hide str...
505
  	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO, &cfg);
a38f7907b   Steffen Klassert   crypto: Add users...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
  	if (!crypto_nlsk)
  		return -ENOMEM;
  
  	return 0;
  }
  
  static void __exit crypto_user_exit(void)
  {
  	netlink_kernel_release(crypto_nlsk);
  }
  
  module_init(crypto_user_init);
  module_exit(crypto_user_exit);
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
  MODULE_DESCRIPTION("Crypto userspace configuration API");
476c7fe20   Stephan Mueller   crypto: user - ad...
522
  MODULE_ALIAS("net-pf-16-proto-21");