blob: a25ce02918f8a01109478f8771df52ddbe0d3131 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Herbert Xucce9e062006-08-21 21:08:13 +10002/*
3 * Cryptographic API for algorithms (i.e., low-level API).
4 *
5 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
Herbert Xucce9e062006-08-21 21:08:13 +10006 */
7
Salvatore Mesoraca13c935b2018-04-09 15:54:46 +02008#include <crypto/algapi.h>
Herbert Xu6bfd4802006-09-21 11:39:29 +10009#include <linux/err.h>
Herbert Xucce9e062006-08-21 21:08:13 +100010#include <linux/errno.h>
Herbert Xu3133d762015-04-22 13:25:53 +080011#include <linux/fips.h>
Herbert Xucce9e062006-08-21 21:08:13 +100012#include <linux/init.h>
13#include <linux/kernel.h>
Herbert Xu4cc77202006-08-06 21:16:34 +100014#include <linux/list.h>
Herbert Xucce9e062006-08-21 21:08:13 +100015#include <linux/module.h>
Herbert Xu7fed0bf2006-08-06 23:10:45 +100016#include <linux/rtnetlink.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Herbert Xucce9e062006-08-21 21:08:13 +100018#include <linux/string.h>
19
20#include "internal.h"
21
Herbert Xu4cc77202006-08-06 21:16:34 +100022static LIST_HEAD(crypto_template_list);
23
Jarod Wilson002c77a2014-07-02 15:37:30 -040024static inline void crypto_check_module_sig(struct module *mod)
25{
Herbert Xu59afdc72015-04-22 11:28:46 +080026 if (fips_enabled && mod && !module_sig_ok(mod))
Jarod Wilson002c77a2014-07-02 15:37:30 -040027 panic("Module %s signature verification failed in FIPS mode\n",
Herbert Xubd4a7c62015-04-23 14:48:05 +080028 module_name(mod));
Jarod Wilson002c77a2014-07-02 15:37:30 -040029}
30
Herbert Xu4cc77202006-08-06 21:16:34 +100031static int crypto_check_alg(struct crypto_alg *alg)
Herbert Xucce9e062006-08-21 21:08:13 +100032{
Jarod Wilson002c77a2014-07-02 15:37:30 -040033 crypto_check_module_sig(alg->cra_module);
34
Eric Biggers177f87d2019-06-02 22:40:58 -070035 if (!alg->cra_name[0] || !alg->cra_driver_name[0])
36 return -EINVAL;
37
Herbert Xucce9e062006-08-21 21:08:13 +100038 if (alg->cra_alignmask & (alg->cra_alignmask + 1))
39 return -EINVAL;
40
Kees Cooka9f7f882018-08-07 14:18:40 -070041 /* General maximums for all algs. */
42 if (alg->cra_alignmask > MAX_ALGAPI_ALIGNMASK)
Herbert Xucce9e062006-08-21 21:08:13 +100043 return -EINVAL;
44
Kees Cooka9f7f882018-08-07 14:18:40 -070045 if (alg->cra_blocksize > MAX_ALGAPI_BLOCKSIZE)
46 return -EINVAL;
47
48 /* Lower maximums for specific alg types. */
Salvatore Mesoraca13c935b2018-04-09 15:54:46 +020049 if (!alg->cra_type && (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
50 CRYPTO_ALG_TYPE_CIPHER) {
51 if (alg->cra_alignmask > MAX_CIPHER_ALIGNMASK)
52 return -EINVAL;
53
54 if (alg->cra_blocksize > MAX_CIPHER_BLOCKSIZE)
55 return -EINVAL;
56 }
57
Herbert Xucce9e062006-08-21 21:08:13 +100058 if (alg->cra_priority < 0)
59 return -EINVAL;
Herbert Xucce9e062006-08-21 21:08:13 +100060
Eric Biggersce8614a2017-12-29 10:00:46 -060061 refcount_set(&alg->cra_refcnt, 1);
Herbert Xue9b8e5b2015-04-09 17:40:35 +080062
Eric Biggers177f87d2019-06-02 22:40:58 -070063 return 0;
Herbert Xu4cc77202006-08-06 21:16:34 +100064}
65
Herbert Xu319382a2015-07-09 07:17:15 +080066static void crypto_free_instance(struct crypto_instance *inst)
67{
68 if (!inst->alg.cra_type->free) {
69 inst->tmpl->free(inst);
70 return;
71 }
72
73 inst->alg.cra_type->free(inst);
74}
75
Herbert Xu6bfd4802006-09-21 11:39:29 +100076static void crypto_destroy_instance(struct crypto_alg *alg)
77{
78 struct crypto_instance *inst = (void *)alg;
79 struct crypto_template *tmpl = inst->tmpl;
80
Herbert Xu319382a2015-07-09 07:17:15 +080081 crypto_free_instance(inst);
Herbert Xu6bfd4802006-09-21 11:39:29 +100082 crypto_tmpl_put(tmpl);
83}
84
Herbert Xu02244ba2019-12-07 22:33:51 +080085/*
86 * This function adds a spawn to the list secondary_spawns which
87 * will be used at the end of crypto_remove_spawns to unregister
88 * instances, unless the spawn happens to be one that is depended
89 * on by the new algorithm (nalg in crypto_remove_spawns).
90 *
91 * This function is also responsible for resurrecting any algorithms
92 * in the dependency chain of nalg by unsetting n->dead.
93 */
Herbert Xu2bf29012009-08-31 15:56:54 +100094static struct list_head *crypto_more_spawns(struct crypto_alg *alg,
95 struct list_head *stack,
96 struct list_head *top,
97 struct list_head *secondary_spawns)
98{
99 struct crypto_spawn *spawn, *n;
100
Geliang Tang304e4812015-11-16 22:37:14 +0800101 spawn = list_first_entry_or_null(stack, struct crypto_spawn, list);
102 if (!spawn)
Herbert Xu2bf29012009-08-31 15:56:54 +1000103 return NULL;
104
Herbert Xu4f87ee12019-12-07 22:15:17 +0800105 n = list_prev_entry(spawn, list);
Herbert Xu2bf29012009-08-31 15:56:54 +1000106 list_move(&spawn->list, secondary_spawns);
107
Herbert Xu4f87ee12019-12-07 22:15:17 +0800108 if (list_is_last(&n->list, stack))
109 return top;
110
111 n = list_next_entry(n, list);
112 if (!spawn->dead)
113 n->dead = false;
114
115 return &n->inst->alg.cra_users;
Herbert Xu2bf29012009-08-31 15:56:54 +1000116}
117
Herbert Xu1f723712015-04-02 22:31:22 +0800118static void crypto_remove_instance(struct crypto_instance *inst,
119 struct list_head *list)
Herbert Xua73e6992007-04-08 21:31:36 +1000120{
Herbert Xua73e6992007-04-08 21:31:36 +1000121 struct crypto_template *tmpl = inst->tmpl;
122
Herbert Xua73e6992007-04-08 21:31:36 +1000123 if (crypto_is_dead(&inst->alg))
124 return;
125
126 inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
Herbert Xu38cb2412007-11-17 22:09:38 +0800127
Herbert Xua73e6992007-04-08 21:31:36 +1000128 if (!tmpl || !crypto_tmpl_get(tmpl))
129 return;
130
Herbert Xua73e6992007-04-08 21:31:36 +1000131 list_move(&inst->alg.cra_list, list);
132 hlist_del(&inst->list);
133 inst->alg.cra_destroy = crypto_destroy_instance;
134
Herbert Xu2bf29012009-08-31 15:56:54 +1000135 BUG_ON(!list_empty(&inst->alg.cra_users));
Herbert Xua73e6992007-04-08 21:31:36 +1000136}
137
Herbert Xu02244ba2019-12-07 22:33:51 +0800138/*
139 * Given an algorithm alg, remove all algorithms that depend on it
140 * through spawns. If nalg is not null, then exempt any algorithms
141 * that is depended on by nalg. This is useful when nalg itself
142 * depends on alg.
143 */
Steffen Klassert89b596b2011-09-27 07:22:08 +0200144void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
145 struct crypto_alg *nalg)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000146{
Herbert Xu2bf29012009-08-31 15:56:54 +1000147 u32 new_type = (nalg ?: alg)->cra_flags;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000148 struct crypto_spawn *spawn, *n;
Herbert Xua73e6992007-04-08 21:31:36 +1000149 LIST_HEAD(secondary_spawns);
Herbert Xu2bf29012009-08-31 15:56:54 +1000150 struct list_head *spawns;
151 LIST_HEAD(stack);
152 LIST_HEAD(top);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000153
Herbert Xu2bf29012009-08-31 15:56:54 +1000154 spawns = &alg->cra_users;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000155 list_for_each_entry_safe(spawn, n, spawns, list) {
Herbert Xua73e6992007-04-08 21:31:36 +1000156 if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000157 continue;
158
Herbert Xu2bf29012009-08-31 15:56:54 +1000159 list_move(&spawn->list, &top);
Herbert Xua73e6992007-04-08 21:31:36 +1000160 }
Herbert Xu6bfd4802006-09-21 11:39:29 +1000161
Herbert Xu02244ba2019-12-07 22:33:51 +0800162 /*
163 * Perform a depth-first walk starting from alg through
164 * the cra_users tree. The list stack records the path
165 * from alg to the current spawn.
166 */
Herbert Xu2bf29012009-08-31 15:56:54 +1000167 spawns = &top;
168 do {
169 while (!list_empty(spawns)) {
170 struct crypto_instance *inst;
171
172 spawn = list_first_entry(spawns, struct crypto_spawn,
173 list);
174 inst = spawn->inst;
175
Herbert Xu2bf29012009-08-31 15:56:54 +1000176 list_move(&spawn->list, &stack);
Herbert Xu5f567ff2019-12-18 15:53:01 +0800177 spawn->dead = !spawn->registered || &inst->alg != nalg;
178
179 if (!spawn->registered)
180 break;
181
182 BUG_ON(&inst->alg == alg);
Herbert Xu2bf29012009-08-31 15:56:54 +1000183
184 if (&inst->alg == nalg)
185 break;
186
Herbert Xu2bf29012009-08-31 15:56:54 +1000187 spawns = &inst->alg.cra_users;
Eric Biggers9a006742017-12-29 14:30:19 -0600188
189 /*
Herbert Xu5f567ff2019-12-18 15:53:01 +0800190 * Even if spawn->registered is true, the
191 * instance itself may still be unregistered.
192 * This is because it may have failed during
193 * registration. Therefore we still need to
194 * make the following test.
195 *
Eric Biggers9a006742017-12-29 14:30:19 -0600196 * We may encounter an unregistered instance here, since
197 * an instance's spawns are set up prior to the instance
198 * being registered. An unregistered instance will have
199 * NULL ->cra_users.next, since ->cra_users isn't
200 * properly initialized until registration. But an
201 * unregistered instance cannot have any users, so treat
202 * it the same as ->cra_users being empty.
203 */
204 if (spawns->next == NULL)
205 break;
Herbert Xu2bf29012009-08-31 15:56:54 +1000206 }
207 } while ((spawns = crypto_more_spawns(alg, &stack, &top,
208 &secondary_spawns)));
209
Herbert Xu02244ba2019-12-07 22:33:51 +0800210 /*
211 * Remove all instances that are marked as dead. Also
212 * complete the resurrection of the others by moving them
213 * back to the cra_users list.
214 */
Herbert Xu2bf29012009-08-31 15:56:54 +1000215 list_for_each_entry_safe(spawn, n, &secondary_spawns, list) {
Herbert Xu4f87ee12019-12-07 22:15:17 +0800216 if (!spawn->dead)
Herbert Xu2bf29012009-08-31 15:56:54 +1000217 list_move(&spawn->list, &spawn->alg->cra_users);
Herbert Xu5f567ff2019-12-18 15:53:01 +0800218 else if (spawn->registered)
Herbert Xu1f723712015-04-02 22:31:22 +0800219 crypto_remove_instance(spawn->inst, list);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000220 }
221}
Steffen Klassert89b596b2011-09-27 07:22:08 +0200222EXPORT_SYMBOL_GPL(crypto_remove_spawns);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000223
Herbert Xu73d38642008-08-03 21:15:23 +0800224static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
Herbert Xu4cc77202006-08-06 21:16:34 +1000225{
226 struct crypto_alg *q;
Herbert Xu73d38642008-08-03 21:15:23 +0800227 struct crypto_larval *larval;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000228 int ret = -EAGAIN;
229
230 if (crypto_is_dead(alg))
Herbert Xu73d38642008-08-03 21:15:23 +0800231 goto err;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000232
233 INIT_LIST_HEAD(&alg->cra_users);
234
Herbert Xu73d38642008-08-03 21:15:23 +0800235 /* No cheating! */
236 alg->cra_flags &= ~CRYPTO_ALG_TESTED;
237
Herbert Xu6bfd4802006-09-21 11:39:29 +1000238 ret = -EEXIST;
Herbert Xu4cc77202006-08-06 21:16:34 +1000239
Herbert Xucce9e062006-08-21 21:08:13 +1000240 list_for_each_entry(q, &crypto_alg_list, cra_list) {
Herbert Xu4cc77202006-08-06 21:16:34 +1000241 if (q == alg)
Herbert Xu73d38642008-08-03 21:15:23 +0800242 goto err;
243
Herbert Xub8e15992009-01-28 14:09:59 +1100244 if (crypto_is_moribund(q))
245 continue;
246
Herbert Xu73d38642008-08-03 21:15:23 +0800247 if (crypto_is_larval(q)) {
248 if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
249 goto err;
250 continue;
251 }
252
253 if (!strcmp(q->cra_driver_name, alg->cra_name) ||
254 !strcmp(q->cra_name, alg->cra_driver_name))
255 goto err;
256 }
257
258 larval = crypto_larval_alloc(alg->cra_name,
259 alg->cra_flags | CRYPTO_ALG_TESTED, 0);
260 if (IS_ERR(larval))
261 goto out;
262
263 ret = -ENOENT;
264 larval->adult = crypto_mod_get(alg);
265 if (!larval->adult)
266 goto free_larval;
267
Eric Biggersce8614a2017-12-29 10:00:46 -0600268 refcount_set(&larval->alg.cra_refcnt, 1);
Herbert Xu73d38642008-08-03 21:15:23 +0800269 memcpy(larval->alg.cra_driver_name, alg->cra_driver_name,
270 CRYPTO_MAX_ALG_NAME);
271 larval->alg.cra_priority = alg->cra_priority;
272
273 list_add(&alg->cra_list, &crypto_alg_list);
274 list_add(&larval->alg.cra_list, &crypto_alg_list);
275
Corentin Labbe1f6669b2018-11-29 14:42:26 +0000276 crypto_stats_init(alg);
Corentin Labbecac58182018-09-19 10:10:54 +0000277
Richard Hartmann5357c6c2010-02-16 20:25:21 +0800278out:
Herbert Xu73d38642008-08-03 21:15:23 +0800279 return larval;
280
281free_larval:
282 kfree(larval);
283err:
284 larval = ERR_PTR(ret);
285 goto out;
286}
287
288void crypto_alg_tested(const char *name, int err)
289{
290 struct crypto_larval *test;
291 struct crypto_alg *alg;
292 struct crypto_alg *q;
293 LIST_HEAD(list);
Herbert Xu2bbb3372019-12-11 10:50:11 +0800294 bool best;
Herbert Xu73d38642008-08-03 21:15:23 +0800295
296 down_write(&crypto_alg_sem);
297 list_for_each_entry(q, &crypto_alg_list, cra_list) {
Herbert Xub8e15992009-01-28 14:09:59 +1100298 if (crypto_is_moribund(q) || !crypto_is_larval(q))
Herbert Xu73d38642008-08-03 21:15:23 +0800299 continue;
300
301 test = (struct crypto_larval *)q;
302
303 if (!strcmp(q->cra_driver_name, name))
304 goto found;
305 }
306
Karim Eshapac7235852017-05-13 21:05:19 +0200307 pr_err("alg: Unexpected test result for %s: %d\n", name, err);
Herbert Xu73d38642008-08-03 21:15:23 +0800308 goto unlock;
309
310found:
Herbert Xub8e15992009-01-28 14:09:59 +1100311 q->cra_flags |= CRYPTO_ALG_DEAD;
Herbert Xu73d38642008-08-03 21:15:23 +0800312 alg = test->adult;
313 if (err || list_empty(&alg->cra_list))
314 goto complete;
315
316 alg->cra_flags |= CRYPTO_ALG_TESTED;
317
Herbert Xu2bbb3372019-12-11 10:50:11 +0800318 /* Only satisfy larval waiters if we are the best. */
319 best = true;
320 list_for_each_entry(q, &crypto_alg_list, cra_list) {
321 if (crypto_is_moribund(q) || !crypto_is_larval(q))
322 continue;
323
324 if (strcmp(alg->cra_name, q->cra_name))
325 continue;
326
327 if (q->cra_priority > alg->cra_priority) {
328 best = false;
329 break;
330 }
331 }
332
Herbert Xu73d38642008-08-03 21:15:23 +0800333 list_for_each_entry(q, &crypto_alg_list, cra_list) {
334 if (q == alg)
335 continue;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000336
337 if (crypto_is_moribund(q))
338 continue;
339
340 if (crypto_is_larval(q)) {
Herbert Xu28259822006-08-06 21:23:26 +1000341 struct crypto_larval *larval = (void *)q;
342
Herbert Xud8058482007-10-02 22:27:29 +0800343 /*
344 * Check to see if either our generic name or
345 * specific name can satisfy the name requested
346 * by the larval entry q.
347 */
Herbert Xu6bfd4802006-09-21 11:39:29 +1000348 if (strcmp(alg->cra_name, q->cra_name) &&
349 strcmp(alg->cra_driver_name, q->cra_name))
350 continue;
351
352 if (larval->adult)
353 continue;
Herbert Xu492e2b62006-09-21 11:35:17 +1000354 if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
355 continue;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000356
Herbert Xu2bbb3372019-12-11 10:50:11 +0800357 if (best && crypto_mod_get(alg))
358 larval->adult = alg;
359 else
360 larval->adult = ERR_PTR(-EAGAIN);
361
Herbert Xu6bfd4802006-09-21 11:39:29 +1000362 continue;
Herbert Xu28259822006-08-06 21:23:26 +1000363 }
Herbert Xu6bfd4802006-09-21 11:39:29 +1000364
365 if (strcmp(alg->cra_name, q->cra_name))
366 continue;
367
368 if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
369 q->cra_priority > alg->cra_priority)
370 continue;
371
Herbert Xu2bf29012009-08-31 15:56:54 +1000372 crypto_remove_spawns(q, &list, alg);
Herbert Xucce9e062006-08-21 21:08:13 +1000373 }
Herbert Xu28259822006-08-06 21:23:26 +1000374
Herbert Xu73d38642008-08-03 21:15:23 +0800375complete:
376 complete_all(&test->completion);
Herbert Xu28259822006-08-06 21:23:26 +1000377
Herbert Xu73d38642008-08-03 21:15:23 +0800378unlock:
379 up_write(&crypto_alg_sem);
380
381 crypto_remove_final(&list);
Herbert Xucce9e062006-08-21 21:08:13 +1000382}
Herbert Xu73d38642008-08-03 21:15:23 +0800383EXPORT_SYMBOL_GPL(crypto_alg_tested);
Herbert Xu4cc77202006-08-06 21:16:34 +1000384
Steffen Klassert22e5b202011-09-27 07:23:07 +0200385void crypto_remove_final(struct list_head *list)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000386{
387 struct crypto_alg *alg;
388 struct crypto_alg *n;
389
390 list_for_each_entry_safe(alg, n, list, cra_list) {
391 list_del_init(&alg->cra_list);
392 crypto_alg_put(alg);
393 }
394}
Steffen Klassert22e5b202011-09-27 07:23:07 +0200395EXPORT_SYMBOL_GPL(crypto_remove_final);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000396
Herbert Xu73d38642008-08-03 21:15:23 +0800397static void crypto_wait_for_test(struct crypto_larval *larval)
398{
399 int err;
400
401 err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
402 if (err != NOTIFY_STOP) {
403 if (WARN_ON(err != NOTIFY_DONE))
404 goto out;
405 crypto_alg_tested(larval->alg.cra_driver_name, 0);
406 }
407
Herbert Xu3fc89ad2015-10-19 18:23:57 +0800408 err = wait_for_completion_killable(&larval->completion);
Herbert Xu73d38642008-08-03 21:15:23 +0800409 WARN_ON(err);
Martin K. Petersendd8b0832018-08-30 11:00:14 -0400410 if (!err)
411 crypto_probing_notify(CRYPTO_MSG_ALG_LOADED, larval);
Herbert Xu73d38642008-08-03 21:15:23 +0800412
413out:
414 crypto_larval_kill(&larval->alg);
415}
416
Herbert Xu4cc77202006-08-06 21:16:34 +1000417int crypto_register_alg(struct crypto_alg *alg)
418{
Herbert Xu73d38642008-08-03 21:15:23 +0800419 struct crypto_larval *larval;
Herbert Xu4cc77202006-08-06 21:16:34 +1000420 int err;
421
Salvatore Benedettod6040762017-01-13 11:54:08 +0000422 alg->cra_flags &= ~CRYPTO_ALG_DEAD;
Herbert Xu4cc77202006-08-06 21:16:34 +1000423 err = crypto_check_alg(alg);
424 if (err)
425 return err;
426
427 down_write(&crypto_alg_sem);
Herbert Xu73d38642008-08-03 21:15:23 +0800428 larval = __crypto_register_alg(alg);
Herbert Xu4cc77202006-08-06 21:16:34 +1000429 up_write(&crypto_alg_sem);
430
Herbert Xu73d38642008-08-03 21:15:23 +0800431 if (IS_ERR(larval))
432 return PTR_ERR(larval);
433
434 crypto_wait_for_test(larval);
435 return 0;
Herbert Xu4cc77202006-08-06 21:16:34 +1000436}
Herbert Xucce9e062006-08-21 21:08:13 +1000437EXPORT_SYMBOL_GPL(crypto_register_alg);
438
Herbert Xu6bfd4802006-09-21 11:39:29 +1000439static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
440{
441 if (unlikely(list_empty(&alg->cra_list)))
442 return -ENOENT;
443
444 alg->cra_flags |= CRYPTO_ALG_DEAD;
445
Herbert Xu6bfd4802006-09-21 11:39:29 +1000446 list_del_init(&alg->cra_list);
Herbert Xu2bf29012009-08-31 15:56:54 +1000447 crypto_remove_spawns(alg, list, NULL);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000448
449 return 0;
450}
451
Eric Biggersc6d633a2019-12-15 15:51:19 -0800452void crypto_unregister_alg(struct crypto_alg *alg)
Herbert Xucce9e062006-08-21 21:08:13 +1000453{
Herbert Xu6bfd4802006-09-21 11:39:29 +1000454 int ret;
455 LIST_HEAD(list);
Richard Hartmann5357c6c2010-02-16 20:25:21 +0800456
Herbert Xucce9e062006-08-21 21:08:13 +1000457 down_write(&crypto_alg_sem);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000458 ret = crypto_remove_alg(alg, &list);
Herbert Xucce9e062006-08-21 21:08:13 +1000459 up_write(&crypto_alg_sem);
460
Eric Biggersc6d633a2019-12-15 15:51:19 -0800461 if (WARN(ret, "Algorithm %s is not registered", alg->cra_driver_name))
462 return;
Herbert Xucce9e062006-08-21 21:08:13 +1000463
Eric Biggersce8614a2017-12-29 10:00:46 -0600464 BUG_ON(refcount_read(&alg->cra_refcnt) != 1);
Herbert Xucce9e062006-08-21 21:08:13 +1000465 if (alg->cra_destroy)
466 alg->cra_destroy(alg);
467
Herbert Xu6bfd4802006-09-21 11:39:29 +1000468 crypto_remove_final(&list);
Herbert Xucce9e062006-08-21 21:08:13 +1000469}
470EXPORT_SYMBOL_GPL(crypto_unregister_alg);
471
Mark Brown4b004342012-01-17 23:34:26 +0000472int crypto_register_algs(struct crypto_alg *algs, int count)
473{
474 int i, ret;
475
476 for (i = 0; i < count; i++) {
477 ret = crypto_register_alg(&algs[i]);
478 if (ret)
479 goto err;
480 }
481
482 return 0;
483
484err:
485 for (--i; i >= 0; --i)
486 crypto_unregister_alg(&algs[i]);
487
488 return ret;
489}
490EXPORT_SYMBOL_GPL(crypto_register_algs);
491
Eric Biggersc6d633a2019-12-15 15:51:19 -0800492void crypto_unregister_algs(struct crypto_alg *algs, int count)
Mark Brown4b004342012-01-17 23:34:26 +0000493{
Eric Biggersc6d633a2019-12-15 15:51:19 -0800494 int i;
Mark Brown4b004342012-01-17 23:34:26 +0000495
Eric Biggersc6d633a2019-12-15 15:51:19 -0800496 for (i = 0; i < count; i++)
497 crypto_unregister_alg(&algs[i]);
Mark Brown4b004342012-01-17 23:34:26 +0000498}
499EXPORT_SYMBOL_GPL(crypto_unregister_algs);
500
Herbert Xu4cc77202006-08-06 21:16:34 +1000501int crypto_register_template(struct crypto_template *tmpl)
502{
503 struct crypto_template *q;
504 int err = -EEXIST;
505
506 down_write(&crypto_alg_sem);
507
Jarod Wilson002c77a2014-07-02 15:37:30 -0400508 crypto_check_module_sig(tmpl->module);
509
Herbert Xu4cc77202006-08-06 21:16:34 +1000510 list_for_each_entry(q, &crypto_template_list, list) {
511 if (q == tmpl)
512 goto out;
513 }
514
515 list_add(&tmpl->list, &crypto_template_list);
516 err = 0;
517out:
518 up_write(&crypto_alg_sem);
519 return err;
520}
521EXPORT_SYMBOL_GPL(crypto_register_template);
522
Xiongfeng Wang95724422019-01-18 13:58:11 +0800523int crypto_register_templates(struct crypto_template *tmpls, int count)
524{
525 int i, err;
526
527 for (i = 0; i < count; i++) {
528 err = crypto_register_template(&tmpls[i]);
529 if (err)
530 goto out;
531 }
532 return 0;
533
534out:
535 for (--i; i >= 0; --i)
536 crypto_unregister_template(&tmpls[i]);
537 return err;
538}
539EXPORT_SYMBOL_GPL(crypto_register_templates);
540
Herbert Xu4cc77202006-08-06 21:16:34 +1000541void crypto_unregister_template(struct crypto_template *tmpl)
542{
543 struct crypto_instance *inst;
Sasha Levinb67bfe02013-02-27 17:06:00 -0800544 struct hlist_node *n;
Herbert Xu4cc77202006-08-06 21:16:34 +1000545 struct hlist_head *list;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000546 LIST_HEAD(users);
Herbert Xu4cc77202006-08-06 21:16:34 +1000547
548 down_write(&crypto_alg_sem);
549
550 BUG_ON(list_empty(&tmpl->list));
551 list_del_init(&tmpl->list);
552
553 list = &tmpl->instances;
Sasha Levinb67bfe02013-02-27 17:06:00 -0800554 hlist_for_each_entry(inst, list, list) {
Herbert Xu6bfd4802006-09-21 11:39:29 +1000555 int err = crypto_remove_alg(&inst->alg, &users);
Joshua I. James0efcb8d2014-12-05 15:00:10 +0900556
Herbert Xu6bfd4802006-09-21 11:39:29 +1000557 BUG_ON(err);
Herbert Xu4cc77202006-08-06 21:16:34 +1000558 }
559
560 up_write(&crypto_alg_sem);
561
Sasha Levinb67bfe02013-02-27 17:06:00 -0800562 hlist_for_each_entry_safe(inst, n, list, list) {
Eric Biggersce8614a2017-12-29 10:00:46 -0600563 BUG_ON(refcount_read(&inst->alg.cra_refcnt) != 1);
Herbert Xu319382a2015-07-09 07:17:15 +0800564 crypto_free_instance(inst);
Herbert Xu4cc77202006-08-06 21:16:34 +1000565 }
Herbert Xu6bfd4802006-09-21 11:39:29 +1000566 crypto_remove_final(&users);
Herbert Xu4cc77202006-08-06 21:16:34 +1000567}
568EXPORT_SYMBOL_GPL(crypto_unregister_template);
569
Xiongfeng Wang95724422019-01-18 13:58:11 +0800570void crypto_unregister_templates(struct crypto_template *tmpls, int count)
571{
572 int i;
573
574 for (i = count - 1; i >= 0; --i)
575 crypto_unregister_template(&tmpls[i]);
576}
577EXPORT_SYMBOL_GPL(crypto_unregister_templates);
578
Herbert Xu4cc77202006-08-06 21:16:34 +1000579static struct crypto_template *__crypto_lookup_template(const char *name)
580{
581 struct crypto_template *q, *tmpl = NULL;
582
583 down_read(&crypto_alg_sem);
584 list_for_each_entry(q, &crypto_template_list, list) {
585 if (strcmp(q->name, name))
586 continue;
587 if (unlikely(!crypto_tmpl_get(q)))
588 continue;
589
590 tmpl = q;
591 break;
592 }
593 up_read(&crypto_alg_sem);
594
595 return tmpl;
596}
597
598struct crypto_template *crypto_lookup_template(const char *name)
599{
Kees Cook4943ba12014-11-24 16:32:38 -0800600 return try_then_request_module(__crypto_lookup_template(name),
601 "crypto-%s", name);
Herbert Xu4cc77202006-08-06 21:16:34 +1000602}
603EXPORT_SYMBOL_GPL(crypto_lookup_template);
604
605int crypto_register_instance(struct crypto_template *tmpl,
606 struct crypto_instance *inst)
607{
Herbert Xu73d38642008-08-03 21:15:23 +0800608 struct crypto_larval *larval;
Herbert Xu5f567ff2019-12-18 15:53:01 +0800609 struct crypto_spawn *spawn;
Herbert Xu73d38642008-08-03 21:15:23 +0800610 int err;
Herbert Xu4cc77202006-08-06 21:16:34 +1000611
Herbert Xu4cc77202006-08-06 21:16:34 +1000612 err = crypto_check_alg(&inst->alg);
613 if (err)
Stephan Mueller9c521a22015-04-09 12:09:55 +0200614 return err;
615
Herbert Xu4cc77202006-08-06 21:16:34 +1000616 inst->alg.cra_module = tmpl->module;
Steffen Klassert64a947b2011-09-27 07:21:26 +0200617 inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
Herbert Xu4cc77202006-08-06 21:16:34 +1000618
619 down_write(&crypto_alg_sem);
620
Herbert Xu5f567ff2019-12-18 15:53:01 +0800621 larval = ERR_PTR(-EAGAIN);
622 for (spawn = inst->spawns; spawn;) {
623 struct crypto_spawn *next;
624
625 if (spawn->dead)
626 goto unlock;
627
628 next = spawn->next;
629 spawn->inst = inst;
630 spawn->registered = true;
631
632 if (spawn->dropref)
633 crypto_mod_put(spawn->alg);
634
635 spawn = next;
636 }
637
Herbert Xu73d38642008-08-03 21:15:23 +0800638 larval = __crypto_register_alg(&inst->alg);
639 if (IS_ERR(larval))
Herbert Xu4cc77202006-08-06 21:16:34 +1000640 goto unlock;
641
642 hlist_add_head(&inst->list, &tmpl->instances);
643 inst->tmpl = tmpl;
644
645unlock:
646 up_write(&crypto_alg_sem);
647
Herbert Xu73d38642008-08-03 21:15:23 +0800648 err = PTR_ERR(larval);
649 if (IS_ERR(larval))
650 goto err;
651
652 crypto_wait_for_test(larval);
653 err = 0;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000654
Herbert Xu4cc77202006-08-06 21:16:34 +1000655err:
656 return err;
657}
658EXPORT_SYMBOL_GPL(crypto_register_instance);
659
Eric Biggersc6d633a2019-12-15 15:51:19 -0800660void crypto_unregister_instance(struct crypto_instance *inst)
Steffen Klassertce3fd842011-11-08 10:09:17 +0100661{
Herbert Xu1f723712015-04-02 22:31:22 +0800662 LIST_HEAD(list);
Steffen Klassertce3fd842011-11-08 10:09:17 +0100663
Steffen Klassertce3fd842011-11-08 10:09:17 +0100664 down_write(&crypto_alg_sem);
665
Herbert Xu87b16752015-04-02 22:39:40 +0800666 crypto_remove_spawns(&inst->alg, &list, NULL);
Herbert Xu1f723712015-04-02 22:31:22 +0800667 crypto_remove_instance(inst, &list);
Steffen Klassertce3fd842011-11-08 10:09:17 +0100668
669 up_write(&crypto_alg_sem);
670
Herbert Xu1f723712015-04-02 22:31:22 +0800671 crypto_remove_final(&list);
Steffen Klassertce3fd842011-11-08 10:09:17 +0100672}
673EXPORT_SYMBOL_GPL(crypto_unregister_instance);
674
Herbert Xu6bfd4802006-09-21 11:39:29 +1000675int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
Herbert Xua73e6992007-04-08 21:31:36 +1000676 struct crypto_instance *inst, u32 mask)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000677{
678 int err = -EAGAIN;
679
Eric Biggers6b476662019-01-06 12:46:06 -0800680 if (WARN_ON_ONCE(inst == NULL))
681 return -EINVAL;
682
Herbert Xu5f567ff2019-12-18 15:53:01 +0800683 spawn->next = inst->spawns;
684 inst->spawns = spawn;
685
Herbert Xua73e6992007-04-08 21:31:36 +1000686 spawn->mask = mask;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000687
688 down_write(&crypto_alg_sem);
689 if (!crypto_is_moribund(alg)) {
690 list_add(&spawn->list, &alg->cra_users);
691 spawn->alg = alg;
692 err = 0;
693 }
694 up_write(&crypto_alg_sem);
695
696 return err;
697}
698EXPORT_SYMBOL_GPL(crypto_init_spawn);
699
Herbert Xu97eedce2009-07-08 15:55:52 +0800700int crypto_init_spawn2(struct crypto_spawn *spawn, struct crypto_alg *alg,
701 struct crypto_instance *inst,
702 const struct crypto_type *frontend)
703{
704 int err = -EINVAL;
705
Dan Carpenterc614e102010-05-03 11:08:15 +0800706 if ((alg->cra_flags ^ frontend->type) & frontend->maskset)
Herbert Xu97eedce2009-07-08 15:55:52 +0800707 goto out;
708
709 spawn->frontend = frontend;
710 err = crypto_init_spawn(spawn, alg, inst, frontend->maskset);
711
712out:
713 return err;
714}
715EXPORT_SYMBOL_GPL(crypto_init_spawn2);
716
Eric Biggersde95c952020-01-02 19:58:48 -0800717int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst,
718 const char *name, u32 type, u32 mask)
Herbert Xud6ef2f12015-05-11 17:47:39 +0800719{
720 struct crypto_alg *alg;
721 int err;
722
Eric Biggersca94e932020-01-02 19:58:42 -0800723 /* Allow the result of crypto_attr_alg_name() to be passed directly */
724 if (IS_ERR(name))
725 return PTR_ERR(name);
726
Herbert Xud6ef2f12015-05-11 17:47:39 +0800727 alg = crypto_find_alg(name, spawn->frontend, type, mask);
728 if (IS_ERR(alg))
729 return PTR_ERR(alg);
730
Herbert Xu5f567ff2019-12-18 15:53:01 +0800731 spawn->dropref = true;
Eric Biggersde95c952020-01-02 19:58:48 -0800732 err = crypto_init_spawn(spawn, alg, inst, mask);
Herbert Xu5f567ff2019-12-18 15:53:01 +0800733 if (err)
734 crypto_mod_put(alg);
Herbert Xud6ef2f12015-05-11 17:47:39 +0800735 return err;
736}
737EXPORT_SYMBOL_GPL(crypto_grab_spawn);
738
Herbert Xu6bfd4802006-09-21 11:39:29 +1000739void crypto_drop_spawn(struct crypto_spawn *spawn)
740{
Eric Biggersff670622020-01-02 19:58:41 -0800741 if (!spawn->alg) /* not yet initialized? */
742 return;
743
Herbert Xu6bfd4802006-09-21 11:39:29 +1000744 down_write(&crypto_alg_sem);
Herbert Xu4f87ee12019-12-07 22:15:17 +0800745 if (!spawn->dead)
Herbert Xu7db3b612019-12-06 13:55:17 +0800746 list_del(&spawn->list);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000747 up_write(&crypto_alg_sem);
Herbert Xu5f567ff2019-12-18 15:53:01 +0800748
749 if (spawn->dropref && !spawn->registered)
750 crypto_mod_put(spawn->alg);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000751}
752EXPORT_SYMBOL_GPL(crypto_drop_spawn);
753
Herbert Xu97eedce2009-07-08 15:55:52 +0800754static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
Herbert Xu6bfd4802006-09-21 11:39:29 +1000755{
756 struct crypto_alg *alg;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000757
758 down_read(&crypto_alg_sem);
759 alg = spawn->alg;
Herbert Xu4f87ee12019-12-07 22:15:17 +0800760 if (!spawn->dead && !crypto_mod_get(alg)) {
Herbert Xu73669cc2019-12-07 22:15:15 +0800761 alg->cra_flags |= CRYPTO_ALG_DYING;
762 alg = NULL;
763 }
Herbert Xu6bfd4802006-09-21 11:39:29 +1000764 up_read(&crypto_alg_sem);
765
Herbert Xu73669cc2019-12-07 22:15:15 +0800766 return alg ?: ERR_PTR(-EAGAIN);
Herbert Xu97eedce2009-07-08 15:55:52 +0800767}
768
769struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
770 u32 mask)
771{
772 struct crypto_alg *alg;
773 struct crypto_tfm *tfm;
774
775 alg = crypto_spawn_alg(spawn);
776 if (IS_ERR(alg))
777 return ERR_CAST(alg);
778
Herbert Xu2e306ee2006-12-17 10:05:58 +1100779 tfm = ERR_PTR(-EINVAL);
780 if (unlikely((alg->cra_flags ^ type) & mask))
781 goto out_put_alg;
782
Herbert Xu27d2a332007-01-24 20:50:26 +1100783 tfm = __crypto_alloc_tfm(alg, type, mask);
Herbert Xu6bfd4802006-09-21 11:39:29 +1000784 if (IS_ERR(tfm))
Herbert Xu2e306ee2006-12-17 10:05:58 +1100785 goto out_put_alg;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000786
787 return tfm;
Herbert Xu2e306ee2006-12-17 10:05:58 +1100788
789out_put_alg:
790 crypto_mod_put(alg);
791 return tfm;
Herbert Xu6bfd4802006-09-21 11:39:29 +1000792}
793EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
794
Herbert Xu97eedce2009-07-08 15:55:52 +0800795void *crypto_spawn_tfm2(struct crypto_spawn *spawn)
796{
797 struct crypto_alg *alg;
798 struct crypto_tfm *tfm;
799
800 alg = crypto_spawn_alg(spawn);
801 if (IS_ERR(alg))
802 return ERR_CAST(alg);
803
804 tfm = crypto_create_tfm(alg, spawn->frontend);
805 if (IS_ERR(tfm))
806 goto out_put_alg;
807
808 return tfm;
809
810out_put_alg:
811 crypto_mod_put(alg);
812 return tfm;
813}
814EXPORT_SYMBOL_GPL(crypto_spawn_tfm2);
815
Herbert Xu28259822006-08-06 21:23:26 +1000816int crypto_register_notifier(struct notifier_block *nb)
817{
818 return blocking_notifier_chain_register(&crypto_chain, nb);
819}
820EXPORT_SYMBOL_GPL(crypto_register_notifier);
821
822int crypto_unregister_notifier(struct notifier_block *nb)
823{
824 return blocking_notifier_chain_unregister(&crypto_chain, nb);
825}
826EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
827
Herbert Xuebc610e2007-01-01 18:37:02 +1100828struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000829{
Herbert Xu39e1ee012007-08-29 19:27:26 +0800830 struct rtattr *rta = tb[0];
Herbert Xuebc610e2007-01-01 18:37:02 +1100831 struct crypto_attr_type *algt;
832
833 if (!rta)
834 return ERR_PTR(-ENOENT);
835 if (RTA_PAYLOAD(rta) < sizeof(*algt))
836 return ERR_PTR(-EINVAL);
Herbert Xu39e1ee012007-08-29 19:27:26 +0800837 if (rta->rta_type != CRYPTOA_TYPE)
838 return ERR_PTR(-EINVAL);
Herbert Xuebc610e2007-01-01 18:37:02 +1100839
840 algt = RTA_DATA(rta);
841
842 return algt;
843}
844EXPORT_SYMBOL_GPL(crypto_get_attr_type);
845
846int crypto_check_attr_type(struct rtattr **tb, u32 type)
847{
848 struct crypto_attr_type *algt;
849
850 algt = crypto_get_attr_type(tb);
851 if (IS_ERR(algt))
852 return PTR_ERR(algt);
853
854 if ((algt->type ^ type) & algt->mask)
855 return -EINVAL;
856
857 return 0;
858}
859EXPORT_SYMBOL_GPL(crypto_check_attr_type);
860
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800861const char *crypto_attr_alg_name(struct rtattr *rta)
Herbert Xuebc610e2007-01-01 18:37:02 +1100862{
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000863 struct crypto_attr_alg *alga;
864
Herbert Xuebc610e2007-01-01 18:37:02 +1100865 if (!rta)
866 return ERR_PTR(-ENOENT);
867 if (RTA_PAYLOAD(rta) < sizeof(*alga))
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000868 return ERR_PTR(-EINVAL);
Herbert Xu39e1ee012007-08-29 19:27:26 +0800869 if (rta->rta_type != CRYPTOA_ALG)
870 return ERR_PTR(-EINVAL);
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000871
872 alga = RTA_DATA(rta);
873 alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
874
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800875 return alga->name;
876}
877EXPORT_SYMBOL_GPL(crypto_attr_alg_name);
878
Herbert Xud06854f2009-07-08 17:53:16 +0800879struct crypto_alg *crypto_attr_alg2(struct rtattr *rta,
880 const struct crypto_type *frontend,
881 u32 type, u32 mask)
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800882{
883 const char *name;
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800884
885 name = crypto_attr_alg_name(rta);
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800886 if (IS_ERR(name))
Julia Lawall3e8afe32013-01-22 12:29:26 +0100887 return ERR_CAST(name);
Herbert Xu68b6c7d2007-12-07 20:18:17 +0800888
Herbert Xud06854f2009-07-08 17:53:16 +0800889 return crypto_find_alg(name, frontend, type, mask);
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000890}
Herbert Xud06854f2009-07-08 17:53:16 +0800891EXPORT_SYMBOL_GPL(crypto_attr_alg2);
Herbert Xu3c09f172007-08-30 16:24:15 +0800892
893int crypto_attr_u32(struct rtattr *rta, u32 *num)
894{
895 struct crypto_attr_u32 *nu32;
896
897 if (!rta)
898 return -ENOENT;
899 if (RTA_PAYLOAD(rta) < sizeof(*nu32))
900 return -EINVAL;
901 if (rta->rta_type != CRYPTOA_U32)
902 return -EINVAL;
903
904 nu32 = RTA_DATA(rta);
905 *num = nu32->num;
906
907 return 0;
908}
909EXPORT_SYMBOL_GPL(crypto_attr_u32);
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000910
Herbert Xu32f27c72016-06-29 18:04:13 +0800911int crypto_inst_setname(struct crypto_instance *inst, const char *name,
912 struct crypto_alg *alg)
913{
914 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name,
915 alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
916 return -ENAMETOOLONG;
917
918 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
919 name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
920 return -ENAMETOOLONG;
921
922 return 0;
923}
924EXPORT_SYMBOL_GPL(crypto_inst_setname);
925
Eric Biggers14aa1a82019-01-03 20:16:25 -0800926void *crypto_alloc_instance(const char *name, struct crypto_alg *alg,
927 unsigned int head)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000928{
929 struct crypto_instance *inst;
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800930 char *p;
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000931 int err;
932
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800933 p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn),
934 GFP_KERNEL);
935 if (!p)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000936 return ERR_PTR(-ENOMEM);
937
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800938 inst = (void *)(p + head);
939
Herbert Xu32f27c72016-06-29 18:04:13 +0800940 err = crypto_inst_setname(inst, name, alg);
941 if (err)
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000942 goto err_free_inst;
943
Herbert Xu70ec7bb2009-07-07 14:07:37 +0800944 return p;
945
946err_free_inst:
947 kfree(p);
948 return ERR_PTR(err);
949}
Herbert Xu7fed0bf2006-08-06 23:10:45 +1000950EXPORT_SYMBOL_GPL(crypto_alloc_instance);
951
Herbert Xub5b7f082007-04-16 20:48:54 +1000952void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen)
953{
954 INIT_LIST_HEAD(&queue->list);
955 queue->backlog = &queue->list;
956 queue->qlen = 0;
957 queue->max_qlen = max_qlen;
958}
959EXPORT_SYMBOL_GPL(crypto_init_queue);
960
961int crypto_enqueue_request(struct crypto_queue *queue,
962 struct crypto_async_request *request)
963{
964 int err = -EINPROGRESS;
965
966 if (unlikely(queue->qlen >= queue->max_qlen)) {
Gilad Ben-Yossef6b80ea32017-10-18 08:00:33 +0100967 if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
968 err = -ENOSPC;
Herbert Xub5b7f082007-04-16 20:48:54 +1000969 goto out;
Gilad Ben-Yossef6b80ea32017-10-18 08:00:33 +0100970 }
971 err = -EBUSY;
Herbert Xub5b7f082007-04-16 20:48:54 +1000972 if (queue->backlog == &queue->list)
973 queue->backlog = &request->list;
974 }
975
976 queue->qlen++;
977 list_add_tail(&request->list, &queue->list);
978
979out:
980 return err;
981}
982EXPORT_SYMBOL_GPL(crypto_enqueue_request);
983
Herbert Xu31d228c2015-07-08 11:55:30 +0800984struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
Herbert Xub5b7f082007-04-16 20:48:54 +1000985{
986 struct list_head *request;
987
988 if (unlikely(!queue->qlen))
989 return NULL;
990
991 queue->qlen--;
992
993 if (queue->backlog != &queue->list)
994 queue->backlog = queue->backlog->next;
995
996 request = queue->list.next;
997 list_del(request);
998
Herbert Xu31d228c2015-07-08 11:55:30 +0800999 return list_entry(request, struct crypto_async_request, list);
Herbert Xub5b7f082007-04-16 20:48:54 +10001000}
1001EXPORT_SYMBOL_GPL(crypto_dequeue_request);
1002
Herbert Xu76136362007-11-20 17:26:06 +08001003static inline void crypto_inc_byte(u8 *a, unsigned int size)
1004{
1005 u8 *b = (a + size);
1006 u8 c;
1007
1008 for (; size; size--) {
1009 c = *--b + 1;
1010 *b = c;
1011 if (c)
1012 break;
1013 }
1014}
1015
1016void crypto_inc(u8 *a, unsigned int size)
1017{
1018 __be32 *b = (__be32 *)(a + size);
1019 u32 c;
1020
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001021 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
Ard Biesheuvel27c539a2017-02-14 21:51:02 +00001022 IS_ALIGNED((unsigned long)b, __alignof__(*b)))
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001023 for (; size >= 4; size -= 4) {
1024 c = be32_to_cpu(*--b) + 1;
1025 *b = cpu_to_be32(c);
Ard Biesheuvel27c539a2017-02-14 21:51:02 +00001026 if (likely(c))
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001027 return;
1028 }
Herbert Xu76136362007-11-20 17:26:06 +08001029
1030 crypto_inc_byte(a, size);
1031}
1032EXPORT_SYMBOL_GPL(crypto_inc);
1033
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001034void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int len)
Herbert Xu76136362007-11-20 17:26:06 +08001035{
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001036 int relalign = 0;
1037
1038 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) {
1039 int size = sizeof(unsigned long);
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001040 int d = (((unsigned long)dst ^ (unsigned long)src1) |
1041 ((unsigned long)dst ^ (unsigned long)src2)) &
1042 (size - 1);
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001043
1044 relalign = d ? 1 << __ffs(d) : size;
1045
1046 /*
1047 * If we care about alignment, process as many bytes as
1048 * needed to advance dst and src to values whose alignments
1049 * equal their relative alignment. This will allow us to
1050 * process the remainder of the input using optimal strides.
1051 */
1052 while (((unsigned long)dst & (relalign - 1)) && len > 0) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001053 *dst++ = *src1++ ^ *src2++;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001054 len--;
1055 }
1056 }
1057
1058 while (IS_ENABLED(CONFIG_64BIT) && len >= 8 && !(relalign & 7)) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001059 *(u64 *)dst = *(u64 *)src1 ^ *(u64 *)src2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001060 dst += 8;
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001061 src1 += 8;
1062 src2 += 8;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001063 len -= 8;
1064 }
1065
1066 while (len >= 4 && !(relalign & 3)) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001067 *(u32 *)dst = *(u32 *)src1 ^ *(u32 *)src2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001068 dst += 4;
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001069 src1 += 4;
1070 src2 += 4;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001071 len -= 4;
1072 }
1073
1074 while (len >= 2 && !(relalign & 1)) {
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001075 *(u16 *)dst = *(u16 *)src1 ^ *(u16 *)src2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001076 dst += 2;
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001077 src1 += 2;
1078 src2 += 2;
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001079 len -= 2;
1080 }
1081
1082 while (len--)
Ard Biesheuvela7c391f2017-07-24 11:28:03 +01001083 *dst++ = *src1++ ^ *src2++;
Herbert Xu76136362007-11-20 17:26:06 +08001084}
Ard Biesheuveldb91af02017-02-05 10:06:12 +00001085EXPORT_SYMBOL_GPL(__crypto_xor);
Herbert Xu76136362007-11-20 17:26:06 +08001086
Herbert Xu38d21432015-04-20 13:39:00 +08001087unsigned int crypto_alg_extsize(struct crypto_alg *alg)
1088{
Herbert Xuc2110f22015-05-28 22:07:56 +08001089 return alg->cra_ctxsize +
1090 (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
Herbert Xu38d21432015-04-20 13:39:00 +08001091}
1092EXPORT_SYMBOL_GPL(crypto_alg_extsize);
1093
Herbert Xuf2aefda2016-01-23 13:51:01 +08001094int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
1095 u32 type, u32 mask)
1096{
1097 int ret = 0;
1098 struct crypto_alg *alg = crypto_find_alg(name, frontend, type, mask);
1099
1100 if (!IS_ERR(alg)) {
1101 crypto_mod_put(alg);
1102 ret = 1;
1103 }
1104
1105 return ret;
1106}
1107EXPORT_SYMBOL_GPL(crypto_type_has_alg);
1108
Corentin Labbef7d76e02018-11-29 14:42:21 +00001109#ifdef CONFIG_CRYPTO_STATS
Corentin Labbe1f6669b2018-11-29 14:42:26 +00001110void crypto_stats_init(struct crypto_alg *alg)
1111{
1112 memset(&alg->stats, 0, sizeof(alg->stats));
1113}
1114EXPORT_SYMBOL_GPL(crypto_stats_init);
1115
Corentin Labbef7d76e02018-11-29 14:42:21 +00001116void crypto_stats_get(struct crypto_alg *alg)
1117{
1118 crypto_alg_get(alg);
1119}
1120EXPORT_SYMBOL_GPL(crypto_stats_get);
1121
Corentin Labbef7d76e02018-11-29 14:42:21 +00001122void crypto_stats_aead_encrypt(unsigned int cryptlen, struct crypto_alg *alg,
1123 int ret)
1124{
1125 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001126 atomic64_inc(&alg->stats.aead.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001127 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001128 atomic64_inc(&alg->stats.aead.encrypt_cnt);
1129 atomic64_add(cryptlen, &alg->stats.aead.encrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001130 }
1131 crypto_alg_put(alg);
1132}
1133EXPORT_SYMBOL_GPL(crypto_stats_aead_encrypt);
1134
1135void crypto_stats_aead_decrypt(unsigned int cryptlen, struct crypto_alg *alg,
1136 int ret)
1137{
1138 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001139 atomic64_inc(&alg->stats.aead.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001140 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001141 atomic64_inc(&alg->stats.aead.decrypt_cnt);
1142 atomic64_add(cryptlen, &alg->stats.aead.decrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001143 }
1144 crypto_alg_put(alg);
1145}
1146EXPORT_SYMBOL_GPL(crypto_stats_aead_decrypt);
1147
1148void crypto_stats_akcipher_encrypt(unsigned int src_len, int ret,
1149 struct crypto_alg *alg)
1150{
1151 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001152 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001153 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001154 atomic64_inc(&alg->stats.akcipher.encrypt_cnt);
1155 atomic64_add(src_len, &alg->stats.akcipher.encrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001156 }
1157 crypto_alg_put(alg);
1158}
1159EXPORT_SYMBOL_GPL(crypto_stats_akcipher_encrypt);
1160
1161void crypto_stats_akcipher_decrypt(unsigned int src_len, int ret,
1162 struct crypto_alg *alg)
1163{
1164 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001165 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001166 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001167 atomic64_inc(&alg->stats.akcipher.decrypt_cnt);
1168 atomic64_add(src_len, &alg->stats.akcipher.decrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001169 }
1170 crypto_alg_put(alg);
1171}
1172EXPORT_SYMBOL_GPL(crypto_stats_akcipher_decrypt);
1173
1174void crypto_stats_akcipher_sign(int ret, struct crypto_alg *alg)
1175{
1176 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001177 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001178 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001179 atomic64_inc(&alg->stats.akcipher.sign_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001180 crypto_alg_put(alg);
1181}
1182EXPORT_SYMBOL_GPL(crypto_stats_akcipher_sign);
1183
1184void crypto_stats_akcipher_verify(int ret, struct crypto_alg *alg)
1185{
1186 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001187 atomic64_inc(&alg->stats.akcipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001188 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001189 atomic64_inc(&alg->stats.akcipher.verify_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001190 crypto_alg_put(alg);
1191}
1192EXPORT_SYMBOL_GPL(crypto_stats_akcipher_verify);
1193
1194void crypto_stats_compress(unsigned int slen, int ret, struct crypto_alg *alg)
1195{
1196 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001197 atomic64_inc(&alg->stats.compress.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001198 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001199 atomic64_inc(&alg->stats.compress.compress_cnt);
1200 atomic64_add(slen, &alg->stats.compress.compress_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001201 }
1202 crypto_alg_put(alg);
1203}
1204EXPORT_SYMBOL_GPL(crypto_stats_compress);
1205
1206void crypto_stats_decompress(unsigned int slen, int ret, struct crypto_alg *alg)
1207{
1208 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001209 atomic64_inc(&alg->stats.compress.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001210 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001211 atomic64_inc(&alg->stats.compress.decompress_cnt);
1212 atomic64_add(slen, &alg->stats.compress.decompress_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001213 }
1214 crypto_alg_put(alg);
1215}
1216EXPORT_SYMBOL_GPL(crypto_stats_decompress);
1217
1218void crypto_stats_ahash_update(unsigned int nbytes, int ret,
1219 struct crypto_alg *alg)
1220{
1221 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001222 atomic64_inc(&alg->stats.hash.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001223 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001224 atomic64_add(nbytes, &alg->stats.hash.hash_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001225 crypto_alg_put(alg);
1226}
1227EXPORT_SYMBOL_GPL(crypto_stats_ahash_update);
1228
1229void crypto_stats_ahash_final(unsigned int nbytes, int ret,
1230 struct crypto_alg *alg)
1231{
1232 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001233 atomic64_inc(&alg->stats.hash.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001234 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001235 atomic64_inc(&alg->stats.hash.hash_cnt);
1236 atomic64_add(nbytes, &alg->stats.hash.hash_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001237 }
1238 crypto_alg_put(alg);
1239}
1240EXPORT_SYMBOL_GPL(crypto_stats_ahash_final);
1241
1242void crypto_stats_kpp_set_secret(struct crypto_alg *alg, int ret)
1243{
1244 if (ret)
Corentin Labbe44f13132018-11-29 14:42:25 +00001245 atomic64_inc(&alg->stats.kpp.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001246 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001247 atomic64_inc(&alg->stats.kpp.setsecret_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001248 crypto_alg_put(alg);
1249}
1250EXPORT_SYMBOL_GPL(crypto_stats_kpp_set_secret);
1251
1252void crypto_stats_kpp_generate_public_key(struct crypto_alg *alg, int ret)
1253{
1254 if (ret)
Corentin Labbe44f13132018-11-29 14:42:25 +00001255 atomic64_inc(&alg->stats.kpp.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001256 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001257 atomic64_inc(&alg->stats.kpp.generate_public_key_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001258 crypto_alg_put(alg);
1259}
1260EXPORT_SYMBOL_GPL(crypto_stats_kpp_generate_public_key);
1261
1262void crypto_stats_kpp_compute_shared_secret(struct crypto_alg *alg, int ret)
1263{
1264 if (ret)
Corentin Labbe44f13132018-11-29 14:42:25 +00001265 atomic64_inc(&alg->stats.kpp.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001266 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001267 atomic64_inc(&alg->stats.kpp.compute_shared_secret_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001268 crypto_alg_put(alg);
1269}
1270EXPORT_SYMBOL_GPL(crypto_stats_kpp_compute_shared_secret);
1271
1272void crypto_stats_rng_seed(struct crypto_alg *alg, int ret)
1273{
1274 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
Corentin Labbe44f13132018-11-29 14:42:25 +00001275 atomic64_inc(&alg->stats.rng.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001276 else
Corentin Labbe17c18f92018-11-29 14:42:24 +00001277 atomic64_inc(&alg->stats.rng.seed_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001278 crypto_alg_put(alg);
1279}
1280EXPORT_SYMBOL_GPL(crypto_stats_rng_seed);
1281
1282void crypto_stats_rng_generate(struct crypto_alg *alg, unsigned int dlen,
1283 int ret)
1284{
1285 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001286 atomic64_inc(&alg->stats.rng.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001287 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001288 atomic64_inc(&alg->stats.rng.generate_cnt);
1289 atomic64_add(dlen, &alg->stats.rng.generate_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001290 }
1291 crypto_alg_put(alg);
1292}
1293EXPORT_SYMBOL_GPL(crypto_stats_rng_generate);
1294
1295void crypto_stats_skcipher_encrypt(unsigned int cryptlen, int ret,
1296 struct crypto_alg *alg)
1297{
1298 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001299 atomic64_inc(&alg->stats.cipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001300 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001301 atomic64_inc(&alg->stats.cipher.encrypt_cnt);
1302 atomic64_add(cryptlen, &alg->stats.cipher.encrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001303 }
1304 crypto_alg_put(alg);
1305}
1306EXPORT_SYMBOL_GPL(crypto_stats_skcipher_encrypt);
1307
1308void crypto_stats_skcipher_decrypt(unsigned int cryptlen, int ret,
1309 struct crypto_alg *alg)
1310{
1311 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
Corentin Labbe44f13132018-11-29 14:42:25 +00001312 atomic64_inc(&alg->stats.cipher.err_cnt);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001313 } else {
Corentin Labbe17c18f92018-11-29 14:42:24 +00001314 atomic64_inc(&alg->stats.cipher.decrypt_cnt);
1315 atomic64_add(cryptlen, &alg->stats.cipher.decrypt_tlen);
Corentin Labbef7d76e02018-11-29 14:42:21 +00001316 }
1317 crypto_alg_put(alg);
1318}
1319EXPORT_SYMBOL_GPL(crypto_stats_skcipher_decrypt);
1320#endif
1321
Herbert Xucce9e062006-08-21 21:08:13 +10001322static int __init crypto_algapi_init(void)
1323{
1324 crypto_init_proc();
1325 return 0;
1326}
1327
1328static void __exit crypto_algapi_exit(void)
1329{
1330 crypto_exit_proc();
1331}
1332
1333module_init(crypto_algapi_init);
1334module_exit(crypto_algapi_exit);
1335
1336MODULE_LICENSE("GPL");
1337MODULE_DESCRIPTION("Cryptographic algorithms API");