diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2008-08-03 09:15:23 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2008-08-29 01:49:57 -0400 |
commit | 73d3864a4823abda19ebc4387b6ddcbf416e3a77 (patch) | |
tree | 2939754dc2532f412c34a974e5f22dde112c525d | |
parent | da7f033ddc9fdebb3223b0bf88a2a2ab5b797608 (diff) |
crypto: api - Use test infrastructure
This patch makes use of the new testing infrastructure by requiring
algorithms to pass a run-time test before they're made available to
users.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | crypto/algapi.c | 143 | ||||
-rw-r--r-- | crypto/algboss.c | 75 | ||||
-rw-r--r-- | crypto/api.c | 73 | ||||
-rw-r--r-- | crypto/internal.h | 7 | ||||
-rw-r--r-- | crypto/proc.c | 3 | ||||
-rw-r--r-- | include/linux/crypto.h | 8 |
6 files changed, 267 insertions, 42 deletions
diff --git a/crypto/algapi.c b/crypto/algapi.c index e9154c1347ca..7c41e7405c41 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c | |||
@@ -21,6 +21,8 @@ | |||
21 | 21 | ||
22 | #include "internal.h" | 22 | #include "internal.h" |
23 | 23 | ||
24 | static void crypto_remove_final(struct list_head *list); | ||
25 | |||
24 | static LIST_HEAD(crypto_template_list); | 26 | static LIST_HEAD(crypto_template_list); |
25 | 27 | ||
26 | void crypto_larval_error(const char *name, u32 type, u32 mask) | 28 | void crypto_larval_error(const char *name, u32 type, u32 mask) |
@@ -126,23 +128,97 @@ static void crypto_remove_spawns(struct list_head *spawns, | |||
126 | } | 128 | } |
127 | } | 129 | } |
128 | 130 | ||
129 | static int __crypto_register_alg(struct crypto_alg *alg, | 131 | static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg) |
130 | struct list_head *list) | ||
131 | { | 132 | { |
132 | struct crypto_alg *q; | 133 | struct crypto_alg *q; |
134 | struct crypto_larval *larval; | ||
133 | int ret = -EAGAIN; | 135 | int ret = -EAGAIN; |
134 | 136 | ||
135 | if (crypto_is_dead(alg)) | 137 | if (crypto_is_dead(alg)) |
136 | goto out; | 138 | goto err; |
137 | 139 | ||
138 | INIT_LIST_HEAD(&alg->cra_users); | 140 | INIT_LIST_HEAD(&alg->cra_users); |
139 | 141 | ||
142 | /* No cheating! */ | ||
143 | alg->cra_flags &= ~CRYPTO_ALG_TESTED; | ||
144 | |||
140 | ret = -EEXIST; | 145 | ret = -EEXIST; |
141 | 146 | ||
142 | atomic_set(&alg->cra_refcnt, 1); | 147 | atomic_set(&alg->cra_refcnt, 1); |
143 | list_for_each_entry(q, &crypto_alg_list, cra_list) { | 148 | list_for_each_entry(q, &crypto_alg_list, cra_list) { |
144 | if (q == alg) | 149 | if (q == alg) |
145 | goto out; | 150 | goto err; |
151 | |||
152 | if (crypto_is_larval(q)) { | ||
153 | if (!strcmp(alg->cra_driver_name, q->cra_driver_name)) | ||
154 | goto err; | ||
155 | continue; | ||
156 | } | ||
157 | |||
158 | if (!strcmp(q->cra_driver_name, alg->cra_name) || | ||
159 | !strcmp(q->cra_name, alg->cra_driver_name)) | ||
160 | goto err; | ||
161 | } | ||
162 | |||
163 | larval = crypto_larval_alloc(alg->cra_name, | ||
164 | alg->cra_flags | CRYPTO_ALG_TESTED, 0); | ||
165 | if (IS_ERR(larval)) | ||
166 | goto out; | ||
167 | |||
168 | ret = -ENOENT; | ||
169 | larval->adult = crypto_mod_get(alg); | ||
170 | if (!larval->adult) | ||
171 | goto free_larval; | ||
172 | |||
173 | atomic_set(&larval->alg.cra_refcnt, 1); | ||
174 | memcpy(larval->alg.cra_driver_name, alg->cra_driver_name, | ||
175 | CRYPTO_MAX_ALG_NAME); | ||
176 | larval->alg.cra_priority = alg->cra_priority; | ||
177 | |||
178 | list_add(&alg->cra_list, &crypto_alg_list); | ||
179 | list_add(&larval->alg.cra_list, &crypto_alg_list); | ||
180 | |||
181 | out: | ||
182 | return larval; | ||
183 | |||
184 | free_larval: | ||
185 | kfree(larval); | ||
186 | err: | ||
187 | larval = ERR_PTR(ret); | ||
188 | goto out; | ||
189 | } | ||
190 | |||
191 | void crypto_alg_tested(const char *name, int err) | ||
192 | { | ||
193 | struct crypto_larval *test; | ||
194 | struct crypto_alg *alg; | ||
195 | struct crypto_alg *q; | ||
196 | LIST_HEAD(list); | ||
197 | |||
198 | down_write(&crypto_alg_sem); | ||
199 | list_for_each_entry(q, &crypto_alg_list, cra_list) { | ||
200 | if (!crypto_is_larval(q)) | ||
201 | continue; | ||
202 | |||
203 | test = (struct crypto_larval *)q; | ||
204 | |||
205 | if (!strcmp(q->cra_driver_name, name)) | ||
206 | goto found; | ||
207 | } | ||
208 | |||
209 | printk(KERN_ERR "alg: Unexpected test result for %s: %d\n", name, err); | ||
210 | goto unlock; | ||
211 | |||
212 | found: | ||
213 | alg = test->adult; | ||
214 | if (err || list_empty(&alg->cra_list)) | ||
215 | goto complete; | ||
216 | |||
217 | alg->cra_flags |= CRYPTO_ALG_TESTED; | ||
218 | |||
219 | list_for_each_entry(q, &crypto_alg_list, cra_list) { | ||
220 | if (q == alg) | ||
221 | continue; | ||
146 | 222 | ||
147 | if (crypto_is_moribund(q)) | 223 | if (crypto_is_moribund(q)) |
148 | continue; | 224 | continue; |
@@ -178,17 +254,18 @@ static int __crypto_register_alg(struct crypto_alg *alg, | |||
178 | q->cra_priority > alg->cra_priority) | 254 | q->cra_priority > alg->cra_priority) |
179 | continue; | 255 | continue; |
180 | 256 | ||
181 | crypto_remove_spawns(&q->cra_users, list, alg->cra_flags); | 257 | crypto_remove_spawns(&q->cra_users, &list, alg->cra_flags); |
182 | } | 258 | } |
183 | |||
184 | list_add(&alg->cra_list, &crypto_alg_list); | ||
185 | 259 | ||
186 | crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg); | 260 | complete: |
187 | ret = 0; | 261 | complete_all(&test->completion); |
188 | 262 | ||
189 | out: | 263 | unlock: |
190 | return ret; | 264 | up_write(&crypto_alg_sem); |
265 | |||
266 | crypto_remove_final(&list); | ||
191 | } | 267 | } |
268 | EXPORT_SYMBOL_GPL(crypto_alg_tested); | ||
192 | 269 | ||
193 | static void crypto_remove_final(struct list_head *list) | 270 | static void crypto_remove_final(struct list_head *list) |
194 | { | 271 | { |
@@ -201,9 +278,27 @@ static void crypto_remove_final(struct list_head *list) | |||
201 | } | 278 | } |
202 | } | 279 | } |
203 | 280 | ||
281 | static void crypto_wait_for_test(struct crypto_larval *larval) | ||
282 | { | ||
283 | int err; | ||
284 | |||
285 | err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult); | ||
286 | if (err != NOTIFY_STOP) { | ||
287 | if (WARN_ON(err != NOTIFY_DONE)) | ||
288 | goto out; | ||
289 | crypto_alg_tested(larval->alg.cra_driver_name, 0); | ||
290 | } | ||
291 | |||
292 | err = wait_for_completion_interruptible(&larval->completion); | ||
293 | WARN_ON(err); | ||
294 | |||
295 | out: | ||
296 | crypto_larval_kill(&larval->alg); | ||
297 | } | ||
298 | |||
204 | int crypto_register_alg(struct crypto_alg *alg) | 299 | int crypto_register_alg(struct crypto_alg *alg) |
205 | { | 300 | { |
206 | LIST_HEAD(list); | 301 | struct crypto_larval *larval; |
207 | int err; | 302 | int err; |
208 | 303 | ||
209 | err = crypto_check_alg(alg); | 304 | err = crypto_check_alg(alg); |
@@ -211,11 +306,14 @@ int crypto_register_alg(struct crypto_alg *alg) | |||
211 | return err; | 306 | return err; |
212 | 307 | ||
213 | down_write(&crypto_alg_sem); | 308 | down_write(&crypto_alg_sem); |
214 | err = __crypto_register_alg(alg, &list); | 309 | larval = __crypto_register_alg(alg); |
215 | up_write(&crypto_alg_sem); | 310 | up_write(&crypto_alg_sem); |
216 | 311 | ||
217 | crypto_remove_final(&list); | 312 | if (IS_ERR(larval)) |
218 | return err; | 313 | return PTR_ERR(larval); |
314 | |||
315 | crypto_wait_for_test(larval); | ||
316 | return 0; | ||
219 | } | 317 | } |
220 | EXPORT_SYMBOL_GPL(crypto_register_alg); | 318 | EXPORT_SYMBOL_GPL(crypto_register_alg); |
221 | 319 | ||
@@ -333,8 +431,8 @@ EXPORT_SYMBOL_GPL(crypto_lookup_template); | |||
333 | int crypto_register_instance(struct crypto_template *tmpl, | 431 | int crypto_register_instance(struct crypto_template *tmpl, |
334 | struct crypto_instance *inst) | 432 | struct crypto_instance *inst) |
335 | { | 433 | { |
336 | LIST_HEAD(list); | 434 | struct crypto_larval *larval; |
337 | int err = -EINVAL; | 435 | int err; |
338 | 436 | ||
339 | err = crypto_check_alg(&inst->alg); | 437 | err = crypto_check_alg(&inst->alg); |
340 | if (err) | 438 | if (err) |
@@ -344,8 +442,8 @@ int crypto_register_instance(struct crypto_template *tmpl, | |||
344 | 442 | ||
345 | down_write(&crypto_alg_sem); | 443 | down_write(&crypto_alg_sem); |
346 | 444 | ||
347 | err = __crypto_register_alg(&inst->alg, &list); | 445 | larval = __crypto_register_alg(&inst->alg); |
348 | if (err) | 446 | if (IS_ERR(larval)) |
349 | goto unlock; | 447 | goto unlock; |
350 | 448 | ||
351 | hlist_add_head(&inst->list, &tmpl->instances); | 449 | hlist_add_head(&inst->list, &tmpl->instances); |
@@ -354,7 +452,12 @@ int crypto_register_instance(struct crypto_template *tmpl, | |||
354 | unlock: | 452 | unlock: |
355 | up_write(&crypto_alg_sem); | 453 | up_write(&crypto_alg_sem); |
356 | 454 | ||
357 | crypto_remove_final(&list); | 455 | err = PTR_ERR(larval); |
456 | if (IS_ERR(larval)) | ||
457 | goto err; | ||
458 | |||
459 | crypto_wait_for_test(larval); | ||
460 | err = 0; | ||
358 | 461 | ||
359 | err: | 462 | err: |
360 | return err; | 463 | return err; |
diff --git a/crypto/algboss.c b/crypto/algboss.c index 2662ac014841..ed9f663c82c6 100644 --- a/crypto/algboss.c +++ b/crypto/algboss.c | |||
@@ -45,6 +45,15 @@ struct cryptomgr_param { | |||
45 | 45 | ||
46 | char larval[CRYPTO_MAX_ALG_NAME]; | 46 | char larval[CRYPTO_MAX_ALG_NAME]; |
47 | char template[CRYPTO_MAX_ALG_NAME]; | 47 | char template[CRYPTO_MAX_ALG_NAME]; |
48 | |||
49 | u32 otype; | ||
50 | u32 omask; | ||
51 | }; | ||
52 | |||
53 | struct crypto_test_param { | ||
54 | char driver[CRYPTO_MAX_ALG_NAME]; | ||
55 | char alg[CRYPTO_MAX_ALG_NAME]; | ||
56 | u32 type; | ||
48 | }; | 57 | }; |
49 | 58 | ||
50 | static int cryptomgr_probe(void *data) | 59 | static int cryptomgr_probe(void *data) |
@@ -76,8 +85,7 @@ out: | |||
76 | module_put_and_exit(0); | 85 | module_put_and_exit(0); |
77 | 86 | ||
78 | err: | 87 | err: |
79 | crypto_larval_error(param->larval, param->type.data.type, | 88 | crypto_larval_error(param->larval, param->otype, param->omask); |
80 | param->type.data.mask); | ||
81 | goto out; | 89 | goto out; |
82 | } | 90 | } |
83 | 91 | ||
@@ -169,13 +177,68 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) | |||
169 | 177 | ||
170 | param->type.attr.rta_len = sizeof(param->type); | 178 | param->type.attr.rta_len = sizeof(param->type); |
171 | param->type.attr.rta_type = CRYPTOA_TYPE; | 179 | param->type.attr.rta_type = CRYPTOA_TYPE; |
172 | param->type.data.type = larval->alg.cra_flags; | 180 | param->type.data.type = larval->alg.cra_flags & ~CRYPTO_ALG_TESTED; |
173 | param->type.data.mask = larval->mask; | 181 | param->type.data.mask = larval->mask & ~CRYPTO_ALG_TESTED; |
174 | param->tb[0] = ¶m->type.attr; | 182 | param->tb[0] = ¶m->type.attr; |
175 | 183 | ||
184 | param->otype = larval->alg.cra_flags; | ||
185 | param->omask = larval->mask; | ||
186 | |||
176 | memcpy(param->larval, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); | 187 | memcpy(param->larval, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); |
177 | 188 | ||
178 | thread = kthread_run(cryptomgr_probe, param, "cryptomgr"); | 189 | thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe"); |
190 | if (IS_ERR(thread)) | ||
191 | goto err_free_param; | ||
192 | |||
193 | return NOTIFY_STOP; | ||
194 | |||
195 | err_free_param: | ||
196 | kfree(param); | ||
197 | err_put_module: | ||
198 | module_put(THIS_MODULE); | ||
199 | err: | ||
200 | return NOTIFY_OK; | ||
201 | } | ||
202 | |||
203 | static int cryptomgr_test(void *data) | ||
204 | { | ||
205 | struct crypto_test_param *param = data; | ||
206 | u32 type = param->type; | ||
207 | int err = 0; | ||
208 | |||
209 | if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & | ||
210 | CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV)) | ||
211 | goto skiptest; | ||
212 | |||
213 | if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) | ||
214 | goto skiptest; | ||
215 | |||
216 | err = alg_test(param->driver, param->alg, 0, CRYPTO_ALG_TESTED); | ||
217 | |||
218 | skiptest: | ||
219 | crypto_alg_tested(param->driver, err); | ||
220 | |||
221 | kfree(param); | ||
222 | module_put_and_exit(0); | ||
223 | } | ||
224 | |||
225 | static int cryptomgr_schedule_test(struct crypto_alg *alg) | ||
226 | { | ||
227 | struct task_struct *thread; | ||
228 | struct crypto_test_param *param; | ||
229 | |||
230 | if (!try_module_get(THIS_MODULE)) | ||
231 | goto err; | ||
232 | |||
233 | param = kzalloc(sizeof(*param), GFP_KERNEL); | ||
234 | if (!param) | ||
235 | goto err_put_module; | ||
236 | |||
237 | memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver)); | ||
238 | memcpy(param->alg, alg->cra_name, sizeof(param->alg)); | ||
239 | param->type = alg->cra_flags; | ||
240 | |||
241 | thread = kthread_run(cryptomgr_test, param, "cryptomgr_test"); | ||
179 | if (IS_ERR(thread)) | 242 | if (IS_ERR(thread)) |
180 | goto err_free_param; | 243 | goto err_free_param; |
181 | 244 | ||
@@ -195,6 +258,8 @@ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, | |||
195 | switch (msg) { | 258 | switch (msg) { |
196 | case CRYPTO_MSG_ALG_REQUEST: | 259 | case CRYPTO_MSG_ALG_REQUEST: |
197 | return cryptomgr_schedule_probe(data); | 260 | return cryptomgr_schedule_probe(data); |
261 | case CRYPTO_MSG_ALG_REGISTER: | ||
262 | return cryptomgr_schedule_test(data); | ||
198 | } | 263 | } |
199 | 264 | ||
200 | return NOTIFY_DONE; | 265 | return NOTIFY_DONE; |
diff --git a/crypto/api.c b/crypto/api.c index 0906cedd4521..0444d242e985 100644 --- a/crypto/api.c +++ b/crypto/api.c | |||
@@ -55,6 +55,11 @@ void crypto_mod_put(struct crypto_alg *alg) | |||
55 | } | 55 | } |
56 | EXPORT_SYMBOL_GPL(crypto_mod_put); | 56 | EXPORT_SYMBOL_GPL(crypto_mod_put); |
57 | 57 | ||
58 | static inline int crypto_is_test_larval(struct crypto_larval *larval) | ||
59 | { | ||
60 | return larval->alg.cra_driver_name[0]; | ||
61 | } | ||
62 | |||
58 | static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, | 63 | static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, |
59 | u32 mask) | 64 | u32 mask) |
60 | { | 65 | { |
@@ -71,6 +76,7 @@ static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, | |||
71 | continue; | 76 | continue; |
72 | 77 | ||
73 | if (crypto_is_larval(q) && | 78 | if (crypto_is_larval(q) && |
79 | !crypto_is_test_larval((struct crypto_larval *)q) && | ||
74 | ((struct crypto_larval *)q)->mask != mask) | 80 | ((struct crypto_larval *)q)->mask != mask) |
75 | continue; | 81 | continue; |
76 | 82 | ||
@@ -104,10 +110,8 @@ static void crypto_larval_destroy(struct crypto_alg *alg) | |||
104 | kfree(larval); | 110 | kfree(larval); |
105 | } | 111 | } |
106 | 112 | ||
107 | static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, | 113 | struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask) |
108 | u32 mask) | ||
109 | { | 114 | { |
110 | struct crypto_alg *alg; | ||
111 | struct crypto_larval *larval; | 115 | struct crypto_larval *larval; |
112 | 116 | ||
113 | larval = kzalloc(sizeof(*larval), GFP_KERNEL); | 117 | larval = kzalloc(sizeof(*larval), GFP_KERNEL); |
@@ -119,10 +123,25 @@ static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, | |||
119 | larval->alg.cra_priority = -1; | 123 | larval->alg.cra_priority = -1; |
120 | larval->alg.cra_destroy = crypto_larval_destroy; | 124 | larval->alg.cra_destroy = crypto_larval_destroy; |
121 | 125 | ||
122 | atomic_set(&larval->alg.cra_refcnt, 2); | ||
123 | strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); | 126 | strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); |
124 | init_completion(&larval->completion); | 127 | init_completion(&larval->completion); |
125 | 128 | ||
129 | return larval; | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(crypto_larval_alloc); | ||
132 | |||
133 | static struct crypto_alg *crypto_larval_add(const char *name, u32 type, | ||
134 | u32 mask) | ||
135 | { | ||
136 | struct crypto_alg *alg; | ||
137 | struct crypto_larval *larval; | ||
138 | |||
139 | larval = crypto_larval_alloc(name, type, mask); | ||
140 | if (IS_ERR(larval)) | ||
141 | return ERR_CAST(larval); | ||
142 | |||
143 | atomic_set(&larval->alg.cra_refcnt, 2); | ||
144 | |||
126 | down_write(&crypto_alg_sem); | 145 | down_write(&crypto_alg_sem); |
127 | alg = __crypto_alg_lookup(name, type, mask); | 146 | alg = __crypto_alg_lookup(name, type, mask); |
128 | if (!alg) { | 147 | if (!alg) { |
@@ -152,14 +171,23 @@ EXPORT_SYMBOL_GPL(crypto_larval_kill); | |||
152 | static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) | 171 | static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) |
153 | { | 172 | { |
154 | struct crypto_larval *larval = (void *)alg; | 173 | struct crypto_larval *larval = (void *)alg; |
174 | long timeout; | ||
175 | |||
176 | timeout = wait_for_completion_interruptible_timeout( | ||
177 | &larval->completion, 60 * HZ); | ||
155 | 178 | ||
156 | wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ); | ||
157 | alg = larval->adult; | 179 | alg = larval->adult; |
158 | if (alg) { | 180 | if (timeout < 0) |
159 | if (!crypto_mod_get(alg)) | 181 | alg = ERR_PTR(-EINTR); |
160 | alg = ERR_PTR(-EAGAIN); | 182 | else if (!timeout) |
161 | } else | 183 | alg = ERR_PTR(-ETIMEDOUT); |
184 | else if (!alg) | ||
162 | alg = ERR_PTR(-ENOENT); | 185 | alg = ERR_PTR(-ENOENT); |
186 | else if (crypto_is_test_larval(larval) && | ||
187 | !(alg->cra_flags & CRYPTO_ALG_TESTED)) | ||
188 | alg = ERR_PTR(-EAGAIN); | ||
189 | else if (!crypto_mod_get(alg)) | ||
190 | alg = ERR_PTR(-EAGAIN); | ||
163 | crypto_mod_put(&larval->alg); | 191 | crypto_mod_put(&larval->alg); |
164 | 192 | ||
165 | return alg; | 193 | return alg; |
@@ -192,25 +220,40 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) | |||
192 | if (alg) | 220 | if (alg) |
193 | return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; | 221 | return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; |
194 | 222 | ||
195 | return crypto_larval_alloc(name, type, mask); | 223 | return crypto_larval_add(name, type, mask); |
196 | } | 224 | } |
197 | EXPORT_SYMBOL_GPL(crypto_larval_lookup); | 225 | EXPORT_SYMBOL_GPL(crypto_larval_lookup); |
198 | 226 | ||
227 | int crypto_probing_notify(unsigned long val, void *v) | ||
228 | { | ||
229 | int ok; | ||
230 | |||
231 | ok = blocking_notifier_call_chain(&crypto_chain, val, v); | ||
232 | if (ok == NOTIFY_DONE) { | ||
233 | request_module("cryptomgr"); | ||
234 | ok = blocking_notifier_call_chain(&crypto_chain, val, v); | ||
235 | } | ||
236 | |||
237 | return ok; | ||
238 | } | ||
239 | EXPORT_SYMBOL_GPL(crypto_probing_notify); | ||
240 | |||
199 | struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) | 241 | struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) |
200 | { | 242 | { |
201 | struct crypto_alg *alg; | 243 | struct crypto_alg *alg; |
202 | struct crypto_alg *larval; | 244 | struct crypto_alg *larval; |
203 | int ok; | 245 | int ok; |
204 | 246 | ||
247 | if (!(mask & CRYPTO_ALG_TESTED)) { | ||
248 | type |= CRYPTO_ALG_TESTED; | ||
249 | mask |= CRYPTO_ALG_TESTED; | ||
250 | } | ||
251 | |||
205 | larval = crypto_larval_lookup(name, type, mask); | 252 | larval = crypto_larval_lookup(name, type, mask); |
206 | if (IS_ERR(larval) || !crypto_is_larval(larval)) | 253 | if (IS_ERR(larval) || !crypto_is_larval(larval)) |
207 | return larval; | 254 | return larval; |
208 | 255 | ||
209 | ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); | 256 | ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval); |
210 | if (ok == NOTIFY_DONE) { | ||
211 | request_module("cryptomgr"); | ||
212 | ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); | ||
213 | } | ||
214 | 257 | ||
215 | if (ok == NOTIFY_STOP) | 258 | if (ok == NOTIFY_STOP) |
216 | alg = crypto_larval_wait(larval); | 259 | alg = crypto_larval_wait(larval); |
diff --git a/crypto/internal.h b/crypto/internal.h index 48cb70416d59..fc93743c5d3e 100644 --- a/crypto/internal.h +++ b/crypto/internal.h | |||
@@ -94,9 +94,11 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm); | |||
94 | void crypto_exit_cipher_ops(struct crypto_tfm *tfm); | 94 | void crypto_exit_cipher_ops(struct crypto_tfm *tfm); |
95 | void crypto_exit_compress_ops(struct crypto_tfm *tfm); | 95 | void crypto_exit_compress_ops(struct crypto_tfm *tfm); |
96 | 96 | ||
97 | struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask); | ||
97 | void crypto_larval_kill(struct crypto_alg *alg); | 98 | void crypto_larval_kill(struct crypto_alg *alg); |
98 | struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask); | 99 | struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask); |
99 | void crypto_larval_error(const char *name, u32 type, u32 mask); | 100 | void crypto_larval_error(const char *name, u32 type, u32 mask); |
101 | void crypto_alg_tested(const char *name, int err); | ||
100 | 102 | ||
101 | void crypto_shoot_alg(struct crypto_alg *alg); | 103 | void crypto_shoot_alg(struct crypto_alg *alg); |
102 | struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, | 104 | struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, |
@@ -107,6 +109,7 @@ int crypto_register_instance(struct crypto_template *tmpl, | |||
107 | 109 | ||
108 | int crypto_register_notifier(struct notifier_block *nb); | 110 | int crypto_register_notifier(struct notifier_block *nb); |
109 | int crypto_unregister_notifier(struct notifier_block *nb); | 111 | int crypto_unregister_notifier(struct notifier_block *nb); |
112 | int crypto_probing_notify(unsigned long val, void *v); | ||
110 | 113 | ||
111 | int __init testmgr_init(void); | 114 | int __init testmgr_init(void); |
112 | void testmgr_exit(void); | 115 | void testmgr_exit(void); |
@@ -142,9 +145,9 @@ static inline int crypto_is_moribund(struct crypto_alg *alg) | |||
142 | return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING); | 145 | return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING); |
143 | } | 146 | } |
144 | 147 | ||
145 | static inline int crypto_notify(unsigned long val, void *v) | 148 | static inline void crypto_notify(unsigned long val, void *v) |
146 | { | 149 | { |
147 | return blocking_notifier_call_chain(&crypto_chain, val, v); | 150 | blocking_notifier_call_chain(&crypto_chain, val, v); |
148 | } | 151 | } |
149 | 152 | ||
150 | #endif /* _CRYPTO_INTERNAL_H */ | 153 | #endif /* _CRYPTO_INTERNAL_H */ |
diff --git a/crypto/proc.c b/crypto/proc.c index c6ede1e9c875..1d616adead0d 100644 --- a/crypto/proc.c +++ b/crypto/proc.c | |||
@@ -46,6 +46,9 @@ static int c_show(struct seq_file *m, void *p) | |||
46 | seq_printf(m, "module : %s\n", module_name(alg->cra_module)); | 46 | seq_printf(m, "module : %s\n", module_name(alg->cra_module)); |
47 | seq_printf(m, "priority : %d\n", alg->cra_priority); | 47 | seq_printf(m, "priority : %d\n", alg->cra_priority); |
48 | seq_printf(m, "refcnt : %d\n", atomic_read(&alg->cra_refcnt)); | 48 | seq_printf(m, "refcnt : %d\n", atomic_read(&alg->cra_refcnt)); |
49 | seq_printf(m, "selftest : %s\n", | ||
50 | (alg->cra_flags & CRYPTO_ALG_TESTED) ? | ||
51 | "passed" : "unknown"); | ||
49 | 52 | ||
50 | switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) { | 53 | switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) { |
51 | case CRYPTO_ALG_TYPE_CIPHER: | 54 | case CRYPTO_ALG_TYPE_CIPHER: |
diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 7ea0a4bc4ced..81d994a3bdaf 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h | |||
@@ -61,6 +61,14 @@ | |||
61 | #define CRYPTO_ALG_GENIV 0x00000200 | 61 | #define CRYPTO_ALG_GENIV 0x00000200 |
62 | 62 | ||
63 | /* | 63 | /* |
64 | * Set if the algorithm has passed automated run-time testing. Note that | ||
65 | * if there is no run-time testing for a given algorithm it is considered | ||
66 | * to have passed. | ||
67 | */ | ||
68 | |||
69 | #define CRYPTO_ALG_TESTED 0x00000400 | ||
70 | |||
71 | /* | ||
64 | * Transform masks and values (for crt_flags). | 72 | * Transform masks and values (for crt_flags). |
65 | */ | 73 | */ |
66 | #define CRYPTO_TFM_REQ_MASK 0x000fff00 | 74 | #define CRYPTO_TFM_REQ_MASK 0x000fff00 |