diff --git a/crypto/algapi.c b/crypto/algapi.c index f0df85fc1f50..acea250677c0 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -21,12 +21,12 @@ static LIST_HEAD(crypto_template_list); -void crypto_larval_error(const char *name) +void crypto_larval_error(const char *name, u32 type, u32 mask) { struct crypto_alg *alg; down_read(&crypto_alg_sem); - alg = __crypto_alg_lookup(name); + alg = __crypto_alg_lookup(name, type, mask); up_read(&crypto_alg_sem); if (alg) { @@ -87,6 +87,8 @@ static int __crypto_register_alg(struct crypto_alg *alg) !strcmp(alg->cra_driver_name, q->cra_name))) { struct crypto_larval *larval = (void *)q; + if ((q->cra_flags ^ alg->cra_flags) & larval->mask) + continue; if (!crypto_mod_get(alg)) continue; larval->adult = alg; diff --git a/crypto/api.c b/crypto/api.c index 67cd6f87b74a..ddf6a767acdd 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -57,7 +57,7 @@ void crypto_mod_put(struct crypto_alg *alg) } EXPORT_SYMBOL_GPL(crypto_mod_put); -struct crypto_alg *__crypto_alg_lookup(const char *name) +struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) { struct crypto_alg *q, *alg = NULL; int best = -2; @@ -65,6 +65,13 @@ struct crypto_alg *__crypto_alg_lookup(const char *name) list_for_each_entry(q, &crypto_alg_list, cra_list) { int exact, fuzzy; + if ((q->cra_flags ^ type) & mask) + continue; + + if (crypto_is_larval(q) && + ((struct crypto_larval *)q)->mask != mask) + continue; + exact = !strcmp(q->cra_driver_name, name); fuzzy = !strcmp(q->cra_name, name); if (!exact && !(fuzzy && q->cra_priority > best)) @@ -96,7 +103,8 @@ static void crypto_larval_destroy(struct crypto_alg *alg) kfree(larval); } -static struct crypto_alg *crypto_larval_alloc(const char *name) +static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, + u32 mask) { struct crypto_alg *alg; struct crypto_larval *larval; @@ -105,7 +113,8 @@ static struct crypto_alg *crypto_larval_alloc(const char *name) if (!larval) return NULL; - larval->alg.cra_flags = CRYPTO_ALG_LARVAL; + larval->mask = mask; + larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type; larval->alg.cra_priority = -1; larval->alg.cra_destroy = crypto_larval_destroy; @@ -114,7 +123,7 @@ static struct crypto_alg *crypto_larval_alloc(const char *name) init_completion(&larval->completion); down_write(&crypto_alg_sem); - alg = __crypto_alg_lookup(name); + alg = __crypto_alg_lookup(name, type, mask); if (!alg) { alg = &larval->alg; list_add(&alg->cra_list, &crypto_alg_list); @@ -151,7 +160,8 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) return alg; } -static struct crypto_alg *crypto_alg_lookup(const char *name) +static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, + u32 mask) { struct crypto_alg *alg; @@ -159,25 +169,27 @@ static struct crypto_alg *crypto_alg_lookup(const char *name) return NULL; down_read(&crypto_alg_sem); - alg = __crypto_alg_lookup(name); + alg = __crypto_alg_lookup(name, type, mask); up_read(&crypto_alg_sem); return alg; } -/* A far more intelligent version of this is planned. For now, just - * try an exact match on the name of the algorithm. */ -static struct crypto_alg *crypto_alg_mod_lookup(const char *name) +struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) { struct crypto_alg *alg; struct crypto_alg *larval; int ok; - alg = try_then_request_module(crypto_alg_lookup(name), name); + mask &= ~CRYPTO_ALG_LARVAL; + type &= mask; + + alg = try_then_request_module(crypto_alg_lookup(name, type, mask), + name); if (alg) return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; - larval = crypto_larval_alloc(name); + larval = crypto_larval_alloc(name, type, mask); if (!larval || !crypto_is_larval(larval)) return larval; @@ -196,6 +208,7 @@ static struct crypto_alg *crypto_alg_mod_lookup(const char *name) crypto_larval_kill(larval); return alg; } +EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup); static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) { @@ -291,7 +304,7 @@ struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) struct crypto_alg *alg; unsigned int tfm_size; - alg = crypto_alg_mod_lookup(name); + alg = crypto_alg_mod_lookup(name, 0, 0); if (alg == NULL) goto out; @@ -346,7 +359,7 @@ void crypto_free_tfm(struct crypto_tfm *tfm) int crypto_alg_available(const char *name, u32 flags) { int ret = 0; - struct crypto_alg *alg = crypto_alg_mod_lookup(name); + struct crypto_alg *alg = crypto_alg_mod_lookup(name, 0, 0); if (alg) { crypto_mod_put(alg); diff --git a/crypto/cryptomgr.c b/crypto/cryptomgr.c index e0ebe1b44b99..ae54942e3b31 100644 --- a/crypto/cryptomgr.c +++ b/crypto/cryptomgr.c @@ -31,6 +31,8 @@ struct cryptomgr_param { } alg; struct { + u32 type; + u32 mask; char name[CRYPTO_MAX_ALG_NAME]; } larval; @@ -62,7 +64,8 @@ out: return; err: - crypto_larval_error(param->larval.name); + crypto_larval_error(param->larval.name, param->larval.type, + param->larval.mask); goto out; } @@ -101,6 +104,8 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) param->alg.data.name[len] = 0; memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); + param->larval.type = larval->alg.cra_flags; + param->larval.mask = larval->mask; INIT_WORK(¶m->work, cryptomgr_probe, param); schedule_work(¶m->work); diff --git a/crypto/internal.h b/crypto/internal.h index 3a08d25fba45..c08d93bdadc4 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -43,6 +43,7 @@ struct crypto_larval { struct crypto_alg alg; struct crypto_alg *adult; struct completion completion; + u32 mask; }; extern struct list_head crypto_alg_list; @@ -124,7 +125,8 @@ static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg, struct crypto_alg *crypto_mod_get(struct crypto_alg *alg); void crypto_mod_put(struct crypto_alg *alg); -struct crypto_alg *__crypto_alg_lookup(const char *name); +struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask); +struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); @@ -138,7 +140,7 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm); void crypto_exit_cipher_ops(struct crypto_tfm *tfm); void crypto_exit_compress_ops(struct crypto_tfm *tfm); -void crypto_larval_error(const char *name); +void crypto_larval_error(const char *name, u32 type, u32 mask); int crypto_register_instance(struct crypto_template *tmpl, struct crypto_instance *inst);