[CRYPTO] api: Allow algorithm lookup by type
authorHerbert Xu <herbert@gondor.apana.org.au>
Thu, 21 Sep 2006 01:35:17 +0000 (11:35 +1000)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 21 Sep 2006 01:35:17 +0000 (11:35 +1000)
This patch also adds the infrastructure to pick an algorithm based on
their type.  For example, this allows you to select the encryption
algorithm "aes", instead of any algorithm registered under the name
"aes".  For now this is only accessible internally.  Eventually it
will be made available through crypto_alloc_tfm.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
crypto/algapi.c
crypto/api.c
crypto/cryptomgr.c
crypto/internal.h

index f0df85fc1f50b720c1eafe443a77f36aac61195b..acea250677c0285266adbd877710c2e5873bd26f 100644 (file)
 
 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;
index 67cd6f87b74a5289d2ac7b3be0b9da2dc322c6a9..ddf6a767acdd72a155c44ea5dbcc62bce2450dc4 100644 (file)
@@ -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);
index e0ebe1b44b994a19574116823153e1a08ce6a4ad..ae54942e3b3102c54c72460a56022f5aae787061 100644 (file)
@@ -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(&param->work, cryptomgr_probe, param);
        schedule_work(&param->work);
index 3a08d25fba45223e198652192bb1a2ba0fa4e695..c08d93bdadc450bf91de85998fabfba96a28a137 100644 (file)
@@ -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);