[CRYPTO] templates: Pass type/mask when creating instances
authorHerbert Xu <herbert@gondor.apana.org.au>
Mon, 1 Jan 2007 07:37:02 +0000 (18:37 +1100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Wed, 2 May 2007 04:38:31 +0000 (14:38 +1000)
This patch passes the type/mask along when constructing instances of
templates.  This is in preparation for templates that may support
multiple types of instances depending on what is requested.  For example,
the planned software async crypto driver will use this construct.

For the moment this allows us to check whether the instance constructed
is of the correct type and avoid returning success if the type does not
match.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/algapi.c
crypto/cbc.c
crypto/cryptomgr.c
crypto/ecb.c
crypto/hmac.c
crypto/lrw.c
crypto/pcbc.c
crypto/xcbc.c
include/crypto/algapi.h
include/linux/crypto.h

index f7d2185b2c8fbac94cf6f6736b5f1a965f224bb9..491205e11cbe4bf1316c25544385abda90b5590f 100644 (file)
@@ -425,15 +425,45 @@ int crypto_unregister_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-                                      u32 type, u32 mask)
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
 {
-       struct rtattr *rta = param;
+       struct rtattr *rta = tb[CRYPTOA_TYPE - 1];
+       struct crypto_attr_type *algt;
+
+       if (!rta)
+               return ERR_PTR(-ENOENT);
+       if (RTA_PAYLOAD(rta) < sizeof(*algt))
+               return ERR_PTR(-EINVAL);
+
+       algt = RTA_DATA(rta);
+
+       return algt;
+}
+EXPORT_SYMBOL_GPL(crypto_get_attr_type);
+
+int crypto_check_attr_type(struct rtattr **tb, u32 type)
+{
+       struct crypto_attr_type *algt;
+
+       algt = crypto_get_attr_type(tb);
+       if (IS_ERR(algt))
+               return PTR_ERR(algt);
+
+       if ((algt->type ^ type) & algt->mask)
+               return -EINVAL;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_check_attr_type);
+
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask)
+{
+       struct rtattr *rta = tb[CRYPTOA_ALG - 1];
        struct crypto_attr_alg *alga;
 
-       if (!RTA_OK(rta, len))
-               return ERR_PTR(-EBADR);
-       if (rta->rta_type != CRYPTOA_ALG || RTA_PAYLOAD(rta) < sizeof(*alga))
+       if (!rta)
+               return ERR_PTR(-ENOENT);
+       if (RTA_PAYLOAD(rta) < sizeof(*alga))
                return ERR_PTR(-EINVAL);
 
        alga = RTA_DATA(rta);
index 136fea7e700095542c585cbb7cae9c16b64eb667..1f2649e13b4266ebc1354bd701c6b98d23c83d2e 100644 (file)
@@ -275,13 +275,18 @@ static void crypto_cbc_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_cbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 2ebffb84f1d99552bc707162eeb26a9d08f4277f..7a3df9b4121881a65bd723ee7ef883baaec0e80f 100644 (file)
 struct cryptomgr_param {
        struct work_struct work;
 
+       struct rtattr *tb[CRYPTOA_MAX];
+
+       struct {
+               struct rtattr attr;
+               struct crypto_attr_type data;
+       } type;
+
        struct {
                struct rtattr attr;
                struct crypto_attr_alg data;
        } alg;
 
        struct {
-               u32 type;
-               u32 mask;
                char name[CRYPTO_MAX_ALG_NAME];
        } larval;
 
@@ -53,7 +58,7 @@ static void cryptomgr_probe(struct work_struct *work)
                goto err;
 
        do {
-               inst = tmpl->alloc(&param->alg, sizeof(param->alg));
+               inst = tmpl->alloc(param->tb);
                if (IS_ERR(inst))
                        err = PTR_ERR(inst);
                else if ((err = crypto_register_instance(tmpl, inst)))
@@ -70,8 +75,8 @@ out:
        return;
 
 err:
-       crypto_larval_error(param->larval.name, param->larval.type,
-                           param->larval.mask);
+       crypto_larval_error(param->larval.name, param->type.data.type,
+                           param->type.data.mask);
        goto out;
 }
 
@@ -82,7 +87,7 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
        const char *p;
        unsigned int len;
 
-       param = kmalloc(sizeof(*param), GFP_KERNEL);
+       param = kzalloc(sizeof(*param), GFP_KERNEL);
        if (!param)
                goto err;
 
@@ -94,7 +99,6 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
                goto err_free_param;
 
        memcpy(param->template, name, len);
-       param->template[len] = 0;
 
        name = p + 1;
        for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
@@ -104,14 +108,18 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
        if (!len || *p != ')' || p[1])
                goto err_free_param;
 
+       param->type.attr.rta_len = sizeof(param->type);
+       param->type.attr.rta_type = CRYPTOA_TYPE;
+       param->type.data.type = larval->alg.cra_flags;
+       param->type.data.mask = larval->mask;
+       param->tb[CRYPTOA_TYPE - 1] = &param->type.attr;
+
        param->alg.attr.rta_len = sizeof(param->alg);
        param->alg.attr.rta_type = CRYPTOA_ALG;
        memcpy(param->alg.data.name, name, len);
-       param->alg.data.name[len] = 0;
+       param->tb[CRYPTOA_ALG - 1] = &param->alg.attr;
 
        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);
        schedule_work(&param->work);
index 839a0aed8c229c26631ff56032165a19295a0531..6310387a872c6c4df4dd538a3d60f25c70391590 100644 (file)
@@ -115,13 +115,18 @@ static void crypto_ecb_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_ecb_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_ecb_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 44187c5ee5933cbf9195ec799d337053ef0e0b8e..8802fb6dd5a6c857e4d78880944d5f9c3cc6c9d4 100644 (file)
@@ -197,13 +197,18 @@ static void hmac_free(struct crypto_instance *inst)
        kfree(inst);
 }
 
