blob: 5278e139a161e97b9888c40c3f554f3c360a243e [file] [log] [blame]
Herbert Xucce9e062006-08-21 21:08:13 +10001/*
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
Salvatore Mesoraca13c935b2018-04-09 15:54:46 +020013#include <crypto/algapi.h>
Herbert Xu6bfd4802006-09-21 11:39:29 +100014#include <linux/err.h>
Herbert Xucce9e062006-08-21 21:08:13 +100015#include <linux/errno.h>
Herbert Xu3133d762015-04-22 13:25:53 +080016#include <linux/fips.h>
Herbert Xucce9e062006-08-21 21:08:13 +100017#include <linux/init.h>
18#include <linux/kernel.h>
Herbert Xu4cc77202006-08-06 21:16:34 +100019#include <linux/list.h>
Herbert Xucce9e062006-08-21 21:08:13 +100020#include <linux/module.h>
Herbert Xu7fed0bf2006-08-06 23:10:45 +100021#include <linux/rtnetlink.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Herbert Xucce9e062006-08-21 21:08:13 +100023#include <linux/string.h>
24
25#include "internal.h"
26
Herbert Xu4cc77202006-08-06 21:16:34 +100027static LIST_HEAD(crypto_template_list);
28
Jarod Wilson002c77a2014-07-02 15:37:30 -040029static inline void crypto_check_module_sig(struct module *mod)
30{
Herbert Xu59afdc72015-04-22 11:28:46 +080031 if (fips_enabled && mod && !module_sig_ok(mod))
Jarod Wilson002c77a2014-07-02 15:37:30 -040032 panic("Module %s signature verification failed in FIPS mode\n",
Herbert Xubd4a7c62015-04-23 14:48:05 +080033 module_name(mod));
Jarod Wilson002c77a2014-07-02 15:37:30 -040034}
35
Herbert Xu4cc77202006-08-06 21:16:34 +100036static int crypto_check_alg(struct crypto_alg *alg)
Herbert Xucce9e062006-08-21 21:08:13 +100037{
Jarod Wilson002c77a2014-07-02 15:37:30 -040038 crypto_check_module_sig(alg->cra_module);
39
Eric Biggers177f87d2019-06-02 22:40:58 -070040 if (!alg->cra_name[0] || !alg->cra_driver_name[0])
41 return -EINVAL;
42
Herbert Xucce9e062006-08-21 21:08:13 +100043 if (alg->cra_alignmask & (alg->cra_alignmask + 1))
44 return -EINVAL;
45
Kees Cooka9f7f882018-08-07 14:18:40 -070046 /* General maximums for all algs. */
47 if (alg->cra_alignmask > MAX_ALGAPI_ALIGNMASK)
Herbert Xucce9e062006-08-21 21:08:13 +100048 return -EINVAL;
49
Kees Cooka9f7f882018-08-07 14:18:40 -070050 if (alg->cra_blocksize > MAX_ALGAPI_BLOCKSIZE)
51 return -EINVAL;
52
53 /* Lower maximums for specific alg types. */
Salvatore Mesoraca13c935b2018-04-09 15:54:46 +020054 if (!alg->cra_type && (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
55 CRYPTO_ALG_TYPE_CIPHER) {
56 if (alg->cra_alignmask > MAX_CIPHER_ALIGNMASK)
57 return -EINVAL;
58
59 if (alg->cra_blocksize > MAX_CIPHER_BLOCKSIZE)
60 return -EINVAL;
61 }
62
Herbert Xucce9e062006-08-21 21:08:13 +100063 if (alg->cra_priority < 0)
64 return -EINVAL;
Herbert Xucce9e062006-08-21 21:08:13 +100065
Eric Biggersce8614a2017-12-29 10:00:46 -060066 refcount_set(&alg->cra_refcnt, 1);
Herbert Xue9b8e5b2015-04-09 17:40:35 +080067
Eric Biggers177f87d2019-06-02 22:40:58 -070068 return 0;
Herbert Xu4cc77202006-08-06 21:16:34 +100069}
70
Herbert Xu319382a2015-07-09 07:17:15 +080071static void crypto_free_instance(struct crypto_instance *inst)
72{
73 if (!inst->alg.cra_type->free) {
74 inst->tmpl->free(inst);
75 return;
76 }
77
78 inst->alg.cra_type->free(inst);
79}
80
Herbert Xu6bfd4802006-09-21 11:39:29 +100081static void crypto_destroy_instance(struct crypto_alg *alg)
82{
83 struct crypto_instance *inst = (void *)alg;
84 struct crypto_template *tmpl = inst->tmpl;
85
Herbert Xu319382a2015-07-09 07:17:15 +080086 crypto_free_instance(inst);
Herbert Xu6bfd4802006-09-21 11:39:29 +100087 crypto_tmpl_put(tmpl);
88}
89
Herbert Xu2bf29012009-08-31 15:56:54 +100090static struct list_head *crypto_more_spawns(struct crypto_alg *alg,
91 struct list_head *stack,
92 struct list_head *top,
93 struct list_head *secondary_spawns)
94{
95 struct crypto_spawn *spawn, *n;
96
Geliang Tang304e4812015-11-16 22:37:14 +080097 spawn = list_first_entry_or_null(stack, struct crypto_spawn, list);
98 if (!spawn)
Herbert Xu2bf29012009-08-31 15:56:54 +100099 return NULL;
100
Geliang Tang304e4812015-11-16 22:37:14 +0800101 n = list_next_entry(spawn, list);
Herbert Xu2bf29012009-08-31 15:56:54 +1000102
103 if (spawn->alg && &n->list != stack && !n->alg)
104 n->alg = (n->list.next == stack) ? alg :
Geliang Tang304e4812015-11-16 22:37:14 +0800105 &list_next_entry(n, list)->inst->alg;
Herbert Xu2bf29012009-08-31 15:56:54 +1000106
107 list_move(&spawn->list, secondary_spawns);
108
109 return &n->list == stack ? top : &n->inst->alg.cra_users;
110}
111
Herbert Xu1f723712015-04-02 22:31:22 +0800112static void crypto_remove_instance(struct crypto_instance *inst,
113 struct list_head *list)
Herbert Xua73e6992007-04-08 21:31:36 +1000114{
Herbert Xua73e6992007-04-08 21:31:36 +1000115 struct crypto_template *tmpl = inst->tmpl;
116
Herbert Xua73e6992007-04-08 21:31:36 +1000117 if (crypto_is_dead(&inst->alg))
118 return;
119
120 inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
Herbert Xu38cb2412007-11-17 22:09:38 +0800121 if (hlist_unhashed(&inst->list))
122 return;
123
Herbert Xua73e6992007-04-08 21:31:36 +1000124 if (!tmpl || !crypto_tmpl_get(tmpl))
125 return;
126
Herbert Xua73e6992007-04-08 21:31:36 +1000127 list_move(&inst->alg.cra_list, list);
128 hlist_del(&inst->list);
129 inst->alg.cra_destroy = crypto_destroy_instance;
130
Herbert Xu2bf29012009-08-31 15:56:54 +1000131 BUG_ON(!list_empty(&inst->alg.cra_users));
Herbert Xua73e6992007-04-08 21:31:36 +1000132}
133
Steffen Klassert89b596b2011-09-27 07:22:08 +0200134void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
135 struct crypto_alg *nalg)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000136{
Herbert Xu2bf29012009-08-31 15:56:54 +1000137 u32 new_type = (nalg ?: alg)->cra_flags;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000138 struct crypto_spawn *spawn, *n;
Herbert Xua73e6992007-04-08 21:31:36 +1000139 LIST_HEAD(secondary_spawns);
Herbert Xu2bf29012009-08-31 15:56:54 +1000140 struct list_head *spawns;
141 LIST_HEAD(stack);
142 LIST_HEAD(top);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000143
Herbert Xu2bf29012009-08-31 15:56:54 +1000144 spawns = &alg->cra_users;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000145 list_for_each_entry_safe(spawn, n, spawns, list) {
Herbert Xua73e6992007-04-08 21:31:36 +1000146 if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000147 continue;
148
Herbert Xu2bf29012009-08-31 15:56:54 +1000149 list_move(&spawn->list, &top);
Herbert Xua73e6992007-04-08 21:31:36 +1000150 }
Herbert Xu6bfd4802006-09-21 11:39:29 +1000151
Herbert Xu2bf29012009-08-31 15:56:54 +1000152 spawns = &top;
153 do {
154 while (!list_empty(spawns)) {
155 struct crypto_instance *inst;
156
157 spawn = list_first_entry(spawns, struct crypto_spawn,
158 list);
159 inst = spawn->inst;
160
161 BUG_ON(&inst->alg == alg);
162
163 list_move(&spawn->list, &stack);
164
165 if (&inst->alg == nalg)
166 break;
167
168 spawn->alg = NULL;
169 spawns = &inst->alg.cra_users;
Eric Biggers9a006742017-12-29 14:30:19 -0600170
171 /*
172 * We may encounter an unregistered instance here, since
173 * an instance's spawns are set up prior to the instance
174 * being registered. An unregistered instance will have
175 * NULL ->cra_users.next, since ->cra_users isn't
176 * properly initialized until registration. But an
177 * unregistered instance cannot have any users, so treat
178 * it the same as ->cra_users being empty.
179 */
180 if (spawns->next == NULL)
181 break;
Herbert Xu2bf29012009-08-31 15:56:54 +1000182 }
183 } while ((spawns = crypto_more_spawns(alg, &stack, &top,
184 &secondary_spawns)));
185
186 list_for_each_entry_safe(spawn, n, &secondary_spawns, list) {
187 if (spawn->alg)
188 list_move(&spawn->list, &spawn->alg->cra_users);
189 else
Herbert Xu1f723712015-04-02 22:31:22 +0800190 crypto_remove_instance(spawn->inst, list);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000191 }
192}
Steffen Klassert89b596b2011-09-27 07:22:08 +0200193EXPORT_SYMBOL_GPL(crypto_remove_spawns);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000194
Herbert Xu73d38642008-08-03 21:15:23 +0800195static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
Herbert Xu4cc77202006-08-06 21:16:34 +1000196{
197 struct crypto_alg *q;
Herbert Xu73d38642008-08-03 21:15:23 +0800198 struct crypto_larval *larval;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000199 int ret = -EAGAIN;
200
201 if (crypto_is_dead(alg))
Herbert Xu73d38642008-08-03 21:15:23 +0800202 goto err;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000203
204 INIT_LIST_HEAD(&alg->cra_users);
205
Herbert Xu73d38642008-08-03 21:15:23 +0800206 /* No cheating! */
207 alg->cra_flags &= ~CRYPTO_ALG_TESTED;
208
Herbert Xu6bfd4802006-09-21 11:39:29 +1000209 ret = -EEXIST;
Herbert Xu4cc77202006-08-06 21:16:34 +1000210
Herbert Xucce9e062006-08-21 21:08:13 +1000211 list_for_each_entry(q, &crypto_alg_list, cra_list) {
Herbert Xu4cc77202006-08-06 21:16:34 +1000212 if (q == alg)
Herbert Xu73d38642008-08-03 21:15:23 +0800213 goto err;
214
Herbert Xub8e15992009-01-28 14:09:59 +1100215 if (crypto_is_moribund(q))
216 continue;
217
Herbert Xu73d38642008-08-03 21:15:23 +0800218 if (crypto_is_larval(q)) {
219 if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
220 goto err;
221 continue;
222 }
223
224 if (!strcmp(q->cra_driver_name, alg->cra_name) ||
225 !strcmp(q->cra_name, alg->cra_driver_name))
226 goto err;
227 }
228
229 larval = crypto_larval_alloc(alg->cra_name,
230 alg->cra_flags | CRYPTO_ALG_TESTED, 0);
231 if (IS_ERR(larval))
232 goto out;
233
234 ret = -ENOENT;
235 larval->adult = crypto_mod_get(alg);
236 if (!larval->adult)
237 goto free_larval;
238
Eric Biggersce8614a2017-12-29 10:00:46 -0600239 refcount_set(&larval->alg.cra_refcnt, 1);
Herbert Xu73d38642008-08-03 21:15:23 +0800240 memcpy(larval->alg.cra_driver_name, alg->cra_driver_name,
241 CRYPTO_MAX_ALG_NAME);
242 larval->alg.cra_priority = alg->cra_priority;
243
244 list_add(&alg->cra_list, &crypto_alg_list);
245 list_add(&larval->alg.cra_list, &crypto_alg_list);
246
Corentin Labbe1f6669b2018-11-29 14:42:26 +0000247 crypto_stats_init(alg);
Corentin Labbecac58182018-09-19 10:10:54 +0000248
Richard Hartmann5357c6c2010-02-16 20:25:21 +0800249out:
Herbert Xu73d38642008-08-03 21:15:23 +0800250 return larval;
251
252free_larval:
253 kfree(larval);
254err:
255 larval = ERR_PTR(ret);
256 goto out;
257}
258
259void crypto_alg_tested(const char *name, int err)
260{
261 struct crypto_larval *test;
262 struct crypto_alg *alg;
263 struct crypto_alg *q;
264 LIST_HEAD(list);
265
266 down_write(&crypto_alg_sem);
267 list_for_each_entry(q, &crypto_alg_list, cra_list) {
Herbert Xub8e15992009-01-28 14:09:59 +1100268 if (crypto_is_moribund(q) || !crypto_is_larval(q))
Herbert Xu73d38642008-08-03 21:15:23 +0800269 continue;
270
271 test = (struct crypto_larval *)q;
272
273 if (!strcmp(q->cra_driver_name, name))
274 goto found;
275 }
276
Karim Eshapac7235852017-05-13 21:05:19 +0200277 pr_err("alg: Unexpected test result for %s: %d\n", name, err);
Herbert Xu73d38642008-08-03 21:15:23 +0800278 goto unlock;
279
280found:
Herbert Xub8e15992009-01-28 14:09:59 +1100281 q->cra_flags |= CRYPTO_ALG_DEAD;
Herbert Xu73d38642008-08-03 21:15:23 +0800282 alg = test->adult;
283 if (err || list_empty(&alg->cra_list))
284 goto complete;
285
286 alg->cra_flags |= CRYPTO_ALG_TESTED;
287
288 list_for_each_entry(q, &crypto_alg_list, cra_list) {
289 if (q == alg)
290 continue;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000291
292 if (crypto_is_moribund(q))
293 continue;
294
295 if (crypto_is_larval(q)) {
Herbert Xu28259822006-08-06 21:23:26 +1000296 struct crypto_larval *larval = (void *)q;
297
Herbert Xud8058482007-10-02 22:27:29 +0800298 /*
299 * Check to see if either our generic name or
300 * specific name can satisfy the name requested
301 * by the larval entry q.
302 */
Herbert Xu6bfd4802006-09-21 11:39:29 +1000303 if (strcmp(alg->cra_name, q->cra_name) &&
304 strcmp(alg->cra_driver_name, q->cra_name))
305 continue;
306
307 if (larval->adult)
308 continue;
Herbert Xu492e2b62006-09-21 11:35:17 +1000309 if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
310 continue;
Herbert Xu28259822006-08-06 21:23:26 +1000311 if (!crypto_mod_get(alg))
312 continue;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000313
Herbert Xu28259822006-08-06 21:23:26 +1000314 larval->adult = alg;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000315 continue;
Herbert Xu28259822006-08-06 21:23:26 +1000316 }
Herbert Xu6bfd4802006-09-21 11:39:29 +1000317
318 if (strcmp(alg->cra_name, q->cra_name))
319 continue;
320
321 if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
322 q->cra_priority > alg->cra_priority)
323 continue;
324
Herbert Xu2bf29012009-08-31 15:56:54 +1000325 crypto_remove_spawns(q, &list, alg);
Herbert Xucce9e062006-08-21 21:08:13 +1000326 }
Herbert Xu28259822006-08-06 21:23:26 +1000327
Herbert Xu73d38642008-08-03 21:15:23 +0800328complete:
329 complete_all(&test->completion);
Herbert Xu28259822006-08-06 21:23:26 +1000330
Herbert Xu73d38642008-08-03 21:15:23 +0800331unlock:
332 up_write(&crypto_alg_sem);
333
334 crypto_remove_final(&list);
Herbert Xucce9e062006-08-21 21:08:13 +1000335}
Herbert Xu73d38642008-08-03 21:15:23 +0800336EXPORT_SYMBOL_GPL(crypto_alg_tested);
Herbert Xu4cc77202006-08-06 21:16:34 +1000337
Steffen Klassert22e5b202011-09-27 07:23:07 +0200338void crypto_remove_final(struct list_head *list)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000339{
340 struct crypto_alg *alg;
341 struct crypto_alg *n;
342
343 list_for_each_entry_safe(alg, n, list, cra_list) {
344 list_del_init(&alg->cra_list);
345 crypto_alg_put(alg);
346 }
347}
Steffen Klassert22e5b202011-09-27 07:23:07 +0200348EXPORT_SYMBOL_GPL(crypto_remove_final);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000349
Herbert Xu73d38642008-08-03 21:15:23 +0800350static void crypto_wait_for_test(struct crypto_larval *larval)
351{
352 int err;
353
354 err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
355 if (err != NOTIFY_STOP) {
356 if (WARN_ON(err != NOTIFY_DONE))
357 goto out;
358 crypto_alg_tested(larval->alg.cra_driver_name, 0);
359 }
360
Herbert Xu3fc89ad2015-10-19 18:23:57 +0800361 err = wait_for_completion_killable(&larval->completion);
Herbert Xu73d38642008-08-03 21:15:23 +0800362 WARN_ON(err);
Martin K. Petersendd8b0832018-08-30 11:00:14 -0400363 if (!err)
364 crypto_probing_notify(CRYPTO_MSG_ALG_LOADED, larval);
Herbert Xu73d38642008-08-03 21:15:23 +0800365
366out:
367 crypto_larval_kill(&larval->alg);
368}
369
Herbert Xu4cc77202006-08-06 21:16:34 +1000370int crypto_register_alg(struct crypto_alg *alg)
371{
Herbert Xu73d38642008-08-03 21:15:23 +0800372 struct crypto_larval *larval;
Herbert Xu4cc77202006-08-06 21:16:34 +1000373 int err;
374
Salvatore Benedettod6040762017-01-13 11:54:08 +0000375 alg->cra_flags &= ~CRYPTO_ALG_DEAD;
Herbert Xu4cc77202006-08-06 21:16:34 +1000376 err = crypto_check_alg(alg);
377 if (err)
378 return err;
379
380 down_write(&crypto_alg_sem);
Herbert Xu73d38642008-08-03 21:15:23 +0800381 larval = __crypto_register_alg(alg);
Herbert Xu4cc77202006-08-06 21:16:34 +1000382 up_write(&crypto_alg_sem);
383
Herbert Xu73d38642008-08-03 21:15:23 +0800384 if (IS_ERR(larval))
385 return PTR_ERR(larval);
386
387 crypto_wait_for_test(larval);
388 return 0;
Herbert Xu4cc77202006-08-06 21:16:34 +1000389}
Herbert Xucce9e062006-08-21 21:08:13 +1000390EXPORT_SYMBOL_GPL(crypto_register_alg);
391
Herbert Xu6bfd4802006-09-21 11:39:29 +1000392static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
393{
394 if (unlikely(list_empty(&alg->cra_list)))
395 return -ENOENT;
396
397 alg->cra_flags |= CRYPTO_ALG_DEAD;
398
Herbert Xu6bfd4802006-09-21 11:39:29 +1000399 list_del_init(&alg->cra_list);
Herbert Xu2bf29012009-08-31 15:56:54 +1000400 crypto_remove_spawns(alg, list, NULL);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000401
402 return 0;
403}
404
Herbert Xucce9e062006-08-21 21:08:13 +1000405int crypto_unregister_alg(struct crypto_alg *alg)
406{
Herbert Xu6bfd4802006-09-21 11:39:29 +1000407 int ret;
408 LIST_HEAD(list);
Richard Hartmann5357c6c2010-02-16 20:25:21 +0800409
Herbert Xucce9e062006-08-21 21:08:13 +1000410 down_write(&crypto_alg_sem);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000411 ret = crypto_remove_alg(alg, &list);
Herbert Xucce9e062006-08-21 21:08:13 +1000412 up_write(&crypto_alg_sem);
413
414 if (ret)
415 return ret;
416
Eric Biggersce8614a2017-12-29 10:00:46 -0600417 BUG_ON(refcount_read(&alg->cra_refcnt) != 1);
Herbert Xucce9e062006-08-21 21:08:13 +1000418 if (alg->cra_destroy)
419 alg->cra_destroy(alg);
420
Herbert Xu6bfd4802006-09-21 11:39:29 +1000421 crypto_remove_final(&list);
Herbert Xucce9e062006-08-21 21:08:13 +1000422 return 0;
423}
424EXPORT_SYMBOL_GPL(crypto_unregister_alg);
425
Mark Brown4b004342012-01-17 23:34:26 +0000426int crypto_register_algs(struct crypto_alg *algs, int count)
427{
428 int i, ret;
429
430 for (i = 0; i < count; i++) {
431 ret = crypto_register_alg(&algs[i]);
432 if (ret)
433 goto err;
434 }
435
436 return 0;
437
438err:
439 for (--i; i >= 0; --i)
440 crypto_unregister_alg(&algs[i]);
441
442 return ret;
443}
444EXPORT_SYMBOL_GPL(crypto_register_algs);
445
446int crypto_unregister_algs(struct crypto_alg *algs, int count)
447{
448 int i, ret;
449
450 for (i = 0; i < count; i++) {
451 ret = crypto_unregister_alg(&algs[i]);
452 if (ret)
453 pr_err("Failed to unregister %s %s: %d\n",
454 algs[i].cra_driver_name, algs[i].cra_name, ret);
455 }
456
457 return 0;
458}
459EXPORT_SYMBOL_GPL(crypto_unregister_algs);
460
Herbert Xu4cc77202006-08-06 21:16:34 +1000461int crypto_register_template(struct crypto_template *tmpl)
462{
463 struct crypto_template *q;
464 int err = -EEXIST;
465
466 down_write(&crypto_alg_sem);
467
Jarod Wilson002c77a2014-07-02 15:37:30 -0400468 crypto_check_module_sig(tmpl->module);
469
Herbert Xu4cc77202006-08-06 21:16:34 +1000470 list_for_each_entry(q, &crypto_template_list, list) {
471 if (q == tmpl)
472 goto out;
473 }
474
475 list_add(&tmpl->list, &crypto_template_list);
476 err = 0;
477out:
478 up_write(&crypto_alg_sem);
479 return err;
480}
481EXPORT_SYMBOL_GPL(crypto_register_template);
482
Xiongfeng Wang95724422019-01-18 13:58:11 +0800483int crypto_register_templates(struct crypto_template *tmpls, int count)
484{
485 int i, err;
486
487 for (i = 0; i < count; i++) {
488 err = crypto_register_template(&tmpls[i]);
489 if (err)
490 goto out;
491 }
492 return 0;
493
494out:
495 for (--i; i >= 0; --i)
496 crypto_unregister_template(&tmpls[i]);
497 return err;
498}
499EXPORT_SYMBOL_GPL(crypto_register_templates);
500
Herbert Xu4cc77202006-08-06 21:16:34 +1000501void crypto_unregister_template(struct crypto_template *tmpl)
502{
503 struct crypto_instance *inst;
Sasha Levinb67bfe02013-02-27 17:06:00 -0800504 struct hlist_node *n;
Herbert Xu4cc77202006-08-06 21:16:34 +1000505 struct hlist_head *list;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000506 LIST_HEAD(users);
Herbert Xu4cc77202006-08-06 21:16:34 +1000507
508 down_write(&crypto_alg_sem);
509
510 BUG_ON(list_empty(&tmpl->list));
511 list_del_init(&tmpl->list);
512
513 list = &tmpl->instances;
Sasha Levinb67bfe02013-02-27 17:06:00 -0800514 hlist_for_each_entry(inst, list, list) {
Herbert Xu6bfd4802006-09-21 11:39:29 +1000515 int err = crypto_remove_alg(&inst->alg, &users);
Joshua I. James0efcb8d2014-12-05 15:00:10 +0900516
Herbert Xu6bfd4802006-09-21 11:39:29 +1000517 BUG_ON(err);
Herbert Xu4cc77202006-08-06 21:16:34 +1000518 }
519
520 up_write(&crypto_alg_sem);
521
Sasha Levinb67bfe02013-02-27 17:06:00 -0800522 hlist_for_each_entry_safe(inst, n, list, list) {
Eric Biggersce8614a2017-12-29 10:00:46 -0600523 BUG_ON(refcount_read(&inst->alg.cra_refcnt) != 1);
Herbert Xu319382a2015-07-09 07:17:15 +0800524 crypto_free_instance(inst);
Herbert Xu4cc77202006-08-06 21:16:34 +1000525 }
Herbert Xu6bfd4802006-09-21 11:39:29 +1000526 crypto_remove_final(&users);
Herbert Xu4cc77202006-08-06 21:16:34 +1000527}
528EXPORT_SYMBOL_GPL(crypto_unregister_template);
529
Xiongfeng Wang95724422019-01-18 13:58:11 +0800530void crypto_unregister_templates(struct crypto_template *tmpls, int count)
531{
532 int i;
533
534 for (i = count - 1; i >= 0; --i)
535 crypto_unregister_template(&tmpls[i]);
536}
537EXPORT_SYMBOL_GPL(crypto_unregister_templates);
538
Herbert Xu4cc77202006-08-06 21:16:34 +1000539static struct crypto_template *__crypto_lookup_template(const char *name)
540{
541 struct crypto_template *q, *tmpl = NULL;
542
543 down_read(&crypto_alg_sem);
544 list_for_each_entry(q, &crypto_template_list, list) {
545 if (strcmp(q->name, name))
546 continue;
547 if (unlikely(!crypto_tmpl_get(q)))
548 continue;
549
550 tmpl = q;
551 break;
552 }
553 up_read(&crypto_alg_sem);
554
555 return tmpl;
556}
557
558struct crypto_template *crypto_lookup_template(const char *name)
559{
Kees Cook4943ba12014-11-24 16:32:38 -0800560 return try_then_request_module(__crypto_lookup_template(name),
561 "crypto-%s", name);
Herbert Xu4cc77202006-08-06 21:16:34 +1000562}
563EXPORT_SYMBOL_GPL(crypto_lookup_template);
564
565int crypto_register_instance(struct crypto_template *tmpl,
566 struct crypto_instance *inst)
567{
Herbert Xu73d38642008-08-03 21:15:23 +0800568 struct crypto_larval *larval;
569 int err;
Herbert Xu4cc77202006-08-06 21:16:34 +1000570
Herbert Xu4cc77202006-08-06 21:16:34 +1000571 err = crypto_check_alg(&inst->alg);
572 if (err)
Stephan Mueller9c521a22015-04-09 12:09:55 +0200573 return err;
574
Herbert Xu4cc77202006-08-06 21:16:34 +1000575 inst->alg.cra_module = tmpl->module;
Steffen Klassert64a947b2011-09-27 07:21:26 +0200576 inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
Herbert Xu4cc77202006-08-06 21:16:34 +1000577
578 down_write(&crypto_alg_sem);
579
Herbert Xu73d38642008-08-03 21:15:23 +0800580 larval = __crypto_register_alg(&inst->alg);
581 if (IS_ERR(larval))
Herbert Xu4cc77202006-08-06 21:16:34 +1000582 goto unlock;
583
584 hlist_add_head(&inst->list, &tmpl->instances);
585 inst->tmpl = tmpl;
586
587unlock:
588 up_write(&crypto_alg_sem);
589
Herbert Xu73d38642008-08-03 21:15:23 +0800590 err = PTR_ERR(larval);
591 if (IS_ERR(larval))
592 goto err;
593
594 crypto_wait_for_test(larval);
595 err = 0;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000596
Herbert Xu4cc77202006-08-06 21:16:34 +1000597err:
598 return err;
599}
600EXPORT_SYMBOL_GPL(crypto_register_instance);
601
Herbert Xu87b16752015-04-02 22:39:40 +0800602int crypto_unregister_instance(struct crypto_instance *inst)
Steffen Klassertce3fd842011-11-08 10:09:17 +0100603{
Herbert Xu1f723712015-04-02 22:31:22 +0800604 LIST_HEAD(list);
Steffen Klassertce3fd842011-11-08 10:09:17 +0100605
Steffen Klassertce3fd842011-11-08 10:09:17 +0100606 down_write(&crypto_alg_sem);
607
Herbert Xu87b16752015-04-02 22:39:40 +0800608 crypto_remove_spawns(&inst->alg, &list, NULL);
Herbert Xu1f723712015-04-02 22:31:22 +0800609 crypto_remove_instance(inst, &list);
Steffen Klassertce3fd842011-11-08 10:09:17 +0100610
611 up_write(&crypto_alg_sem);
612
Herbert Xu1f723712015-04-02 22:31:22 +0800613 crypto_remove_final(&list);
Steffen Klassertce3fd842011-11-08 10:09:17 +0100614
615 return 0;
616}
617EXPORT_SYMBOL_GPL(crypto_unregister_instance);
618
Herbert Xu6bfd4802006-09-21 11:39:29 +1000619int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
Herbert Xua73e6992007-04-08 21:31:36 +1000620 struct crypto_instance *inst, u32 mask)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000621{
622 int err = -EAGAIN;
623
Eric Biggers6b476662019-01-06 12:46:06 -0800624 if (WARN_ON_ONCE(inst == NULL))
625 return -EINVAL;
626
Herbert Xu6bfd4802006-09-21 11:39:29 +1000627 spawn->inst = inst;
Herbert Xua73e6992007-04-08 21:31:36 +1000628 spawn->mask = mask;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000629
630 down_write(&crypto_alg_sem);
631 if (!crypto_is_moribund(alg)) {
632 list_add(&spawn->list, &alg->cra_users);
633 spawn->alg = alg;
634 err = 0;
635 }
636 up_write(&crypto_alg_sem);
637
638 return err;
639}
640EXPORT_SYMBOL_GPL(crypto_init_spawn);
641
Herbert Xu97eedce2009-07-08 15:55:52 +0800642int crypto_init_spawn2(struct crypto_spawn *spawn, struct crypto_alg *alg,
643 struct crypto_instance *inst,
644 const struct crypto_type *frontend)
645{
646 int err = -EINVAL;
647
Dan Carpenterc614e102010-05-03 11:08:15 +0800648 if ((alg->cra_flags ^ frontend->type) & frontend->maskset)
Herbert Xu97eedce2009-07-08 15:55:52 +0800649 goto out;
650
651 spawn->frontend = frontend;
652 err = crypto_init_spawn(spawn, alg, inst, frontend->maskset);
653
654out:
655 return err;
656}
657EXPORT_SYMBOL_GPL(crypto_init_spawn2);
658
Herbert Xud6ef2f12015-05-11 17:47:39 +0800659int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name,
660 u32 type, u32 mask)
661{
662 struct crypto_alg *alg;
663 int err;
664
665 alg = crypto_find_alg(name, spawn->frontend, type, mask);
666 if (IS_ERR(alg))
667 return PTR_ERR(alg);
668
669 err = crypto_init_spawn(spawn, alg, spawn->inst, mask);
670 crypto_mod_put(alg);
671 return err;
672}
673EXPORT_SYMBOL_GPL(crypto_grab_spawn);
674
Herbert Xu6bfd4802006-09-21 11:39:29 +1000675void crypto_drop_spawn(struct crypto_spawn *spawn)
676{
Herbert Xu7ede5a52009-07-09 11:34:06 +0800677 if (!spawn->alg)
678 return;
679
Herbert Xu6bfd4802006-09-21 11:39:29 +1000680 down_write(&crypto_alg_sem);
681 list_del(&spawn->list);
682 up_write(&crypto_alg_sem);
683}
684EXPORT_SYMBOL_GPL(crypto_drop_spawn);
685
Herbert Xu97eedce2009-07-08 15:55:52 +0800686static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000687{
688 struct crypto_alg *alg;
689 struct crypto_alg *alg2;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000690
691 down_read(&crypto_alg_sem);
692 alg = spawn->alg;
693 alg2 = alg;
694 if (alg2)
695 alg2 = crypto_mod_get(alg2);
696 up_read(&crypto_alg_sem);
697
698 if (!alg2) {
699 if (alg)
700 crypto_shoot_alg(alg);
701 return ERR_PTR(-EAGAIN);
702 }
703
Herbert Xu97eedce2009-07-08 15:55:52 +0800704 return alg;
705}
706
707struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
708 u32 mask)
709{
710 struct crypto_alg *alg;
711 struct crypto_tfm *tfm;
712
713 alg = crypto_spawn_alg(spawn);
714 if (IS_ERR(alg))
715 return ERR_CAST(alg);
716
Herbert Xu2e306ee2006-12-17 10:05:58 +1100717 tfm = ERR_PTR(-EINVAL);
718 if (unlikely((alg->cra_flags ^ type) & mask))
719 goto out_put_alg;
720
Herbert Xu27d2a332007-01-24 20:50:26 +1100721 tfm = __crypto_alloc_tfm(alg, type, mask);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000722 if (IS_ERR(tfm))
Herbert Xu2e306ee2006-12-17 10:05:58 +1100723 goto out_put_alg;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000724
725 return tfm;
Herbert Xu2e306ee2006-12-17 10:05:58 +1100726
727out_put_alg:
728 crypto_mod_put(alg);
729 return tfm;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000730}
731EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
732
Herbert Xu97eedce2009-07-08 15:55:52 +0800733void *crypto_spawn_tfm2(struct crypto_spawn *spawn)
734{
735 struct crypto_alg *alg;
736 struct crypto_tfm *tfm;
737
738 alg = crypto_spawn_alg(spawn);
739 if (IS_ERR(alg))
740 return ERR_CAST(alg);
741
742 tfm = crypto_create_tfm(alg, spawn->frontend);
743 if (IS_ERR(tfm))
744 goto out_put_alg;
745
746 return tfm;
747
748out_put_alg:
749 crypto_mod_put(alg);
750 return tfm;
751}
752EXPORT_SYMBOL_GPL(crypto_spawn_tfm2);
753
Herbert Xu28259822006-08-06 21:23:26 +1000754int crypto_register_notifier(struct notifier_block *nb)
755{
756 return blocking_notifier_chain_register(&crypto_chain, nb);
757}
758EXPORT_SYMBOL_GPL(crypto_register_notifier);
759
760int crypto_unregister_notifier(struct notifier_block *nb)
761{
762 return blocking_notifier_chain_unregister(&crypto_chain, nb);
763}
764EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
765
Herbert Xuebc610e2007-01-01 18:37:02 +1100766struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000767{
Herbert Xu39e1ee012007-08-29 19:27:26 +0800768 struct rtattr *rta = tb[0];
Herbert Xuebc610e2007-01-01 18:37:02 +1100769 struct crypto_attr_type *algt;
770
771 if (!rta)
772 return ERR_PTR(-ENOENT);
773 if (RTA_PAYLOAD(rta) < sizeof(*algt))
774 return ERR_PTR(-EINVAL);
Herbert Xu39e1ee012007-08-29 19:27:26 +0800775 if (rta->rta_type != CRYPTOA_TYPE)
776 return ERR_PTR(-EINVAL);
Herbert Xuebc610e2007-01-01 18:37:02 +1100777
778 algt = RTA_DATA(rta);
779
780 return algt;
781}
782EXPORT_SYMBOL_GPL(crypto_get_attr_type);
783
784int crypto_check_attr_type(struct rtattr **tb, u32 type)
785{
786 struct crypto_attr_type *algt;
787
788 algt = crypto_get_attr_type(tb);
789 if (IS_ERR(algt))
790 return PTR_ERR(algt);
791
792 if ((algt->type ^ type) & algt->mask)
793 return -EINVAL;
794
795 return 0;
796}
797EXPORT_SYMBOL_GPL(crypto_check_attr_type);
798
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800799const char *crypto_attr_alg_name(struct rtattr *rta)
Herbert Xuebc610e2007-01-01 18:37:02 +1100800{
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000801 struct crypto_attr_alg *alga;
802
Herbert Xuebc610e2007-01-01 18:37:02 +1100803 if (!rta)
804 return ERR_PTR(-ENOENT);
805 if (RTA_PAYLOAD(rta) < sizeof(*alga))
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000806 return ERR_PTR(-EINVAL);
Herbert Xu39e1ee012007-08-29 19:27:26 +0800807 if (rta->rta_type != CRYPTOA_ALG)
808 return ERR_PTR(-EINVAL);
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000809
810 alga = RTA_DATA(rta);
811 alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
812
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800813 return alga->name;
814}
815EXPORT_SYMBOL_GPL(crypto_attr_alg_name);
816
Herbert Xud06854f2009-07-08 17:53:16 +0800817struct crypto_alg *crypto_attr_alg2(struct rtattr *rta,
818 const struct crypto_type *frontend,
819 u32 type, u32 mask)
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800820{
821 const char *name;
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800822
823 name = crypto_attr_alg_name(rta);
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800824 if (IS_ERR(name))
Julia Lawall3e8afe32013-01-22 12:29:26 +0100825 return ERR_CAST(name);
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800826
Herbert Xud06854f2009-07-08 17:53:16 +0800827 return crypto_find_alg(name, frontend, type, mask);
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000828}
Herbert Xud06854f2009-07-08 17:53:16 +0800829EXPORT_SYMBOL_GPL(crypto_attr_alg2);
Herbert Xu3c09f172007-08-30 16:24:15 +0800830
831int crypto_attr_u32(struct rtattr *rta, u32 *num)
832{
833 struct crypto_attr_u32 *nu32;
834
835 if (!rta)
836 return -ENOENT;
837 if (RTA_PAYLOAD(rta) < sizeof(*nu32))
838 return -EINVAL;
839 if (rta->rta_type != CRYPTOA_U32)
840 return -EINVAL;
841
842 nu32 = RTA_DATA(rta);
843 *num = nu32->num;
844
845 return 0;
846}
847EXPORT_SYMBOL_GPL(crypto_attr_u32);
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000848
Herbert Xu32f27c72016-06-29 18:04:13 +0800849int crypto_inst_setname(struct crypto_instance *inst, const char *name,
850 struct crypto_alg *alg)
851{
852 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name,
853 alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
854 return -ENAMETOOLONG;
855
856 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
857 name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
858 return -ENAMETOOLONG;
859
860 return 0;
861}
862EXPORT_SYMBOL_GPL(crypto_inst_setname);
863
Eric Biggers14aa1a82019-01-03 20:16:25 -0800864void *crypto_alloc_instance(const char *name, struct crypto_alg *alg,
865 unsigned int head)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000866{
867 struct crypto_instance *inst;
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800868 char *p;
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000869 int err;
870
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800871 p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn),
872 GFP_KERNEL);
873 if (!p)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000874 return ERR_PTR(-ENOMEM);
875
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800876 inst = (void *)(p + head);
877
Herbert Xu32f27c72016-06-29 18:04:13 +0800878 err = crypto_inst_setname(inst, name, alg);
879 if (err)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000880 goto err_free_inst;
881
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800882 return p;
883
884err_free_inst:
885 kfree(p);
886 return ERR_PTR(err);
887}
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000888EXPORT_SYMBOL_GPL(crypto_alloc_instance);
889
Herbert Xub5b7f082007-04-16 20:48:54 +1000890void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen)
891{
892 INIT_LIST_HEAD(&queue->list);
893 queue->backlog = &queue->list;
894 queue->qlen = 0;
895 queue->max_qlen = max_qlen;
896}
897EXPORT_SYMBOL_GPL(crypto_init_queue);
898
899int crypto_enqueue_request(struct crypto_queue *queue,
900 struct crypto_async_request *request)
901{
902 int err = -EINPROGRESS;
903
904 if (unlikely(queue->qlen >= queue->max_qlen)) {
Gilad Ben-Yossef6b80ea32017-10-18 08:00:33 +0100905 if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
906 err = -ENOSPC;
Herbert Xub5b7f082007-04-16 20:48:54 +1000907 goto out;
Gilad Ben-Yossef6b80ea32017-10-18 08:00:33 +0100908 }
909 err = -EBUSY;
Herbert Xub5b7f082007-04-16 20:48:54 +1000910 if (queue->backlog == &queue->list)
911 queue->backlog = &request->list;
912 }
913
914 queue->qlen++;
915 list_add_tail(&request->list, &queue->list);
916
917out:
918 return err;
919}
920EXPORT_SYMBOL_GPL(crypto_enqueue_request);
921
Herbert Xu31d228c2015-07-08 11:55:30 +0800922struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
Herbert Xub5b7f082007-04-16 20:48:54 +1000923{
924 struct list_head *request;
925
926 if (unlikely(!queue->qlen))
927 return NULL;
928
929 queue->qlen--;
930
931 if (queue->backlog != &queue->list)
932 queue->backlog = queue->backlog->next;
933
934 request = queue->list.next;
935 list_del(request);
936
Herbert Xu31d228c2015-07-08 11:55:30 +0800937 return list_entry(request, struct crypto_async_request, list);
Herbert Xub5b7f082007-04-16 20:48:54 +1000938}
939EXPORT_SYMBOL_GPL(crypto_dequeue_request);
940
Herbert Xu76136362007-11-20 17:26:06 +0800941static inline void crypto_inc_byte(u8 *a, unsigned int size)
942{
943 u8 *b = (a + size);
944 u8 c;
945
946 for (; size; size--) {
947 c = *--b + 1;
948 *b = c;
949 if (c)
950 break;
951 }
952}
953
954void crypto_inc(u8 *a, unsigned int size)
955{
956 __be32 *b = (__be32 *)(a + size);
957 u32 c;
958
Ard Biesheuveldb91af02017-02-05 10:06:12 +0000959 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
Ard Biesheuvel27c539a2017-02-14 21:51:02 +0000960 IS_ALIGNED((unsigned long)b, __alignof__(*b)))
Ard Biesheuveldb91af02017-02-05 10:06:12 +0000961 for (; size >= 4; size -= 4) {
962 c = be32_to_cpu(*--b) + 1;
963 *b = cpu_to_be32(c);
Ard Biesheuvel27c539a2017-02-14 21:51:02 +0000964 if (likely(c))
Ard Biesheuveldb91af02017-02-05 10:06:12 +0000965 return;
966 }
Herbert Xu76136362007-11-20 17:26:06 +0800967
968 crypto_inc_byte(a, size);
969}
970EXPORT_SYMBOL_GPL(crypto_inc);
971
Ard Biesheuvela7c391f2017-07-24 11:28:03 +0100972void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int len)
Herbert Xu76136362007-11-20 17:26:06 +0800973{
Ard Biesheuveldb91af02017-02-05 10:06:12 +0000974 int relalign = 0;
975
976 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) {
977 int size = sizeof(unsigned long);
Ard Biesheuvela7c391f2017-07-24 11:28:03 +0100978 int d = (((unsigned long)dst ^ (unsigned long)src1) |
979 ((unsigned long)dst ^ (unsigned long)src2)) &
980 (size - 1);
Ard Biesheuveldb91af02017-02-05 10:06:12 +0000981
982 relalign = d ? 1 << __ffs(d) : size;
983
984 /*
985 * If we care about alignment, process as many bytes as
986 * needed to advance dst and src to values whose alignments
987 * equal their relative alignment. This will allow us to
988 * process the remainder of the input using optimal strides.
989 */
990 while (((unsigned long)dst & (relalign - 1)) && len > 0) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +0100991 *dst++ = *src1++ ^ *src2++;
Ard Biesheuveldb91af02017-02-05 10:06:12 +0000992 len--;
993 }
994 }
995
996 while (IS_ENABLED(CONFIG_64BIT) && len >= 8 && !(relalign & 7)) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +0100997 *(u64 *)dst = *(u64 *)src1 ^ *(u64 *)src2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +0000998 dst += 8;
Ard Biesheuvela7c391f2017-07-24 11:28:03 +0100999 src1 += 8;
1000 src2 += 8;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001001 len -= 8;
1002 }
1003
1004 while (len >= 4 && !(relalign & 3)) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001005 *(u32 *)dst = *(u32 *)src1 ^ *(u32 *)src2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001006 dst += 4;
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001007 src1 += 4;
1008 src2 += 4;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001009 len -= 4;
1010 }
1011
1012 while (len >= 2 && !(relalign & 1)) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001013 *(u16 *)dst = *(u16 *)src1 ^ *(u16 *)src2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001014 dst += 2;
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001015 src1 += 2;
1016 src2 += 2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001017 len -= 2;
1018 }
1019
1020 while (len--)
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001021 *dst++ = *src1++ ^ *src2++;
Herbert Xu76136362007-11-20 17:26:06 +08001022}
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001023EXPORT_SYMBOL_GPL(__crypto_xor);
Herbert Xu76136362007-11-20 17:26:06 +08001024
Herbert Xu38d21432015-04-20 13:39:00 +08001025unsigned int crypto_alg_extsize(struct crypto_alg *alg)
1026{
Herbert Xuc2110f22015-05-28 22:07:56 +08001027 return alg->cra_ctxsize +
1028 (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
Herbert Xu38d21432015-04-20 13:39:00 +08001029}
1030EXPORT_SYMBOL_GPL(crypto_alg_extsize);
1031
Herbert Xuf2aefda2016-01-23 13:51:01 +08001032int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
1033 u32 type, u32 mask)
1034{
1035 int ret = 0;
1036 struct crypto_alg *alg = crypto_find_alg(name, frontend, type, mask);
1037
1038 if (!IS_ERR(alg)) {
1039 crypto_mod_put(alg);
1040 ret = 1;
1041 }
1042
1043 return ret;
1044}
1045EXPORT_SYMBOL_GPL(crypto_type_has_alg);
1046
Corentin Labbef7d76e02018-11-29 14:42:21 +00001047#ifdef CONFIG_CRYPTO_STATS
Corentin Labbe1f6669b2018-11-29 14:42:26 +00001048void crypto_stats_init(struct crypto_alg *alg)
1049{
1050 memset(&alg->stats, 0, sizeof(alg->stats));
1051}
1052EXPORT_SYMBOL_GPL(crypto_stats_init);
1053
Corentin Labbef7d76e02018-11-29 14:42:21 +00001054void crypto_stats_get(struct crypto_alg *alg)
1055{
1056 crypto_alg_get(alg);
1057}
1058EXPORT_SYMBOL_GPL(crypto_stats_get);
1059
1060void crypto_stats_ablkcipher_encrypt(unsigned int nbytes, int ret,
1061 struct crypto_alg *alg)
1062{
1063 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001064 atomic64_inc(&alg->stats.cipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001065 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001066 atomic64_inc(&alg->stats.cipher.encrypt_cnt);
1067 atomic64_add(nbytes, &alg->stats.cipher.encrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001068 }
1069 crypto_alg_put(alg);
1070}
1071EXPORT_SYMBOL_GPL(crypto_stats_ablkcipher_encrypt);
1072
1073void crypto_stats_ablkcipher_decrypt(unsigned int nbytes, int ret,
1074 struct crypto_alg *alg)
1075{
1076 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001077 atomic64_inc(&alg->stats.cipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001078 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001079 atomic64_inc(&alg->stats.cipher.decrypt_cnt);
1080 atomic64_add(nbytes, &alg->stats.cipher.decrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001081 }
1082 crypto_alg_put(alg);
1083}
1084EXPORT_SYMBOL_GPL(crypto_stats_ablkcipher_decrypt);
1085
1086void crypto_stats_aead_encrypt(unsigned int cryptlen, struct crypto_alg *alg,
1087 int ret)
1088{
1089 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001090 atomic64_inc(&alg->stats.aead.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001091 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001092 atomic64_inc(&alg->stats.aead.encrypt_cnt);
1093 atomic64_add(cryptlen, &alg->stats.aead.encrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001094 }
1095 crypto_alg_put(alg);
1096}
1097EXPORT_SYMBOL_GPL(crypto_stats_aead_encrypt);
1098
1099void crypto_stats_aead_decrypt(unsigned int cryptlen, struct crypto_alg *alg,
1100 int ret)
1101{
1102 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001103 atomic64_inc(&alg->stats.aead.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001104 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001105 atomic64_inc(&alg->stats.aead.decrypt_cnt);
1106 atomic64_add(cryptlen, &alg->stats.aead.decrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001107 }
1108 crypto_alg_put(alg);
1109}
1110EXPORT_SYMBOL_GPL(crypto_stats_aead_decrypt);
1111
1112void crypto_stats_akcipher_encrypt(unsigned int src_len, int ret,
1113 struct crypto_alg *alg)
1114{
1115 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001116 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001117 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001118 atomic64_inc(&alg->stats.akcipher.encrypt_cnt);
1119 atomic64_add(src_len, &alg->stats.akcipher.encrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001120 }
1121 crypto_alg_put(alg);
1122}
1123EXPORT_SYMBOL_GPL(crypto_stats_akcipher_encrypt);
1124
1125void crypto_stats_akcipher_decrypt(unsigned int src_len, int ret,
1126 struct crypto_alg *alg)
1127{
1128 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001129 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001130 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001131 atomic64_inc(&alg->stats.akcipher.decrypt_cnt);
1132 atomic64_add(src_len, &alg->stats.akcipher.decrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001133 }
1134 crypto_alg_put(alg);
1135}
1136EXPORT_SYMBOL_GPL(crypto_stats_akcipher_decrypt);
1137
1138void crypto_stats_akcipher_sign(int ret, struct crypto_alg *alg)
1139{
1140 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001141 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001142 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001143 atomic64_inc(&alg->stats.akcipher.sign_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001144 crypto_alg_put(alg);
1145}
1146EXPORT_SYMBOL_GPL(crypto_stats_akcipher_sign);
1147
1148void crypto_stats_akcipher_verify(int ret, struct crypto_alg *alg)
1149{
1150 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001151 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001152 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001153 atomic64_inc(&alg->stats.akcipher.verify_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001154 crypto_alg_put(alg);
1155}
1156EXPORT_SYMBOL_GPL(crypto_stats_akcipher_verify);
1157
1158void crypto_stats_compress(unsigned int slen, int ret, struct crypto_alg *alg)
1159{
1160 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001161 atomic64_inc(&alg->stats.compress.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001162 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001163 atomic64_inc(&alg->stats.compress.compress_cnt);
1164 atomic64_add(slen, &alg->stats.compress.compress_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001165 }
1166 crypto_alg_put(alg);
1167}
1168EXPORT_SYMBOL_GPL(crypto_stats_compress);
1169
1170void crypto_stats_decompress(unsigned int slen, int ret, struct crypto_alg *alg)
1171{
1172 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001173 atomic64_inc(&alg->stats.compress.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001174 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001175 atomic64_inc(&alg->stats.compress.decompress_cnt);
1176 atomic64_add(slen, &alg->stats.compress.decompress_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001177 }
1178 crypto_alg_put(alg);
1179}
1180EXPORT_SYMBOL_GPL(crypto_stats_decompress);
1181
1182void crypto_stats_ahash_update(unsigned int nbytes, int ret,
1183 struct crypto_alg *alg)
1184{
1185 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001186 atomic64_inc(&alg->stats.hash.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001187 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001188 atomic64_add(nbytes, &alg->stats.hash.hash_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001189 crypto_alg_put(alg);
1190}
1191EXPORT_SYMBOL_GPL(crypto_stats_ahash_update);
1192
1193void crypto_stats_ahash_final(unsigned int nbytes, int ret,
1194 struct crypto_alg *alg)
1195{
1196 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001197 atomic64_inc(&alg->stats.hash.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001198 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001199 atomic64_inc(&alg->stats.hash.hash_cnt);
1200 atomic64_add(nbytes, &alg->stats.hash.hash_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001201 }
1202 crypto_alg_put(alg);
1203}
1204EXPORT_SYMBOL_GPL(crypto_stats_ahash_final);
1205
1206void crypto_stats_kpp_set_secret(struct crypto_alg *alg, int ret)
1207{
1208 if (ret)
Corentin Labbe44f13132018-11-29 14:42:25 +00001209 atomic64_inc(&alg->stats.kpp.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001210 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001211 atomic64_inc(&alg->stats.kpp.setsecret_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001212 crypto_alg_put(alg);
1213}
1214EXPORT_SYMBOL_GPL(crypto_stats_kpp_set_secret);
1215
1216void crypto_stats_kpp_generate_public_key(struct crypto_alg *alg, int ret)
1217{
1218 if (ret)
Corentin Labbe44f13132018-11-29 14:42:25 +00001219 atomic64_inc(&alg->stats.kpp.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001220 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001221 atomic64_inc(&alg->stats.kpp.generate_public_key_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001222 crypto_alg_put(alg);
1223}
1224EXPORT_SYMBOL_GPL(crypto_stats_kpp_generate_public_key);
1225
1226void crypto_stats_kpp_compute_shared_secret(struct crypto_alg *alg, int ret)
1227{
1228 if (ret)
Corentin Labbe44f13132018-11-29 14:42:25 +00001229 atomic64_inc(&alg->stats.kpp.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001230 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001231 atomic64_inc(&alg->stats.kpp.compute_shared_secret_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001232 crypto_alg_put(alg);
1233}
1234EXPORT_SYMBOL_GPL(crypto_stats_kpp_compute_shared_secret);
1235
1236void crypto_stats_rng_seed(struct crypto_alg *alg, int ret)
1237{
1238 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001239 atomic64_inc(&alg->stats.rng.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001240 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001241 atomic64_inc(&alg->stats.rng.seed_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001242 crypto_alg_put(alg);
1243}
1244EXPORT_SYMBOL_GPL(crypto_stats_rng_seed);
1245
1246void crypto_stats_rng_generate(struct crypto_alg *alg, unsigned int dlen,
1247 int ret)
1248{
1249 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001250 atomic64_inc(&alg->stats.rng.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001251 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001252 atomic64_inc(&alg->stats.rng.generate_cnt);
1253 atomic64_add(dlen, &alg->stats.rng.generate_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001254 }
1255 crypto_alg_put(alg);
1256}
1257EXPORT_SYMBOL_GPL(crypto_stats_rng_generate);
1258
1259void crypto_stats_skcipher_encrypt(unsigned int cryptlen, int ret,
1260 struct crypto_alg *alg)
1261{
1262 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001263 atomic64_inc(&alg->stats.cipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001264 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001265 atomic64_inc(&alg->stats.cipher.encrypt_cnt);
1266 atomic64_add(cryptlen, &alg->stats.cipher.encrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001267 }
1268 crypto_alg_put(alg);
1269}
1270EXPORT_SYMBOL_GPL(crypto_stats_skcipher_encrypt);
1271
1272void crypto_stats_skcipher_decrypt(unsigned int cryptlen, int ret,
1273 struct crypto_alg *alg)
1274{
1275 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001276 atomic64_inc(&alg->stats.cipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001277 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001278 atomic64_inc(&alg->stats.cipher.decrypt_cnt);
1279 atomic64_add(cryptlen, &alg->stats.cipher.decrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001280 }
1281 crypto_alg_put(alg);
1282}
1283EXPORT_SYMBOL_GPL(crypto_stats_skcipher_decrypt);
1284#endif
1285
Herbert Xucce9e062006-08-21 21:08:13 +10001286static int __init crypto_algapi_init(void)
1287{
1288 crypto_init_proc();
1289 return 0;
1290}
1291
1292static void __exit crypto_algapi_exit(void)
1293{
1294 crypto_exit_proc();
1295}
1296
1297module_init(crypto_algapi_init);
1298module_exit(crypto_algapi_exit);
1299
1300MODULE_LICENSE("GPL");
1301MODULE_DESCRIPTION("Cryptographic algorithms API");