2 * Cryptographic API for algorithms (i.e., low-level API).
4 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
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)
13 #include <linux/err.h>
14 #include <linux/errno.h>
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/list.h>
18 #include <linux/module.h>
19 #include <linux/string.h>
23 static LIST_HEAD(crypto_template_list);
25 void crypto_larval_error(const char *name, u32 type, u32 mask)
27 struct crypto_alg *alg;
29 down_read(&crypto_alg_sem);
30 alg = __crypto_alg_lookup(name, type, mask);
31 up_read(&crypto_alg_sem);
34 if (crypto_is_larval(alg)) {
35 struct crypto_larval *larval = (void *)alg;
36 complete(&larval->completion);
41 EXPORT_SYMBOL_GPL(crypto_larval_error);
43 static inline int crypto_set_driver_name(struct crypto_alg *alg)
45 static const char suffix[] = "-generic";
46 char *driver_name = alg->cra_driver_name;
52 len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
53 if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
56 memcpy(driver_name + len, suffix, sizeof(suffix));
60 static int crypto_check_alg(struct crypto_alg *alg)
62 if (alg->cra_alignmask & (alg->cra_alignmask + 1))
65 if (alg->cra_alignmask & alg->cra_blocksize)
68 if (alg->cra_blocksize > PAGE_SIZE / 8)
71 if (alg->cra_priority < 0)
74 return crypto_set_driver_name(alg);
77 static void crypto_destroy_instance(struct crypto_alg *alg)
79 struct crypto_instance *inst = (void *)alg;
80 struct crypto_template *tmpl = inst->tmpl;
83 crypto_tmpl_put(tmpl);
86 static void crypto_remove_spawns(struct list_head *spawns,
87 struct list_head *list)
89 struct crypto_spawn *spawn, *n;
91 list_for_each_entry_safe(spawn, n, spawns, list) {
92 struct crypto_instance *inst = spawn->inst;
93 struct crypto_template *tmpl = inst->tmpl;
95 list_del_init(&spawn->list);
98 if (crypto_is_dead(&inst->alg))
101 inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
102 if (!tmpl || !crypto_tmpl_get(tmpl))
105 crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
106 list_move(&inst->alg.cra_list, list);
107 hlist_del(&inst->list);
108 inst->alg.cra_destroy = crypto_destroy_instance;
110 if (!list_empty(&inst->alg.cra_users)) {
111 if (&n->list == spawns)
112 n = list_entry(inst->alg.cra_users.next,
114 __list_splice(&inst->alg.cra_users, spawns->prev);
119 static int __crypto_register_alg(struct crypto_alg *alg,
120 struct list_head *list)
122 struct crypto_alg *q;
125 if (crypto_is_dead(alg))
128 INIT_LIST_HEAD(&alg->cra_users);
132 atomic_set(&alg->cra_refcnt, 1);
133 list_for_each_entry(q, &crypto_alg_list, cra_list) {
137 if (crypto_is_moribund(q))
140 if (crypto_is_larval(q)) {
141 struct crypto_larval *larval = (void *)q;
143 if (strcmp(alg->cra_name, q->cra_name) &&
144 strcmp(alg->cra_driver_name, q->cra_name))
149 if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
151 if (!crypto_mod_get(alg))
155 complete(&larval->completion);
159 if (strcmp(alg->cra_name, q->cra_name))
162 if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
163 q->cra_priority > alg->cra_priority)
166 crypto_remove_spawns(&q->cra_users, list);
169 list_add(&alg->cra_list, &crypto_alg_list);
171 crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg);
178 static void crypto_remove_final(struct list_head *list)
180 struct crypto_alg *alg;
181 struct crypto_alg *n;
183 list_for_each_entry_safe(alg, n, list, cra_list) {
184 list_del_init(&alg->cra_list);
189 int crypto_register_alg(struct crypto_alg *alg)
194 err = crypto_check_alg(alg);
198 down_write(&crypto_alg_sem);
199 err = __crypto_register_alg(alg, &list);
200 up_write(&crypto_alg_sem);
202 crypto_remove_final(&list);
205 EXPORT_SYMBOL_GPL(crypto_register_alg);
207 static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
209 if (unlikely(list_empty(&alg->cra_list)))
212 alg->cra_flags |= CRYPTO_ALG_DEAD;
214 crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
215 list_del_init(&alg->cra_list);
216 crypto_remove_spawns(&alg->cra_users, list);
221 int crypto_unregister_alg(struct crypto_alg *alg)
226 down_write(&crypto_alg_sem);
227 ret = crypto_remove_alg(alg, &list);
228 up_write(&crypto_alg_sem);
233 BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
234 if (alg->cra_destroy)
235 alg->cra_destroy(alg);
237 crypto_remove_final(&list);
240 EXPORT_SYMBOL_GPL(crypto_unregister_alg);
242 int crypto_register_template(struct crypto_template *tmpl)
244 struct crypto_template *q;
247 down_write(&crypto_alg_sem);
249 list_for_each_entry(q, &crypto_template_list, list) {
254 list_add(&tmpl->list, &crypto_template_list);
255 crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl);
258 up_write(&crypto_alg_sem);
261 EXPORT_SYMBOL_GPL(crypto_register_template);
263 void crypto_unregister_template(struct crypto_template *tmpl)
265 struct crypto_instance *inst;
266 struct hlist_node *p, *n;
267 struct hlist_head *list;
270 down_write(&crypto_alg_sem);
272 BUG_ON(list_empty(&tmpl->list));
273 list_del_init(&tmpl->list);
275 list = &tmpl->instances;
276 hlist_for_each_entry(inst, p, list, list) {
277 int err = crypto_remove_alg(&inst->alg, &users);
281 crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl);
283 up_write(&crypto_alg_sem);
285 hlist_for_each_entry_safe(inst, p, n, list, list) {
286 BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1);
289 crypto_remove_final(&users);
291 EXPORT_SYMBOL_GPL(crypto_unregister_template);
293 static struct crypto_template *__crypto_lookup_template(const char *name)
295 struct crypto_template *q, *tmpl = NULL;
297 down_read(&crypto_alg_sem);
298 list_for_each_entry(q, &crypto_template_list, list) {
299 if (strcmp(q->name, name))
301 if (unlikely(!crypto_tmpl_get(q)))
307 up_read(&crypto_alg_sem);
312 struct crypto_template *crypto_lookup_template(const char *name)
314 return try_then_request_module(__crypto_lookup_template(name), name);
316 EXPORT_SYMBOL_GPL(crypto_lookup_template);
318 int crypto_register_instance(struct crypto_template *tmpl,
319 struct crypto_instance *inst)
324 if (inst->alg.cra_destroy)
327 err = crypto_check_alg(&inst->alg);
331 inst->alg.cra_module = tmpl->module;
333 down_write(&crypto_alg_sem);
335 err = __crypto_register_alg(&inst->alg, &list);
339 hlist_add_head(&inst->list, &tmpl->instances);
343 up_write(&crypto_alg_sem);
345 crypto_remove_final(&list);
350 EXPORT_SYMBOL_GPL(crypto_register_instance);
352 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
353 struct crypto_instance *inst)
359 down_write(&crypto_alg_sem);
360 if (!crypto_is_moribund(alg)) {
361 list_add(&spawn->list, &alg->cra_users);
365 up_write(&crypto_alg_sem);
369 EXPORT_SYMBOL_GPL(crypto_init_spawn);
371 void crypto_drop_spawn(struct crypto_spawn *spawn)
373 down_write(&crypto_alg_sem);
374 list_del(&spawn->list);
375 up_write(&crypto_alg_sem);
377 EXPORT_SYMBOL_GPL(crypto_drop_spawn);
379 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
381 struct crypto_alg *alg;
382 struct crypto_alg *alg2;
383 struct crypto_tfm *tfm;
385 down_read(&crypto_alg_sem);
389 alg2 = crypto_mod_get(alg2);
390 up_read(&crypto_alg_sem);
394 crypto_shoot_alg(alg);
395 return ERR_PTR(-EAGAIN);
398 tfm = __crypto_alloc_tfm(alg, 0);
404 EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
406 int crypto_register_notifier(struct notifier_block *nb)
408 return blocking_notifier_chain_register(&crypto_chain, nb);
410 EXPORT_SYMBOL_GPL(crypto_register_notifier);
412 int crypto_unregister_notifier(struct notifier_block *nb)
414 return blocking_notifier_chain_unregister(&crypto_chain, nb);
416 EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
418 static int __init crypto_algapi_init(void)
424 static void __exit crypto_algapi_exit(void)
429 module_init(crypto_algapi_init);
430 module_exit(crypto_algapi_exit);
432 MODULE_LICENSE("GPL");
433 MODULE_DESCRIPTION("Cryptographic algorithms API");