-static struct crypto_instance *hmac_alloc(void *param, unsigned int len)
+static struct crypto_instance *hmac_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_HASH,
-                                 CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH,
+                                 CRYPTO_ALG_TYPE_HASH_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index b4105080ac7aa9d5886ea28772cfea6101197d27..621095db28b354fa314acb44528f514baf026cf5 100644 (file)
@@ -228,13 +228,18 @@ static void exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *alloc(void *param, unsigned int len)
+static struct crypto_instance *alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 5174d7fdad6e20f2d3051d60d3c764dfeb8dbaf1..c3ed8a1c9f4616022ad1e80525875c8f5ce776d0 100644 (file)
@@ -279,13 +279,18 @@ static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_pcbc_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 53e8ccbf0f5f514d9023431d9e15a47e53ed705e..9f502b86e0ea563ac04b31fbf96dcd534367e05a 100644 (file)
@@ -288,12 +288,18 @@ static void xcbc_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *xcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+       if (err)
+               return ERR_PTR(err);
+
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 4e05e93ff6811248002485475e8a624fa1209cf1..d0c190b4d02fb439b1884c3130459af9047ad0ab 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/crypto.h>
 
 struct module;
+struct rtattr;
 struct seq_file;
 
 struct crypto_type {
@@ -38,7 +39,7 @@ struct crypto_template {
        struct hlist_head instances;
        struct module *module;
 
-       struct crypto_instance *(*alloc)(void *param, unsigned int len);
+       struct crypto_instance *(*alloc)(struct rtattr **tb);
        void (*free)(struct crypto_instance *inst);
 
        char name[CRYPTO_MAX_ALG_NAME];
@@ -96,8 +97,9 @@ void crypto_drop_spawn(struct crypto_spawn *spawn);
 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
                                    u32 mask);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-                                      u32 type, u32 mask);
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb);
+int crypto_check_attr_type(struct rtattr **tb, u32 type);
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask);
 struct crypto_instance *crypto_alloc_instance(const char *name,
                                              struct crypto_alg *alg);
 
index d4d05313280c5643a4c0b05e2f388d901bb581f1..67830e7c2c318e2d75d43e3ae587a65719835506 100644 (file)
@@ -372,12 +372,21 @@ struct crypto_hash {
 enum {
        CRYPTOA_UNSPEC,
        CRYPTOA_ALG,
+       CRYPTOA_TYPE,
+       __CRYPTOA_MAX,
 };
 
+#define CRYPTOA_MAX (__CRYPTOA_MAX - 1)
+
 struct crypto_attr_alg {
        char name[CRYPTO_MAX_ALG_NAME];
 };
 
+struct crypto_attr_type {
+       u32 type;
+       u32 mask;
+};
+
 /* 
  * Transform user interface.
  */