]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - crypto/algapi.c
crypto: user - rename err_cnt parameter
[mirror_ubuntu-hirsute-kernel.git] / crypto / algapi.c
CommitLineData
cce9e06d
HX
1/*
2 * Cryptographic API for algorithms (i.e., low-level API).
3 *
4 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 */
12
13c935bb 13#include <crypto/algapi.h>
6bfd4809 14#include <linux/err.h>
cce9e06d 15#include <linux/errno.h>
3133d76f 16#include <linux/fips.h>
cce9e06d
HX
17#include <linux/init.h>
18#include <linux/kernel.h>
4cc7720c 19#include <linux/list.h>
cce9e06d 20#include <linux/module.h>
7fed0bf2 21#include <linux/rtnetlink.h>
5a0e3ad6 22#include <linux/slab.h>
cce9e06d
HX
23#include <linux/string.h>
24
25#include "internal.h"
26
4cc7720c
HX
27static LIST_HEAD(crypto_template_list);
28
cce9e06d
HX
29static inline int crypto_set_driver_name(struct crypto_alg *alg)
30{
31 static const char suffix[] = "-generic";
32 char *driver_name = alg->cra_driver_name;
33 int len;
34
35 if (*driver_name)
36 return 0;
37
38 len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
39 if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
40 return -ENAMETOOLONG;
41
42 memcpy(driver_name + len, suffix, sizeof(suffix));
43 return 0;
44}
45
002c77a4
JW
46static inline void crypto_check_module_sig(struct module *mod)
47{
59afdc7b 48 if (fips_enabled && mod && !module_sig_ok(mod))
002c77a4 49 panic("Module %s signature verification failed in FIPS mode\n",
bd4a7c69 50 module_name(mod));
002c77a4
JW
51}
52
4cc7720c 53static int crypto_check_alg(struct crypto_alg *alg)
cce9e06d 54{
002c77a4
JW
55 crypto_check_module_sig(alg->cra_module);
56
cce9e06d
HX
57 if (alg->cra_alignmask & (alg->cra_alignmask + 1))
58 return -EINVAL;
59
a9f7f88a
KC
60 /* General maximums for all algs. */
61 if (alg->cra_alignmask > MAX_ALGAPI_ALIGNMASK)
cce9e06d
HX
62 return -EINVAL;
63
a9f7f88a
KC
64 if (alg->cra_blocksize > MAX_ALGAPI_BLOCKSIZE)
65 return -EINVAL;
66
67 /* Lower maximums for specific alg types. */
13c935bb
SM
68 if (!alg->cra_type && (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
69 CRYPTO_ALG_TYPE_CIPHER) {
70 if (alg->cra_alignmask > MAX_CIPHER_ALIGNMASK)
71 return -EINVAL;
72
73 if (alg->cra_blocksize > MAX_CIPHER_BLOCKSIZE)
74 return -EINVAL;
75 }
76
cce9e06d
HX
77 if (alg->cra_priority < 0)
78 return -EINVAL;
cce9e06d 79
ce8614a3 80 refcount_set(&alg->cra_refcnt, 1);
e9b8e5be 81
4cc7720c
HX
82 return crypto_set_driver_name(alg);
83}
84
319382a6
HX
85static void crypto_free_instance(struct crypto_instance *inst)
86{
87 if (!inst->alg.cra_type->free) {
88 inst->tmpl->free(inst);
89 return;
90 }
91
92 inst->alg.cra_type->free(inst);
93}
94
6bfd4809
HX
95static void crypto_destroy_instance(struct crypto_alg *alg)
96{
97 struct crypto_instance *inst = (void *)alg;
98 struct crypto_template *tmpl = inst->tmpl;
99
319382a6 100 crypto_free_instance(inst);
6bfd4809
HX
101 crypto_tmpl_put(tmpl);
102}
103
2bf29016
HX
104static struct list_head *crypto_more_spawns(struct crypto_alg *alg,
105 struct list_head *stack,
106 struct list_head *top,
107 struct list_head *secondary_spawns)
108{
109 struct crypto_spawn *spawn, *n;
110
304e4818
GT
111 spawn = list_first_entry_or_null(stack, struct crypto_spawn, list);
112 if (!spawn)
2bf29016
HX
113 return NULL;
114
304e4818 115 n = list_next_entry(spawn, list);
2bf29016
HX
116
117 if (spawn->alg && &n->list != stack && !n->alg)
118 n->alg = (n->list.next == stack) ? alg :
304e4818 119 &list_next_entry(n, list)->inst->alg;
2bf29016
HX
120
121 list_move(&spawn->list, secondary_spawns);
122
123 return &n->list == stack ? top : &n->inst->alg.cra_users;
124}
125
1f723710
HX
126static void crypto_remove_instance(struct crypto_instance *inst,
127 struct list_head *list)
6bfd4809 128{
a73e6996 129 struct crypto_template *tmpl = inst->tmpl;
6bfd4809 130
a73e6996
HX
131 if (crypto_is_dead(&inst->alg))
132 return;
6bfd4809 133
a73e6996 134 inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
38cb2419
HX
135 if (hlist_unhashed(&inst->list))
136 return;
137
a73e6996
HX
138 if (!tmpl || !crypto_tmpl_get(tmpl))
139 return;
140
a73e6996
HX
141 list_move(&inst->alg.cra_list, list);
142 hlist_del(&inst->list);
143 inst->alg.cra_destroy = crypto_destroy_instance;
144
2bf29016 145 BUG_ON(!list_empty(&inst->alg.cra_users));
a73e6996
HX
146}
147
89b596ba
SK
148void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
149 struct crypto_alg *nalg)
a73e6996 150{
2bf29016 151 u32 new_type = (nalg ?: alg)->cra_flags;
a73e6996
HX
152 struct crypto_spawn *spawn, *n;
153 LIST_HEAD(secondary_spawns);
2bf29016
HX
154 struct list_head *spawns;
155 LIST_HEAD(stack);
156 LIST_HEAD(top);
6bfd4809 157
2bf29016 158 spawns = &alg->cra_users;
a73e6996
HX
159 list_for_each_entry_safe(spawn, n, spawns, list) {
160 if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
6bfd4809
HX
161 continue;
162
2bf29016 163 list_move(&spawn->list, &top);
a73e6996 164 }
6bfd4809 165
2bf29016
HX
166 spawns = &top;
167 do {
168 while (!list_empty(spawns)) {
169 struct crypto_instance *inst;
170
171 spawn = list_first_entry(spawns, struct crypto_spawn,
172 list);
173 inst = spawn->inst;
174
175 BUG_ON(&inst->alg == alg);
176
177 list_move(&spawn->list, &stack);
178
179 if (&inst->alg == nalg)
180 break;
181
182 spawn->alg = NULL;
183 spawns = &inst->alg.cra_users;
9a006742
EB
184
185 /*
186 * We may encounter an unregistered instance here, since
187 * an instance's spawns are set up prior to the instance
188 * being registered. An unregistered instance will have
189 * NULL ->cra_users.next, since ->cra_users isn't
190 * properly initialized until registration. But an
191 * unregistered instance cannot have any users, so treat
192 * it the same as ->cra_users being empty.
193 */
194 if (spawns->next == NULL)
195 break;
2bf29016
HX
196 }
197 } while ((spawns = crypto_more_spawns(alg, &stack, &top,
198 &secondary_spawns)));
199
200 list_for_each_entry_safe(spawn, n, &secondary_spawns, list) {
201 if (spawn->alg)
202 list_move(&spawn->list, &spawn->alg->cra_users);
203 else
1f723710 204 crypto_remove_instance(spawn->inst, list);
6bfd4809
HX
205 }
206}
89b596ba 207EXPORT_SYMBOL_GPL(crypto_remove_spawns);
6bfd4809 208
73d3864a 209static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
4cc7720c
HX
210{
211 struct crypto_alg *q;
73d3864a 212 struct crypto_larval *larval;
6bfd4809
HX
213 int ret = -EAGAIN;
214
215 if (crypto_is_dead(alg))
73d3864a 216 goto err;
6bfd4809
HX
217
218 INIT_LIST_HEAD(&alg->cra_users);
219
73d3864a
HX
220 /* No cheating! */
221 alg->cra_flags &= ~CRYPTO_ALG_TESTED;
222
6bfd4809 223 ret = -EEXIST;
4cc7720c 224
cce9e06d 225 list_for_each_entry(q, &crypto_alg_list, cra_list) {
4cc7720c 226 if (q == alg)
73d3864a
HX
227 goto err;
228
b8e15992
HX
229 if (crypto_is_moribund(q))
230 continue;
231
73d3864a
HX
232 if (crypto_is_larval(q)) {
233 if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
234 goto err;
235 continue;
236 }
237
238 if (!strcmp(q->cra_driver_name, alg->cra_name) ||
239 !strcmp(q->cra_name, alg->cra_driver_name))
240 goto err;
241 }
242
243 larval = crypto_larval_alloc(alg->cra_name,
244 alg->cra_flags | CRYPTO_ALG_TESTED, 0);
245 if (IS_ERR(larval))
246 goto out;
247
248 ret = -ENOENT;
249 larval->adult = crypto_mod_get(alg);
250 if (!larval->adult)
251 goto free_larval;
252
ce8614a3 253 refcount_set(&larval->alg.cra_refcnt, 1);
73d3864a
HX
254 memcpy(larval->alg.cra_driver_name, alg->cra_driver_name,
255 CRYPTO_MAX_ALG_NAME);
256 larval->alg.cra_priority = alg->cra_priority;
257
258 list_add(&alg->cra_list, &crypto_alg_list);
259 list_add(&larval->alg.cra_list, &crypto_alg_list);
260
2ced2607 261#ifdef CONFIG_CRYPTO_STATS
17c18f9e 262 memset(&alg->stats, 0, sizeof(alg->stats));
2ced2607 263#endif
cac5818c 264
5357c6c4 265out:
73d3864a
HX
266 return larval;
267
268free_larval:
269 kfree(larval);
270err:
271 larval = ERR_PTR(ret);
272 goto out;
273}
274
275void crypto_alg_tested(const char *name, int err)
276{
277 struct crypto_larval *test;
278 struct crypto_alg *alg;
279 struct crypto_alg *q;
280 LIST_HEAD(list);
281
282 down_write(&crypto_alg_sem);
283 list_for_each_entry(q, &crypto_alg_list, cra_list) {
b8e15992 284 if (crypto_is_moribund(q) || !crypto_is_larval(q))
73d3864a
HX
285 continue;
286
287 test = (struct crypto_larval *)q;
288
289 if (!strcmp(q->cra_driver_name, name))
290 goto found;
291 }
292
c7235857 293 pr_err("alg: Unexpected test result for %s: %d\n", name, err);
73d3864a
HX
294 goto unlock;
295
296found:
b8e15992 297 q->cra_flags |= CRYPTO_ALG_DEAD;
73d3864a
HX
298 alg = test->adult;
299 if (err || list_empty(&alg->cra_list))
300 goto complete;
301
302 alg->cra_flags |= CRYPTO_ALG_TESTED;
303
304 list_for_each_entry(q, &crypto_alg_list, cra_list) {
305 if (q == alg)
306 continue;
6bfd4809
HX
307
308 if (crypto_is_moribund(q))
309 continue;
310
311 if (crypto_is_larval(q)) {
2825982d
HX
312 struct crypto_larval *larval = (void *)q;
313
d8058480
HX
314 /*
315 * Check to see if either our generic name or
316 * specific name can satisfy the name requested
317 * by the larval entry q.
318 */
6bfd4809
HX
319 if (strcmp(alg->cra_name, q->cra_name) &&
320 strcmp(alg->cra_driver_name, q->cra_name))
321 continue;
322
323 if (larval->adult)
324 continue;
492e2b63
HX
325 if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
326 continue;
2825982d
HX
327 if (!crypto_mod_get(alg))
328 continue;
6bfd4809 329
2825982d 330 larval->adult = alg;
6bfd4809 331 continue;
2825982d 332 }
6bfd4809
HX
333
334 if (strcmp(alg->cra_name, q->cra_name))
335 continue;
336
337 if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
338 q->cra_priority > alg->cra_priority)
339 continue;
340
2bf29016 341 crypto_remove_spawns(q, &list, alg);
cce9e06d 342 }
2825982d 343
73d3864a
HX
344complete:
345 complete_all(&test->completion);
2825982d 346
73d3864a
HX
347unlock:
348 up_write(&crypto_alg_sem);
349
350 crypto_remove_final(&list);
cce9e06d 351}
73d3864a 352EXPORT_SYMBOL_GPL(crypto_alg_tested);
4cc7720c 353
22e5b20b 354void crypto_remove_final(struct list_head *list)
6bfd4809
HX
355{
356 struct crypto_alg *alg;
357 struct crypto_alg *n;
358
359 list_for_each_entry_safe(alg, n, list, cra_list) {
360 list_del_init(&alg->cra_list);
361 crypto_alg_put(alg);
362 }
363}
22e5b20b 364EXPORT_SYMBOL_GPL(crypto_remove_final);
6bfd4809 365
73d3864a
HX
366static void crypto_wait_for_test(struct crypto_larval *larval)
367{
368 int err;
369
370 err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
371 if (err != NOTIFY_STOP) {
372 if (WARN_ON(err != NOTIFY_DONE))
373 goto out;
374 crypto_alg_tested(larval->alg.cra_driver_name, 0);
375 }
376
3fc89adb 377 err = wait_for_completion_killable(&larval->completion);
73d3864a 378 WARN_ON(err);
dd8b083f
MP
379 if (!err)
380 crypto_probing_notify(CRYPTO_MSG_ALG_LOADED, larval);
73d3864a
HX
381
382out:
383 crypto_larval_kill(&larval->alg);
384}
385
4cc7720c
HX
386int crypto_register_alg(struct crypto_alg *alg)
387{
73d3864a 388 struct crypto_larval *larval;
4cc7720c
HX
389 int err;
390
d6040764 391 alg->cra_flags &= ~CRYPTO_ALG_DEAD;
4cc7720c
HX
392 err = crypto_check_alg(alg);
393 if (err)
394 return err;
395
396 down_write(&crypto_alg_sem);
73d3864a 397 larval = __crypto_register_alg(alg);
4cc7720c
HX
398 up_write(&crypto_alg_sem);
399
73d3864a
HX
400 if (IS_ERR(larval))
401 return PTR_ERR(larval);
402
403 crypto_wait_for_test(larval);
404 return 0;
4cc7720c 405}
cce9e06d
HX
406EXPORT_SYMBOL_GPL(crypto_register_alg);
407
6bfd4809
HX
408static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
409{
410 if (unlikely(list_empty(&alg->cra_list)))
411 return -ENOENT;
412
413 alg->cra_flags |= CRYPTO_ALG_DEAD;
414
6bfd4809 415 list_del_init(&alg->cra_list);
2bf29016 416 crypto_remove_spawns(alg, list, NULL);
6bfd4809
HX
417
418 return 0;
419}
420
cce9e06d
HX
421int crypto_unregister_alg(struct crypto_alg *alg)
422{
6bfd4809
HX
423 int ret;
424 LIST_HEAD(list);
5357c6c4 425
cce9e06d 426 down_write(&crypto_alg_sem);
6bfd4809 427 ret = crypto_remove_alg(alg, &list);
cce9e06d
HX
428 up_write(&crypto_alg_sem);
429
430 if (ret)
431 return ret;
432
ce8614a3 433 BUG_ON(refcount_read(&alg->cra_refcnt) != 1);
cce9e06d
HX
434 if (alg->cra_destroy)
435 alg->cra_destroy(alg);
436
6bfd4809 437 crypto_remove_final(&list);
cce9e06d
HX
438 return 0;
439}
440EXPORT_SYMBOL_GPL(crypto_unregister_alg);
441
4b004346
MB
442int crypto_register_algs(struct crypto_alg *algs, int count)
443{
444 int i, ret;
445
446 for (i = 0; i < count; i++) {
447 ret = crypto_register_alg(&algs[i]);
448 if (ret)
449 goto err;
450 }
451
452 return 0;
453
454err:
455 for (--i; i >= 0; --i)
456 crypto_unregister_alg(&algs[i]);
457
458 return ret;
459}
460EXPORT_SYMBOL_GPL(crypto_register_algs);
461
462int crypto_unregister_algs(struct crypto_alg *algs, int count)
463{
464 int i, ret;
465
466 for (i = 0; i < count; i++) {
467 ret = crypto_unregister_alg(&algs[i]);
468 if (ret)
469 pr_err("Failed to unregister %s %s: %d\n",
470 algs[i].cra_driver_name, algs[i].cra_name, ret);
471 }
472
473 return 0;
474}
475EXPORT_SYMBOL_GPL(crypto_unregister_algs);
476
4cc7720c
HX
477int crypto_register_template(struct crypto_template *tmpl)
478{
479 struct crypto_template *q;
480 int err = -EEXIST;
481
482 down_write(&crypto_alg_sem);
483
002c77a4
JW
484 crypto_check_module_sig(tmpl->module);
485
4cc7720c
HX
486 list_for_each_entry(q, &crypto_template_list, list) {
487 if (q == tmpl)
488 goto out;
489 }
490
491 list_add(&tmpl->list, &crypto_template_list);
492 err = 0;
493out:
494 up_write(&crypto_alg_sem);
495 return err;
496}
497EXPORT_SYMBOL_GPL(crypto_register_template);
498
499void crypto_unregister_template(struct crypto_template *tmpl)
500{
501 struct crypto_instance *inst;
b67bfe0d 502 struct hlist_node *n;
4cc7720c 503 struct hlist_head *list;
6bfd4809 504 LIST_HEAD(users);
4cc7720c
HX
505
506 down_write(&crypto_alg_sem);
507
508 BUG_ON(list_empty(&tmpl->list));
509 list_del_init(&tmpl->list);
510
511 list = &tmpl->instances;
b67bfe0d 512 hlist_for_each_entry(inst, list, list) {
6bfd4809 513 int err = crypto_remove_alg(&inst->alg, &users);
0efcb8d5 514
6bfd4809 515 BUG_ON(err);
4cc7720c
HX
516 }
517
518 up_write(&crypto_alg_sem);
519
b67bfe0d 520 hlist_for_each_entry_safe(inst, n, list, list) {
ce8614a3 521 BUG_ON(refcount_read(&inst->alg.cra_refcnt) != 1);
319382a6 522 crypto_free_instance(inst);
4cc7720c 523 }
6bfd4809 524 crypto_remove_final(&users);
4cc7720c
HX
525}
526EXPORT_SYMBOL_GPL(crypto_unregister_template);
527
528static struct crypto_template *__crypto_lookup_template(const char *name)
529{
530 struct crypto_template *q, *tmpl = NULL;
531
532 down_read(&crypto_alg_sem);
533 list_for_each_entry(q, &crypto_template_list, list) {
534 if (strcmp(q->name, name))
535 continue;
536 if (unlikely(!crypto_tmpl_get(q)))
537 continue;
538
539 tmpl = q;
540 break;
541 }
542 up_read(&crypto_alg_sem);
543
544 return tmpl;
545}
546
547struct crypto_template *crypto_lookup_template(const char *name)
548{
4943ba16
KC
549 return try_then_request_module(__crypto_lookup_template(name),
550 "crypto-%s", name);
4cc7720c
HX
551}
552EXPORT_SYMBOL_GPL(crypto_lookup_template);
553
554int crypto_register_instance(struct crypto_template *tmpl,
555 struct crypto_instance *inst)
556{
73d3864a
HX
557 struct crypto_larval *larval;
558 int err;
4cc7720c 559
4cc7720c
HX
560 err = crypto_check_alg(&inst->alg);
561 if (err)
9c521a20
SM
562 return err;
563
4cc7720c 564 inst->alg.cra_module = tmpl->module;
64a947b1 565 inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
4cc7720c
HX
566
567 down_write(&crypto_alg_sem);
568
73d3864a
HX
569 larval = __crypto_register_alg(&inst->alg);
570 if (IS_ERR(larval))
4cc7720c
HX
571 goto unlock;
572
573 hlist_add_head(&inst->list, &tmpl->instances);
574 inst->tmpl = tmpl;
575
576unlock:
577 up_write(&crypto_alg_sem);
578
73d3864a
HX
579 err = PTR_ERR(larval);
580 if (IS_ERR(larval))
581 goto err;
582
583 crypto_wait_for_test(larval);
584 err = 0;
6bfd4809 585
4cc7720c
HX
586err:
587 return err;
588}
589EXPORT_SYMBOL_GPL(crypto_register_instance);
ce3fd840 590
87b16756 591int crypto_unregister_instance(struct crypto_instance *inst)
ce3fd840 592{
1f723710 593 LIST_HEAD(list);
ce3fd840 594
ce3fd840
SK
595 down_write(&crypto_alg_sem);
596
87b16756 597 crypto_remove_spawns(&inst->alg, &list, NULL);
1f723710 598 crypto_remove_instance(inst, &list);
ce3fd840
SK
599
600 up_write(&crypto_alg_sem);
601
1f723710 602 crypto_remove_final(&list);
ce3fd840
SK
603
604 return 0;
605}
606EXPORT_SYMBOL_GPL(crypto_unregister_instance);
4cc7720c 607
6bfd4809 608int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
a73e6996 609 struct crypto_instance *inst, u32 mask)
6bfd4809
HX
610{
611 int err = -EAGAIN;
612
613 spawn->inst = inst;
a73e6996 614 spawn->mask = mask;
6bfd4809
HX
615
616 down_write(&crypto_alg_sem);
617 if (!crypto_is_moribund(alg)) {
618 list_add(&spawn->list, &alg->cra_users);
619 spawn->alg = alg;
620 err = 0;
621 }
622 up_write(&crypto_alg_sem);
623
624 return err;
625}
626EXPORT_SYMBOL_GPL(crypto_init_spawn);
627
97eedce1
HX
628int crypto_init_spawn2(struct crypto_spawn *spawn, struct crypto_alg *alg,
629 struct crypto_instance *inst,
630 const struct crypto_type *frontend)
631{
632 int err = -EINVAL;
633
c614e109 634 if ((alg->cra_flags ^ frontend->type) & frontend->maskset)
97eedce1
HX
635 goto out;
636
637 spawn->frontend = frontend;
638 err = crypto_init_spawn(spawn, alg, inst, frontend->maskset);
639
640out:
641 return err;
642}
643EXPORT_SYMBOL_GPL(crypto_init_spawn2);
644
d6ef2f19
HX
645int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name,
646 u32 type, u32 mask)
647{
648 struct crypto_alg *alg;
649 int err;
650
651 alg = crypto_find_alg(name, spawn->frontend, type, mask);
652 if (IS_ERR(alg))
653 return PTR_ERR(alg);
654
655 err = crypto_init_spawn(spawn, alg, spawn->inst, mask);
656 crypto_mod_put(alg);
657 return err;
658}
659EXPORT_SYMBOL_GPL(crypto_grab_spawn);
660
6bfd4809
HX
661void crypto_drop_spawn(struct crypto_spawn *spawn)
662{
7ede5a5b
HX
663 if (!spawn->alg)
664 return;
665
6bfd4809
HX
666 down_write(&crypto_alg_sem);
667 list_del(&spawn->list);
668 up_write(&crypto_alg_sem);
669}
670EXPORT_SYMBOL_GPL(crypto_drop_spawn);
671
97eedce1 672static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
6bfd4809
HX
673{
674 struct crypto_alg *alg;
675 struct crypto_alg *alg2;
6bfd4809
HX
676
677 down_read(&crypto_alg_sem);
678 alg = spawn->alg;
679 alg2 = alg;
680 if (alg2)
681 alg2 = crypto_mod_get(alg2);
682 up_read(&crypto_alg_sem);
683
684 if (!alg2) {
685 if (alg)
686 crypto_shoot_alg(alg);
687 return ERR_PTR(-EAGAIN);
688 }
689
97eedce1
HX
690 return alg;
691}
692
693struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
694 u32 mask)
695{
696 struct crypto_alg *alg;
697 struct crypto_tfm *tfm;
698
699 alg = crypto_spawn_alg(spawn);
700 if (IS_ERR(alg))
701 return ERR_CAST(alg);
702
2e306ee0
HX
703 tfm = ERR_PTR(-EINVAL);
704 if (unlikely((alg->cra_flags ^ type) & mask))
705 goto out_put_alg;
706
27d2a330 707 tfm = __crypto_alloc_tfm(alg, type, mask);
6bfd4809 708 if (IS_ERR(tfm))
2e306ee0
HX
709 goto out_put_alg;
710
711 return tfm;
6bfd4809 712
2e306ee0
HX
713out_put_alg:
714 crypto_mod_put(alg);
6bfd4809
HX
715 return tfm;
716}
717EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
718
97eedce1
HX
719void *crypto_spawn_tfm2(struct crypto_spawn *spawn)
720{
721 struct crypto_alg *alg;
722 struct crypto_tfm *tfm;
723
724 alg = crypto_spawn_alg(spawn);
725 if (IS_ERR(alg))
726 return ERR_CAST(alg);
727
728 tfm = crypto_create_tfm(alg, spawn->frontend);
729 if (IS_ERR(tfm))
730 goto out_put_alg;
731
732 return tfm;
733
734out_put_alg:
735 crypto_mod_put(alg);
736 return tfm;
737}
738EXPORT_SYMBOL_GPL(crypto_spawn_tfm2);
739
2825982d
HX
740int crypto_register_notifier(struct notifier_block *nb)
741{
742 return blocking_notifier_chain_register(&crypto_chain, nb);
743}
744EXPORT_SYMBOL_GPL(crypto_register_notifier);
745
746int crypto_unregister_notifier(struct notifier_block *nb)
747{
748 return blocking_notifier_chain_unregister(&crypto_chain, nb);
749}
750EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
751
ebc610e5 752struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
7fed0bf2 753{
39e1ee01 754 struct rtattr *rta = tb[0];
ebc610e5
HX
755 struct crypto_attr_type *algt;
756
757 if (!rta)
758 return ERR_PTR(-ENOENT);
759 if (RTA_PAYLOAD(rta) < sizeof(*algt))
760 return ERR_PTR(-EINVAL);
39e1ee01
HX
761 if (rta->rta_type != CRYPTOA_TYPE)
762 return ERR_PTR(-EINVAL);
ebc610e5
HX
763
764 algt = RTA_DATA(rta);
765
766 return algt;
767}
768EXPORT_SYMBOL_GPL(crypto_get_attr_type);
769
770int crypto_check_attr_type(struct rtattr **tb, u32 type)
771{
772 struct crypto_attr_type *algt;
773
774 algt = crypto_get_attr_type(tb);
775 if (IS_ERR(algt))
776 return PTR_ERR(algt);
777
778 if ((algt->type ^ type) & algt->mask)
779 return -EINVAL;
780
781 return 0;
782}
783EXPORT_SYMBOL_GPL(crypto_check_attr_type);
784
68b6c7d6 785const char *crypto_attr_alg_name(struct rtattr *rta)
ebc610e5 786{
7fed0bf2
HX
787 struct crypto_attr_alg *alga;
788
ebc610e5
HX
789 if (!rta)
790 return ERR_PTR(-ENOENT);
791 if (RTA_PAYLOAD(rta) < sizeof(*alga))
7fed0bf2 792 return ERR_PTR(-EINVAL);
39e1ee01
HX
793 if (rta->rta_type != CRYPTOA_ALG)
794 return ERR_PTR(-EINVAL);
7fed0bf2
HX
795
796 alga = RTA_DATA(rta);
797 alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
798
68b6c7d6
HX
799 return alga->name;
800}
801EXPORT_SYMBOL_GPL(crypto_attr_alg_name);
802
d06854f0
HX
803struct crypto_alg *crypto_attr_alg2(struct rtattr *rta,
804 const struct crypto_type *frontend,
805 u32 type, u32 mask)
68b6c7d6
HX
806{
807 const char *name;
68b6c7d6
HX
808
809 name = crypto_attr_alg_name(rta);
68b6c7d6 810 if (IS_ERR(name))
3e8afe35 811 return ERR_CAST(name);
68b6c7d6 812
d06854f0 813 return crypto_find_alg(name, frontend, type, mask);
7fed0bf2 814}
d06854f0 815EXPORT_SYMBOL_GPL(crypto_attr_alg2);
3c09f17c
HX
816
817int crypto_attr_u32(struct rtattr *rta, u32 *num)
818{
819 struct crypto_attr_u32 *nu32;
820
821 if (!rta)
822 return -ENOENT;
823 if (RTA_PAYLOAD(rta) < sizeof(*nu32))
824 return -EINVAL;
825 if (rta->rta_type != CRYPTOA_U32)
826 return -EINVAL;
827
828 nu32 = RTA_DATA(rta);
829 *num = nu32->num;
830
831 return 0;
832}
833EXPORT_SYMBOL_GPL(crypto_attr_u32);
7fed0bf2 834
32f27c74
HX
835int crypto_inst_setname(struct crypto_instance *inst, const char *name,
836 struct crypto_alg *alg)
837{
838 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name,
839 alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
840 return -ENAMETOOLONG;
841
842 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
843 name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
844 return -ENAMETOOLONG;
845
846 return 0;
847}
848EXPORT_SYMBOL_GPL(crypto_inst_setname);
849
70ec7bb9
HX
850void *crypto_alloc_instance2(const char *name, struct crypto_alg *alg,
851 unsigned int head)
7fed0bf2
HX
852{
853 struct crypto_instance *inst;
70ec7bb9 854 char *p;
7fed0bf2
HX
855 int err;
856
70ec7bb9
HX
857 p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn),
858 GFP_KERNEL);
859 if (!p)
7fed0bf2
HX
860 return ERR_PTR(-ENOMEM);
861
70ec7bb9
HX
862 inst = (void *)(p + head);
863
32f27c74
HX
864 err = crypto_inst_setname(inst, name, alg);
865 if (err)
7fed0bf2
HX
866 goto err_free_inst;
867
70ec7bb9
HX
868 return p;
869
870err_free_inst:
871 kfree(p);
872 return ERR_PTR(err);
873}
874EXPORT_SYMBOL_GPL(crypto_alloc_instance2);
875
876struct crypto_instance *crypto_alloc_instance(const char *name,
877 struct crypto_alg *alg)
878{
879 struct crypto_instance *inst;
880 struct crypto_spawn *spawn;
881 int err;
882
883 inst = crypto_alloc_instance2(name, alg, 0);
884 if (IS_ERR(inst))
885 goto out;
886
7fed0bf2 887 spawn = crypto_instance_ctx(inst);
a73e6996
HX
888 err = crypto_init_spawn(spawn, alg, inst,
889 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
7fed0bf2
HX
890
891 if (err)
892 goto err_free_inst;
893
894 return inst;
895
896err_free_inst:
897 kfree(inst);
70ec7bb9
HX
898 inst = ERR_PTR(err);
899
900out:
901 return inst;
7fed0bf2
HX
902}
903EXPORT_SYMBOL_GPL(crypto_alloc_instance);
904
b5b7f088
HX
905void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen)
906{
907 INIT_LIST_HEAD(&queue->list);
908 queue->backlog = &queue->list;
909 queue->qlen = 0;
910 queue->max_qlen = max_qlen;
911}
912EXPORT_SYMBOL_GPL(crypto_init_queue);
913
914int crypto_enqueue_request(struct crypto_queue *queue,
915 struct crypto_async_request *request)
916{
917 int err = -EINPROGRESS;
918
919 if (unlikely(queue->qlen >= queue->max_qlen)) {
6b80ea38
GBY
920 if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
921 err = -ENOSPC;
b5b7f088 922 goto out;
6b80ea38
GBY
923 }
924 err = -EBUSY;
b5b7f088
HX
925 if (queue->backlog == &queue->list)
926 queue->backlog = &request->list;
927 }
928
929 queue->qlen++;
930 list_add_tail(&request->list, &queue->list);
931
932out:
933 return err;
934}
935EXPORT_SYMBOL_GPL(crypto_enqueue_request);
936
31d228cc 937struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
b5b7f088
HX
938{
939 struct list_head *request;
940
941 if (unlikely(!queue->qlen))
942 return NULL;
943
944 queue->qlen--;
945
946 if (queue->backlog != &queue->list)
947 queue->backlog = queue->backlog->next;
948
949 request = queue->list.next;
950 list_del(request);
951
31d228cc 952 return list_entry(request, struct crypto_async_request, list);
b5b7f088
HX
953}
954EXPORT_SYMBOL_GPL(crypto_dequeue_request);
955
956int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm)
957{
958 struct crypto_async_request *req;
959
960 list_for_each_entry(req, &queue->list, list) {
961 if (req->tfm == tfm)
962 return 1;
963 }
964
965 return 0;
966}
967EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);
968
7613636d
HX
969static inline void crypto_inc_byte(u8 *a, unsigned int size)
970{
971 u8 *b = (a + size);
972 u8 c;
973
974 for (; size; size--) {
975 c = *--b + 1;
976 *b = c;
977 if (c)
978 break;
979 }
980}
981
982void crypto_inc(u8 *a, unsigned int size)
983{
984 __be32 *b = (__be32 *)(a + size);
985 u32 c;
986
db91af0f 987 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
27c539ae 988 IS_ALIGNED((unsigned long)b, __alignof__(*b)))
db91af0f
AB
989 for (; size >= 4; size -= 4) {
990 c = be32_to_cpu(*--b) + 1;
991 *b = cpu_to_be32(c);
27c539ae 992 if (likely(c))
db91af0f
AB
993 return;
994 }
7613636d
HX
995
996 crypto_inc_byte(a, size);
997}
998EXPORT_SYMBOL_GPL(crypto_inc);
999
a7c391f0 1000void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int len)
7613636d 1001{
db91af0f
AB
1002 int relalign = 0;
1003
1004 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) {
1005 int size = sizeof(unsigned long);
a7c391f0
AB
1006 int d = (((unsigned long)dst ^ (unsigned long)src1) |
1007 ((unsigned long)dst ^ (unsigned long)src2)) &
1008 (size - 1);
db91af0f
AB
1009
1010 relalign = d ? 1 << __ffs(d) : size;
1011
1012 /*
1013 * If we care about alignment, process as many bytes as
1014 * needed to advance dst and src to values whose alignments
1015 * equal their relative alignment. This will allow us to
1016 * process the remainder of the input using optimal strides.
1017 */
1018 while (((unsigned long)dst & (relalign - 1)) && len > 0) {
a7c391f0 1019 *dst++ = *src1++ ^ *src2++;
db91af0f
AB
1020 len--;
1021 }
1022 }
7613636d 1023
db91af0f 1024 while (IS_ENABLED(CONFIG_64BIT) && len >= 8 && !(relalign & 7)) {
a7c391f0 1025 *(u64 *)dst = *(u64 *)src1 ^ *(u64 *)src2;
db91af0f 1026 dst += 8;
a7c391f0
AB
1027 src1 += 8;
1028 src2 += 8;
db91af0f
AB
1029 len -= 8;
1030 }
7613636d 1031
db91af0f 1032 while (len >= 4 && !(relalign & 3)) {
a7c391f0 1033 *(u32 *)dst = *(u32 *)src1 ^ *(u32 *)src2;
db91af0f 1034 dst += 4;
a7c391f0
AB
1035 src1 += 4;
1036 src2 += 4;
db91af0f
AB
1037 len -= 4;
1038 }
1039
1040 while (len >= 2 && !(relalign & 1)) {
a7c391f0 1041 *(u16 *)dst = *(u16 *)src1 ^ *(u16 *)src2;
db91af0f 1042 dst += 2;
a7c391f0
AB
1043 src1 += 2;
1044 src2 += 2;
db91af0f
AB
1045 len -= 2;
1046 }
7613636d 1047
db91af0f 1048 while (len--)
a7c391f0 1049 *dst++ = *src1++ ^ *src2++;
7613636d 1050}
db91af0f 1051EXPORT_SYMBOL_GPL(__crypto_xor);
7613636d 1052
38d21433
HX
1053unsigned int crypto_alg_extsize(struct crypto_alg *alg)
1054{
c2110f28
HX
1055 return alg->cra_ctxsize +
1056 (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
38d21433
HX
1057}
1058EXPORT_SYMBOL_GPL(crypto_alg_extsize);
1059
f2aefdab
HX
1060int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
1061 u32 type, u32 mask)
1062{
1063 int ret = 0;
1064 struct crypto_alg *alg = crypto_find_alg(name, frontend, type, mask);
1065
1066 if (!IS_ERR(alg)) {
1067 crypto_mod_put(alg);
1068 ret = 1;
1069 }
1070
1071 return ret;
1072}
1073EXPORT_SYMBOL_GPL(crypto_type_has_alg);
1074
f7d76e05
CL
1075#ifdef CONFIG_CRYPTO_STATS
1076void crypto_stats_get(struct crypto_alg *alg)
1077{
1078 crypto_alg_get(alg);
1079}
1080EXPORT_SYMBOL_GPL(crypto_stats_get);
1081
1082void crypto_stats_ablkcipher_encrypt(unsigned int nbytes, int ret,
1083 struct crypto_alg *alg)
1084{
1085 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1086 atomic64_inc(&alg->stats.cipher.err_cnt);
f7d76e05 1087 } else {
17c18f9e
CL
1088 atomic64_inc(&alg->stats.cipher.encrypt_cnt);
1089 atomic64_add(nbytes, &alg->stats.cipher.encrypt_tlen);
f7d76e05
CL
1090 }
1091 crypto_alg_put(alg);
1092}
1093EXPORT_SYMBOL_GPL(crypto_stats_ablkcipher_encrypt);
1094
1095void crypto_stats_ablkcipher_decrypt(unsigned int nbytes, int ret,
1096 struct crypto_alg *alg)
1097{
1098 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1099 atomic64_inc(&alg->stats.cipher.err_cnt);
f7d76e05 1100 } else {
17c18f9e
CL
1101 atomic64_inc(&alg->stats.cipher.decrypt_cnt);
1102 atomic64_add(nbytes, &alg->stats.cipher.decrypt_tlen);
f7d76e05
CL
1103 }
1104 crypto_alg_put(alg);
1105}
1106EXPORT_SYMBOL_GPL(crypto_stats_ablkcipher_decrypt);
1107
1108void crypto_stats_aead_encrypt(unsigned int cryptlen, struct crypto_alg *alg,
1109 int ret)
1110{
1111 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1112 atomic64_inc(&alg->stats.aead.err_cnt);
f7d76e05 1113 } else {
17c18f9e
CL
1114 atomic64_inc(&alg->stats.aead.encrypt_cnt);
1115 atomic64_add(cryptlen, &alg->stats.aead.encrypt_tlen);
f7d76e05
CL
1116 }
1117 crypto_alg_put(alg);
1118}
1119EXPORT_SYMBOL_GPL(crypto_stats_aead_encrypt);
1120
1121void crypto_stats_aead_decrypt(unsigned int cryptlen, struct crypto_alg *alg,
1122 int ret)
1123{
1124 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1125 atomic64_inc(&alg->stats.aead.err_cnt);
f7d76e05 1126 } else {
17c18f9e
CL
1127 atomic64_inc(&alg->stats.aead.decrypt_cnt);
1128 atomic64_add(cryptlen, &alg->stats.aead.decrypt_tlen);
f7d76e05
CL
1129 }
1130 crypto_alg_put(alg);
1131}
1132EXPORT_SYMBOL_GPL(crypto_stats_aead_decrypt);
1133
1134void crypto_stats_akcipher_encrypt(unsigned int src_len, int ret,
1135 struct crypto_alg *alg)
1136{
1137 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1138 atomic64_inc(&alg->stats.akcipher.err_cnt);
f7d76e05 1139 } else {
17c18f9e
CL
1140 atomic64_inc(&alg->stats.akcipher.encrypt_cnt);
1141 atomic64_add(src_len, &alg->stats.akcipher.encrypt_tlen);
f7d76e05
CL
1142 }
1143 crypto_alg_put(alg);
1144}
1145EXPORT_SYMBOL_GPL(crypto_stats_akcipher_encrypt);
1146
1147void crypto_stats_akcipher_decrypt(unsigned int src_len, int ret,
1148 struct crypto_alg *alg)
1149{
1150 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1151 atomic64_inc(&alg->stats.akcipher.err_cnt);
f7d76e05 1152 } else {
17c18f9e
CL
1153 atomic64_inc(&alg->stats.akcipher.decrypt_cnt);
1154 atomic64_add(src_len, &alg->stats.akcipher.decrypt_tlen);
f7d76e05
CL
1155 }
1156 crypto_alg_put(alg);
1157}
1158EXPORT_SYMBOL_GPL(crypto_stats_akcipher_decrypt);
1159
1160void crypto_stats_akcipher_sign(int ret, struct crypto_alg *alg)
1161{
1162 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
44f13133 1163 atomic64_inc(&alg->stats.akcipher.err_cnt);
f7d76e05 1164 else
17c18f9e 1165 atomic64_inc(&alg->stats.akcipher.sign_cnt);
f7d76e05
CL
1166 crypto_alg_put(alg);
1167}
1168EXPORT_SYMBOL_GPL(crypto_stats_akcipher_sign);
1169
1170void crypto_stats_akcipher_verify(int ret, struct crypto_alg *alg)
1171{
1172 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
44f13133 1173 atomic64_inc(&alg->stats.akcipher.err_cnt);
f7d76e05 1174 else
17c18f9e 1175 atomic64_inc(&alg->stats.akcipher.verify_cnt);
f7d76e05
CL
1176 crypto_alg_put(alg);
1177}
1178EXPORT_SYMBOL_GPL(crypto_stats_akcipher_verify);
1179
1180void crypto_stats_compress(unsigned int slen, int ret, struct crypto_alg *alg)
1181{
1182 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1183 atomic64_inc(&alg->stats.compress.err_cnt);
f7d76e05 1184 } else {
17c18f9e
CL
1185 atomic64_inc(&alg->stats.compress.compress_cnt);
1186 atomic64_add(slen, &alg->stats.compress.compress_tlen);
f7d76e05
CL
1187 }
1188 crypto_alg_put(alg);
1189}
1190EXPORT_SYMBOL_GPL(crypto_stats_compress);
1191
1192void crypto_stats_decompress(unsigned int slen, int ret, struct crypto_alg *alg)
1193{
1194 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1195 atomic64_inc(&alg->stats.compress.err_cnt);
f7d76e05 1196 } else {
17c18f9e
CL
1197 atomic64_inc(&alg->stats.compress.decompress_cnt);
1198 atomic64_add(slen, &alg->stats.compress.decompress_tlen);
f7d76e05
CL
1199 }
1200 crypto_alg_put(alg);
1201}
1202EXPORT_SYMBOL_GPL(crypto_stats_decompress);
1203
1204void crypto_stats_ahash_update(unsigned int nbytes, int ret,
1205 struct crypto_alg *alg)
1206{
1207 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
44f13133 1208 atomic64_inc(&alg->stats.hash.err_cnt);
f7d76e05 1209 else
17c18f9e 1210 atomic64_add(nbytes, &alg->stats.hash.hash_tlen);
f7d76e05
CL
1211 crypto_alg_put(alg);
1212}
1213EXPORT_SYMBOL_GPL(crypto_stats_ahash_update);
1214
1215void crypto_stats_ahash_final(unsigned int nbytes, int ret,
1216 struct crypto_alg *alg)
1217{
1218 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1219 atomic64_inc(&alg->stats.hash.err_cnt);
f7d76e05 1220 } else {
17c18f9e
CL
1221 atomic64_inc(&alg->stats.hash.hash_cnt);
1222 atomic64_add(nbytes, &alg->stats.hash.hash_tlen);
f7d76e05
CL
1223 }
1224 crypto_alg_put(alg);
1225}
1226EXPORT_SYMBOL_GPL(crypto_stats_ahash_final);
1227
1228void crypto_stats_kpp_set_secret(struct crypto_alg *alg, int ret)
1229{
1230 if (ret)
44f13133 1231 atomic64_inc(&alg->stats.kpp.err_cnt);
f7d76e05 1232 else
17c18f9e 1233 atomic64_inc(&alg->stats.kpp.setsecret_cnt);
f7d76e05
CL
1234 crypto_alg_put(alg);
1235}
1236EXPORT_SYMBOL_GPL(crypto_stats_kpp_set_secret);
1237
1238void crypto_stats_kpp_generate_public_key(struct crypto_alg *alg, int ret)
1239{
1240 if (ret)
44f13133 1241 atomic64_inc(&alg->stats.kpp.err_cnt);
f7d76e05 1242 else
17c18f9e 1243 atomic64_inc(&alg->stats.kpp.generate_public_key_cnt);
f7d76e05
CL
1244 crypto_alg_put(alg);
1245}
1246EXPORT_SYMBOL_GPL(crypto_stats_kpp_generate_public_key);
1247
1248void crypto_stats_kpp_compute_shared_secret(struct crypto_alg *alg, int ret)
1249{
1250 if (ret)
44f13133 1251 atomic64_inc(&alg->stats.kpp.err_cnt);
f7d76e05 1252 else
17c18f9e 1253 atomic64_inc(&alg->stats.kpp.compute_shared_secret_cnt);
f7d76e05
CL
1254 crypto_alg_put(alg);
1255}
1256EXPORT_SYMBOL_GPL(crypto_stats_kpp_compute_shared_secret);
1257
1258void crypto_stats_rng_seed(struct crypto_alg *alg, int ret)
1259{
1260 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
44f13133 1261 atomic64_inc(&alg->stats.rng.err_cnt);
f7d76e05 1262 else
17c18f9e 1263 atomic64_inc(&alg->stats.rng.seed_cnt);
f7d76e05
CL
1264 crypto_alg_put(alg);
1265}
1266EXPORT_SYMBOL_GPL(crypto_stats_rng_seed);
1267
1268void crypto_stats_rng_generate(struct crypto_alg *alg, unsigned int dlen,
1269 int ret)
1270{
1271 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1272 atomic64_inc(&alg->stats.rng.err_cnt);
f7d76e05 1273 } else {
17c18f9e
CL
1274 atomic64_inc(&alg->stats.rng.generate_cnt);
1275 atomic64_add(dlen, &alg->stats.rng.generate_tlen);
f7d76e05
CL
1276 }
1277 crypto_alg_put(alg);
1278}
1279EXPORT_SYMBOL_GPL(crypto_stats_rng_generate);
1280
1281void crypto_stats_skcipher_encrypt(unsigned int cryptlen, int ret,
1282 struct crypto_alg *alg)
1283{
1284 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1285 atomic64_inc(&alg->stats.cipher.err_cnt);
f7d76e05 1286 } else {
17c18f9e
CL
1287 atomic64_inc(&alg->stats.cipher.encrypt_cnt);
1288 atomic64_add(cryptlen, &alg->stats.cipher.encrypt_tlen);
f7d76e05
CL
1289 }
1290 crypto_alg_put(alg);
1291}
1292EXPORT_SYMBOL_GPL(crypto_stats_skcipher_encrypt);
1293
1294void crypto_stats_skcipher_decrypt(unsigned int cryptlen, int ret,
1295 struct crypto_alg *alg)
1296{
1297 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
44f13133 1298 atomic64_inc(&alg->stats.cipher.err_cnt);
f7d76e05 1299 } else {
17c18f9e
CL
1300 atomic64_inc(&alg->stats.cipher.decrypt_cnt);
1301 atomic64_add(cryptlen, &alg->stats.cipher.decrypt_tlen);
f7d76e05
CL
1302 }
1303 crypto_alg_put(alg);
1304}
1305EXPORT_SYMBOL_GPL(crypto_stats_skcipher_decrypt);
1306#endif
1307
cce9e06d
HX
1308static int __init crypto_algapi_init(void)
1309{
1310 crypto_init_proc();
1311 return 0;
1312}
1313
1314static void __exit crypto_algapi_exit(void)
1315{
1316 crypto_exit_proc();
1317}
1318
1319module_init(crypto_algapi_init);
1320module_exit(crypto_algapi_exit);
1321
1322MODULE_LICENSE("GPL");
1323MODULE_DESCRIPTION("Cryptographic algorithms API");