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