aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/algapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/algapi.c')
-rw-r--r--crypto/algapi.c156
1 files changed, 134 insertions, 22 deletions
diff --git a/crypto/algapi.c b/crypto/algapi.c
index a65c6ccfbe17..232b37d81613 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -13,11 +13,14 @@
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/list.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/string.h> 18#include <linux/string.h>
18 19
19#include "internal.h" 20#include "internal.h"
20 21
22static LIST_HEAD(crypto_template_list);
23
21static inline int crypto_set_driver_name(struct crypto_alg *alg) 24static inline int crypto_set_driver_name(struct crypto_alg *alg)
22{ 25{
23 static const char suffix[] = "-generic"; 26 static const char suffix[] = "-generic";
@@ -35,11 +38,8 @@ static inline int crypto_set_driver_name(struct crypto_alg *alg)
35 return 0; 38 return 0;
36} 39}
37 40
38int crypto_register_alg(struct crypto_alg *alg) 41static int crypto_check_alg(struct crypto_alg *alg)
39{ 42{
40 int ret;
41 struct crypto_alg *q;
42
43 if (alg->cra_alignmask & (alg->cra_alignmask + 1)) 43 if (alg->cra_alignmask & (alg->cra_alignmask + 1))
44 return -EINVAL; 44 return -EINVAL;
45 45
@@ -51,42 +51,52 @@ int crypto_register_alg(struct crypto_alg *alg)
51 51
52 if (alg->cra_priority < 0) 52 if (alg->cra_priority < 0)
53 return -EINVAL; 53 return -EINVAL;
54
55 ret = crypto_set_driver_name(alg);
56 if (unlikely(ret))
57 return ret;
58 54
59 down_write(&crypto_alg_sem); 55 return crypto_set_driver_name(alg);
60 56}
57
58static int __crypto_register_alg(struct crypto_alg *alg)
59{
60 struct crypto_alg *q;
61 int ret = -EEXIST;
62
61 list_for_each_entry(q, &crypto_alg_list, cra_list) { 63 list_for_each_entry(q, &crypto_alg_list, cra_list) {
62 if (q == alg) { 64 if (q == alg)
63 ret = -EEXIST;
64 goto out; 65 goto out;
65 }
66 } 66 }
67 67
68 list_add(&alg->cra_list, &crypto_alg_list); 68 list_add(&alg->cra_list, &crypto_alg_list);
69 atomic_set(&alg->cra_refcnt, 1); 69 atomic_set(&alg->cra_refcnt, 1);
70 ret = 0;
70out: 71out:
71 up_write(&crypto_alg_sem);
72 return ret; 72 return ret;
73} 73}
74
75int crypto_register_alg(struct crypto_alg *alg)
76{
77 int err;
78
79 err = crypto_check_alg(alg);
80 if (err)
81 return err;
82
83 down_write(&crypto_alg_sem);
84 err = __crypto_register_alg(alg);
85 up_write(&crypto_alg_sem);
86
87 return err;
88}
74EXPORT_SYMBOL_GPL(crypto_register_alg); 89EXPORT_SYMBOL_GPL(crypto_register_alg);
75 90
76int crypto_unregister_alg(struct crypto_alg *alg) 91int crypto_unregister_alg(struct crypto_alg *alg)
77{ 92{
78 int ret = -ENOENT; 93 int ret = -ENOENT;
79 struct crypto_alg *q;
80 94
81 down_write(&crypto_alg_sem); 95 down_write(&crypto_alg_sem);
82 list_for_each_entry(q, &crypto_alg_list, cra_list) { 96 if (likely(!list_empty(&alg->cra_list))) {
83 if (alg == q) { 97 list_del_init(&alg->cra_list);
84 list_del(&alg->cra_list); 98 ret = 0;
85 ret = 0;
86 goto out;
87 }
88 } 99 }
89out:
90 up_write(&crypto_alg_sem); 100 up_write(&crypto_alg_sem);
91 101
92 if (ret) 102 if (ret)
@@ -100,6 +110,108 @@ out:
100} 110}
101EXPORT_SYMBOL_GPL(crypto_unregister_alg); 111EXPORT_SYMBOL_GPL(crypto_unregister_alg);
102 112
113int crypto_register_template(struct crypto_template *tmpl)
114{
115 struct crypto_template *q;
116 int err = -EEXIST;
117
118 down_write(&crypto_alg_sem);
119
120 list_for_each_entry(q, &crypto_template_list, list) {
121 if (q == tmpl)
122 goto out;
123 }
124
125 list_add(&tmpl->list, &crypto_template_list);
126 err = 0;
127out:
128 up_write(&crypto_alg_sem);
129 return err;
130}
131EXPORT_SYMBOL_GPL(crypto_register_template);
132
133void crypto_unregister_template(struct crypto_template *tmpl)
134{
135 struct crypto_instance *inst;
136 struct hlist_node *p, *n;
137 struct hlist_head *list;
138
139 down_write(&crypto_alg_sem);
140
141 BUG_ON(list_empty(&tmpl->list));
142 list_del_init(&tmpl->list);
143
144 list = &tmpl->instances;
145 hlist_for_each_entry(inst, p, list, list) {
146 BUG_ON(list_empty(&inst->alg.cra_list));
147 list_del_init(&inst->alg.cra_list);
148 }
149
150 up_write(&crypto_alg_sem);
151
152 hlist_for_each_entry_safe(inst, p, n, list, list) {
153 BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1);
154 tmpl->free(inst);
155 }
156}
157EXPORT_SYMBOL_GPL(crypto_unregister_template);
158
159static struct crypto_template *__crypto_lookup_template(const char *name)
160{
161 struct crypto_template *q, *tmpl = NULL;
162
163 down_read(&crypto_alg_sem);
164 list_for_each_entry(q, &crypto_template_list, list) {
165 if (strcmp(q->name, name))
166 continue;
167 if (unlikely(!crypto_tmpl_get(q)))
168 continue;
169
170 tmpl = q;
171 break;
172 }
173 up_read(&crypto_alg_sem);
174
175 return tmpl;
176}
177
178struct crypto_template *crypto_lookup_template(const char *name)
179{
180 return try_then_request_module(__crypto_lookup_template(name), name);
181}
182EXPORT_SYMBOL_GPL(crypto_lookup_template);
183
184int crypto_register_instance(struct crypto_template *tmpl,
185 struct crypto_instance *inst)
186{
187 int err = -EINVAL;
188
189 if (inst->alg.cra_destroy)
190 goto err;
191
192 err = crypto_check_alg(&inst->alg);
193 if (err)
194 goto err;
195
196 inst->alg.cra_module = tmpl->module;
197
198 down_write(&crypto_alg_sem);
199
200 err = __crypto_register_alg(&inst->alg);
201 if (err)
202 goto unlock;
203
204 hlist_add_head(&inst->list, &tmpl->instances);
205 inst->tmpl = tmpl;
206
207unlock:
208 up_write(&crypto_alg_sem);
209
210err:
211 return err;
212}
213EXPORT_SYMBOL_GPL(crypto_register_instance);
214
103static int __init crypto_algapi_init(void) 215static int __init crypto_algapi_init(void)
104{ 216{
105 crypto_init_proc(); 217 crypto_init_proc();