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;
fdc427442   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;
fdc427442   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;
fdc427442   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;
fdc427442   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;
fdc427442   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)
  {
fdc427442   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));
fdc427442   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
156
  	ualg->cru_flags = alg->cra_flags;
  	ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
6662df33f   David S. Miller   crypto: Stop usin...
157
158
  	if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
  		goto nla_put_failure;
6c5a86f52   Steffen Klassert   crypto: Add users...
159
160
  	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
  		struct crypto_report_larval rl;
fdc427442   Eric Biggers   crypto: user - fi...
161
  		strncpy(rl.type, "larval", sizeof(rl.type));
6662df33f   David S. Miller   crypto: Stop usin...
162
163
164
  		if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
  			    sizeof(struct crypto_report_larval), &rl))
  			goto nla_put_failure;
6c5a86f52   Steffen Klassert   crypto: Add users...
165
166
  		goto out;
  	}
b6aa63c09   Steffen Klassert   crypto: Add a rep...
167
168
169
  	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...
170
171
172
173
174
175
176
177
178
179
  
  		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...
180
181
182
183
184
  	case CRYPTO_ALG_TYPE_COMPRESS:
  		if (crypto_report_comp(skb, alg))
  			goto nla_put_failure;
  
  		break;
2ebda74fd   Giovanni Cabiddu   crypto: acomp - a...
185
186
187
  	case CRYPTO_ALG_TYPE_ACOMPRESS:
  		if (crypto_report_acomp(skb, alg))
  			goto nla_put_failure;
3c339ab83   Tadeusz Struk   crypto: akcipher ...
188

2ebda74fd   Giovanni Cabiddu   crypto: acomp - a...
189
  		break;
3c339ab83   Tadeusz Struk   crypto: akcipher ...
190
191
192
193
194
  	case CRYPTO_ALG_TYPE_AKCIPHER:
  		if (crypto_report_akcipher(skb, alg))
  			goto nla_put_failure;
  
  		break;
4e5f2c400   Salvatore Benedetto   crypto: kpp - Key...
195
196
197
198
  	case CRYPTO_ALG_TYPE_KPP:
  		if (crypto_report_kpp(skb, alg))
  			goto nla_put_failure;
  		break;
b6aa63c09   Steffen Klassert   crypto: Add a rep...
199
  	}
6c5a86f52   Steffen Klassert   crypto: Add users...
200
  out:
a38f7907b   Steffen Klassert   crypto: Add users...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  	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...
215
  	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
a38f7907b   Steffen Klassert   crypto: Add users...
216
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
  			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...
244
245
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
5d4a5e770   Herbert Xu   crypto: user - Al...
246
  	alg = crypto_alg_match(p, 0);
a38f7907b   Steffen Klassert   crypto: Add users...
247
248
  	if (!alg)
  		return -ENOENT;
016baaa11   Herbert Xu   crypto: user - Fi...
249
  	err = -ENOMEM;
a38f7907b   Steffen Klassert   crypto: Add users...
250
251
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  	if (!skb)
016baaa11   Herbert Xu   crypto: user - Fi...
252
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
253
254
255
256
257
258
259
  
  	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...
260
261
262
  
  drop_alg:
  	crypto_mod_put(alg);
a38f7907b   Steffen Klassert   crypto: Add users...
263
264
  	if (err)
  		return err;
15e473046   Eric W. Biederman   netlink: Rename p...
265
  	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
a38f7907b   Steffen Klassert   crypto: Add users...
266
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
  }
  
  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...
308
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
c568398aa   Matthias-Christian Ott   crypto: user - Al...
309
  		return -EPERM;
8fd61d342   Mathias Krause   crypto: user - en...
310
311
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  	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...
327
  	crypto_mod_put(alg);
a38f7907b   Steffen Klassert   crypto: Add users...
328
329
330
331
332
333
334
335
336
337
  	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...
338
  	int err;
a38f7907b   Steffen Klassert   crypto: Add users...
339

639b4ac69   Linus Torvalds   Merge git://git.k...
340
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
c568398aa   Matthias-Christian Ott   crypto: user - Al...
341
  		return -EPERM;
8fd61d342   Mathias Krause   crypto: user - en...
342
343
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
344
345
346
347
348
349
350
351
352
  	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...
353
  	err = -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
354
  	if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
016baaa11   Herbert Xu   crypto: user - Fi...
355
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
356

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

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

63e41ebc6   Mathias Krause   crypto: user - lo...
466
  		down_read(&crypto_alg_sem);
5219a5342   Steffen Klassert   crypto: user - Fi...
467
468
  		list_for_each_entry(alg, &crypto_alg_list, cra_list)
  			dump_alloc += CRYPTO_REPORT_MAXSIZE;
80d326fab   Pablo Neira Ayuso   netlink: add netl...
469
470
471
472
  		{
  			struct netlink_dump_control c = {
  				.dump = link->dump,
  				.done = link->done,
5219a5342   Steffen Klassert   crypto: user - Fi...
473
  				.min_dump_alloc = dump_alloc,
80d326fab   Pablo Neira Ayuso   netlink: add netl...
474
  			};
63e41ebc6   Mathias Krause   crypto: user - lo...
475
  			err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
80d326fab   Pablo Neira Ayuso   netlink: add netl...
476
  		}
63e41ebc6   Mathias Krause   crypto: user - lo...
477
478
479
  		up_read(&crypto_alg_sem);
  
  		return err;
a38f7907b   Steffen Klassert   crypto: Add users...
480
  	}
fd2efd93b   Herbert Xu   Revert "crypto: u...
481
  	err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
fe52145f9   Johannes Berg   netlink: pass ext...
482
  			  crypto_policy, extack);
fd2efd93b   Herbert Xu   Revert "crypto: u...
483
484
  	if (err < 0)
  		return err;
a38f7907b   Steffen Klassert   crypto: Add users...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  
  	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...
501
502
503
  	struct netlink_kernel_cfg cfg = {
  		.input	= crypto_netlink_rcv,
  	};
9f00d9776   Pablo Neira Ayuso   netlink: hide str...
504
  	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO, &cfg);
a38f7907b   Steffen Klassert   crypto: Add users...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
  	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...
521
  MODULE_ALIAS("net-pf-16-proto-21");