--- zzzz-none-000/linux-3.10.107/crypto/algapi.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/crypto/algapi.c 2021-02-04 17:41:59.000000000 +0000 @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -41,8 +42,17 @@ return 0; } +static inline void crypto_check_module_sig(struct module *mod) +{ + if (fips_enabled && mod && !module_sig_ok(mod)) + panic("Module %s signature verification failed in FIPS mode\n", + module_name(mod)); +} + static int crypto_check_alg(struct crypto_alg *alg) { + crypto_check_module_sig(alg->cra_module); + if (alg->cra_alignmask & (alg->cra_alignmask + 1)) return -EINVAL; @@ -52,15 +62,27 @@ if (alg->cra_priority < 0) return -EINVAL; + atomic_set(&alg->cra_refcnt, 1); + return crypto_set_driver_name(alg); } +static void crypto_free_instance(struct crypto_instance *inst) +{ + if (!inst->alg.cra_type->free) { + inst->tmpl->free(inst); + return; + } + + inst->alg.cra_type->free(inst); +} + static void crypto_destroy_instance(struct crypto_alg *alg) { struct crypto_instance *inst = (void *)alg; struct crypto_template *tmpl = inst->tmpl; - tmpl->free(inst); + crypto_free_instance(inst); crypto_tmpl_put(tmpl); } @@ -87,10 +109,9 @@ return &n->list == stack ? top : &n->inst->alg.cra_users; } -static void crypto_remove_spawn(struct crypto_spawn *spawn, - struct list_head *list) +static void crypto_remove_instance(struct crypto_instance *inst, + struct list_head *list) { - struct crypto_instance *inst = spawn->inst; struct crypto_template *tmpl = inst->tmpl; if (crypto_is_dead(&inst->alg)) @@ -155,7 +176,7 @@ if (spawn->alg) list_move(&spawn->list, &spawn->alg->cra_users); else - crypto_remove_spawn(spawn, list); + crypto_remove_instance(spawn->inst, list); } } EXPORT_SYMBOL_GPL(crypto_remove_spawns); @@ -176,7 +197,6 @@ ret = -EEXIST; - atomic_set(&alg->cra_refcnt, 1); list_for_each_entry(q, &crypto_alg_list, cra_list) { if (q == alg) goto err; @@ -431,6 +451,8 @@ down_write(&crypto_alg_sem); + crypto_check_module_sig(tmpl->module); + list_for_each_entry(q, &crypto_template_list, list) { if (q == tmpl) goto out; @@ -460,6 +482,7 @@ list = &tmpl->instances; hlist_for_each_entry(inst, list, list) { int err = crypto_remove_alg(&inst->alg, &users); + BUG_ON(err); } @@ -469,7 +492,7 @@ hlist_for_each_entry_safe(inst, n, list, list) { BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1); - tmpl->free(inst); + crypto_free_instance(inst); } crypto_remove_final(&users); } @@ -509,11 +532,14 @@ err = crypto_check_alg(&inst->alg); if (err) - goto err; + return err; inst->alg.cra_module = tmpl->module; inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE; + if (unlikely(!crypto_mod_get(&inst->alg))) + return -EAGAIN; + down_write(&crypto_alg_sem); larval = __crypto_register_alg(&inst->alg); @@ -531,37 +557,30 @@ goto err; crypto_wait_for_test(larval); + + /* Remove instance if test failed */ + if (!(inst->alg.cra_flags & CRYPTO_ALG_TESTED)) + crypto_unregister_instance(inst); err = 0; err: + crypto_mod_put(&inst->alg); return err; } EXPORT_SYMBOL_GPL(crypto_register_instance); -int crypto_unregister_instance(struct crypto_alg *alg) +int crypto_unregister_instance(struct crypto_instance *inst) { - int err; - struct crypto_instance *inst = (void *)alg; - struct crypto_template *tmpl = inst->tmpl; - LIST_HEAD(users); - - if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE)) - return -EINVAL; - - BUG_ON(atomic_read(&alg->cra_refcnt) != 1); + LIST_HEAD(list); down_write(&crypto_alg_sem); - hlist_del_init(&inst->list); - err = crypto_remove_alg(alg, &users); + crypto_remove_spawns(&inst->alg, &list, NULL); + crypto_remove_instance(inst, &list); up_write(&crypto_alg_sem); - if (err) - return err; - - tmpl->free(inst); - crypto_remove_final(&users); + crypto_remove_final(&list); return 0; } @@ -604,6 +623,22 @@ } EXPORT_SYMBOL_GPL(crypto_init_spawn2); +int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name, + u32 type, u32 mask) +{ + struct crypto_alg *alg; + int err; + + alg = crypto_find_alg(name, spawn->frontend, type, mask); + if (IS_ERR(alg)) + return PTR_ERR(alg); + + err = crypto_init_spawn(spawn, alg, spawn->inst, mask); + crypto_mod_put(alg); + return err; +} +EXPORT_SYMBOL_GPL(crypto_grab_spawn); + void crypto_drop_spawn(struct crypto_spawn *spawn) { if (!spawn->alg) @@ -868,7 +903,7 @@ } EXPORT_SYMBOL_GPL(crypto_enqueue_request); -void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset) +struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) { struct list_head *request; @@ -883,14 +918,7 @@ request = queue->list.next; list_del(request); - return (char *)list_entry(request, struct crypto_async_request, list) - - offset; -} -EXPORT_SYMBOL_GPL(__crypto_dequeue_request); - -struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) -{ - return __crypto_dequeue_request(queue, 0); + return list_entry(request, struct crypto_async_request, list); } EXPORT_SYMBOL_GPL(crypto_dequeue_request); @@ -954,6 +982,13 @@ } EXPORT_SYMBOL_GPL(crypto_xor); +unsigned int crypto_alg_extsize(struct crypto_alg *alg) +{ + return alg->cra_ctxsize + + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1)); +} +EXPORT_SYMBOL_GPL(crypto_alg_extsize); + static int __init crypto_algapi_init(void) { crypto_init_proc();