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 /crypto | |
| 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>
Diffstat (limited to 'crypto')
| -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 |
5 files changed, 259 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: |
