Blame view

crypto/crypto_user.c 12.6 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;
9a5467bf7   Mathias Krause   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;
9a5467bf7   Mathias Krause   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;
  }
3c339ab83   Tadeusz Struk   crypto: akcipher ...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_akcipher rakcipher;
  
  	strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
  
  	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...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_kpp rkpp;
  
  	strncpy(rkpp.type, "kpp", sizeof(rkpp.type));
  
  	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...
133
134
135
  static int crypto_report_one(struct crypto_alg *alg,
  			     struct crypto_user_alg *ualg, struct sk_buff *skb)
  {
9a5467bf7   Mathias Krause   crypto: user - fi...
136
137
138
139
140
141
142
143
  	strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
  	strncpy(ualg->cru_driver_name, alg->cra_driver_name,
  		sizeof(ualg->cru_driver_name));
  	strncpy(ualg->cru_module_name, module_name(alg->cra_module),
  		sizeof(ualg->cru_module_name));
  
  	ualg->cru_type = 0;
  	ualg->cru_mask = 0;
a38f7907b   Steffen Klassert   crypto: Add users...
144
145
  	ualg->cru_flags = alg->cra_flags;
  	ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
6662df33f   David S. Miller   crypto: Stop usin...
146
147
  	if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
  		goto nla_put_failure;
6c5a86f52   Steffen Klassert   crypto: Add users...
148
149
  	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
  		struct crypto_report_larval rl;
9a5467bf7   Mathias Krause   crypto: user - fi...
150
  		strncpy(rl.type, "larval", sizeof(rl.type));
6662df33f   David S. Miller   crypto: Stop usin...
151
152
153
  		if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
  			    sizeof(struct crypto_report_larval), &rl))
  			goto nla_put_failure;
6c5a86f52   Steffen Klassert   crypto: Add users...
154
155
  		goto out;
  	}
b6aa63c09   Steffen Klassert   crypto: Add a rep...
156
157
158
  	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...
159
160
161
162
163
164
165
166
167
168
  
  		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...
169
170
171
172
173
  	case CRYPTO_ALG_TYPE_COMPRESS:
  		if (crypto_report_comp(skb, alg))
  			goto nla_put_failure;
  
  		break;
3c339ab83   Tadeusz Struk   crypto: akcipher ...
174
175
176
177
178
179
  
  	case CRYPTO_ALG_TYPE_AKCIPHER:
  		if (crypto_report_akcipher(skb, alg))
  			goto nla_put_failure;
  
  		break;
4e5f2c400   Salvatore Benedetto   crypto: kpp - Key...
180
181
182
183
  	case CRYPTO_ALG_TYPE_KPP:
  		if (crypto_report_kpp(skb, alg))
  			goto nla_put_failure;
  		break;
b6aa63c09   Steffen Klassert   crypto: Add a rep...
184
  	}
6c5a86f52   Steffen Klassert   crypto: Add users...
185
  out:
a38f7907b   Steffen Klassert   crypto: Add users...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  	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...
200
  	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
a38f7907b   Steffen Klassert   crypto: Add users...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  			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...
229
230
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
5d4a5e770   Herbert Xu   crypto: user - Al...
231
  	alg = crypto_alg_match(p, 0);
a38f7907b   Steffen Klassert   crypto: Add users...
232
233
  	if (!alg)
  		return -ENOENT;
016baaa11   Herbert Xu   crypto: user - Fi...
234
  	err = -ENOMEM;
a38f7907b   Steffen Klassert   crypto: Add users...
235
236
  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  	if (!skb)
016baaa11   Herbert Xu   crypto: user - Fi...
237
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
238
239
240
241
242
243
244
  
  	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...
245
246
247
  
  drop_alg:
  	crypto_mod_put(alg);
a38f7907b   Steffen Klassert   crypto: Add users...
248
249
  	if (err)
  		return err;
15e473046   Eric W. Biederman   netlink: Rename p...
250
  	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
a38f7907b   Steffen Klassert   crypto: Add users...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
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
  }
  
  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...
293
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
c568398aa   Matthias-Christian Ott   crypto: user - Al...
294
  		return -EPERM;
8fd61d342   Mathias Krause   crypto: user - en...
295
296
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  	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...
312
  	crypto_mod_put(alg);
a38f7907b   Steffen Klassert   crypto: Add users...
313
314
315
316
317
318
319
320
321
322
  	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...
323
  	int err;
a38f7907b   Steffen Klassert   crypto: Add users...
324

639b4ac69   Linus Torvalds   Merge git://git.k...
325
  	if (!netlink_capable(skb, CAP_NET_ADMIN))
c568398aa   Matthias-Christian Ott   crypto: user - Al...
326
  		return -EPERM;
8fd61d342   Mathias Krause   crypto: user - en...
327
328
  	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  		return -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
329
330
331
332
333
334
335
336
337
  	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...
338
  	err = -EINVAL;
a38f7907b   Steffen Klassert   crypto: Add users...
339
  	if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
016baaa11   Herbert Xu   crypto: user - Fi...
340
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
341

016baaa11   Herbert Xu   crypto: user - Fi...
342
343
344
  	err = -EBUSY;
  	if (atomic_read(&alg->cra_refcnt) > 2)
  		goto drop_alg;
a38f7907b   Steffen Klassert   crypto: Add users...
345

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

63e41ebc6   Mathias Krause   crypto: user - lo...
451
  		down_read(&crypto_alg_sem);
5219a5342   Steffen Klassert   crypto: user - Fi...
452
453
  		list_for_each_entry(alg, &crypto_alg_list, cra_list)
  			dump_alloc += CRYPTO_REPORT_MAXSIZE;
80d326fab   Pablo Neira Ayuso   netlink: add netl...
454
455
456
457
  		{
  			struct netlink_dump_control c = {
  				.dump = link->dump,
  				.done = link->done,
5219a5342   Steffen Klassert   crypto: user - Fi...
458
  				.min_dump_alloc = dump_alloc,
80d326fab   Pablo Neira Ayuso   netlink: add netl...
459
  			};
63e41ebc6   Mathias Krause   crypto: user - lo...
460
  			err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
80d326fab   Pablo Neira Ayuso   netlink: add netl...
461
  		}
63e41ebc6   Mathias Krause   crypto: user - lo...
462
463
464
  		up_read(&crypto_alg_sem);
  
  		return err;
a38f7907b   Steffen Klassert   crypto: Add users...
465
  	}
fd2efd93b   Herbert Xu   Revert "crypto: u...
466
467
468
469
  	err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
  			  crypto_policy);
  	if (err < 0)
  		return err;
a38f7907b   Steffen Klassert   crypto: Add users...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
  
  	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...
486
487
488
  	struct netlink_kernel_cfg cfg = {
  		.input	= crypto_netlink_rcv,
  	};
9f00d9776   Pablo Neira Ayuso   netlink: hide str...
489
  	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO, &cfg);
a38f7907b   Steffen Klassert   crypto: Add users...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  	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...
506
  MODULE_ALIAS("net-pf-16-proto-21");