Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=d29ce988aeb459203c74f14747f4f77e1829ef78
Commit:     d29ce988aeb459203c74f14747f4f77e1829ef78
Parent:     14df4d80433b8413f901e80880c39e8759b8418f
Author:     Herbert Xu <[EMAIL PROTECTED]>
AuthorDate: Wed Dec 12 19:24:27 2007 +0800
Committer:  Herbert Xu <[EMAIL PROTECTED]>
CommitDate: Fri Jan 11 08:16:52 2008 +1100

    [CRYPTO] aead: Create default givcipher instances
    
    This patch makes crypto_alloc_aead always return algorithms that is
    capable of generating their own IVs through givencrypt and givdecrypt.
    All existing AEAD algorithms already do.  New ones must either supply
    their own or specify a generic IV generator with the geniv field.
    
    Signed-off-by: Herbert Xu <[EMAIL PROTECTED]>
---
 crypto/aead.c                  |  153 ++++++++++++++++++++++++++++++++++++++++
 include/crypto/internal/aead.h |    3 +
 include/linux/crypto.h         |   10 +---
 3 files changed, 157 insertions(+), 9 deletions(-)

diff --git a/crypto/aead.c b/crypto/aead.c
index 9f7aca8..f5b1add 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/rtnetlink.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 
@@ -328,5 +329,157 @@ void aead_geniv_exit(struct crypto_tfm *tfm)
 }
 EXPORT_SYMBOL_GPL(aead_geniv_exit);
 
+static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
+{
+       struct rtattr *tb[3];
+       struct {
+               struct rtattr attr;
+               struct crypto_attr_type data;
+       } ptype;
+       struct {
+               struct rtattr attr;
+               struct crypto_attr_alg data;
+       } palg;
+       struct crypto_template *tmpl;
+       struct crypto_instance *inst;
+       struct crypto_alg *larval;
+       const char *geniv;
+       int err;
+
+       larval = crypto_larval_lookup(alg->cra_driver_name,
+                                     CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
+                                     CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+       err = PTR_ERR(larval);
+       if (IS_ERR(larval))
+               goto out;
+
+       err = -EAGAIN;
+       if (!crypto_is_larval(larval))
+               goto drop_larval;
+
+       ptype.attr.rta_len = sizeof(ptype);
+       ptype.attr.rta_type = CRYPTOA_TYPE;
+       ptype.data.type = type | CRYPTO_ALG_GENIV;
+       /* GENIV tells the template that we're making a default geniv. */
+       ptype.data.mask = mask | CRYPTO_ALG_GENIV;
+       tb[0] = &ptype.attr;
+
+       palg.attr.rta_len = sizeof(palg);
+       palg.attr.rta_type = CRYPTOA_ALG;
+       /* Must use the exact name to locate ourselves. */
+       memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
+       tb[1] = &palg.attr;
+
+       tb[2] = NULL;
+
+       geniv = alg->cra_aead.geniv;
+
+       tmpl = crypto_lookup_template(geniv);
+       err = -ENOENT;
+       if (!tmpl)
+               goto kill_larval;
+
+       inst = tmpl->alloc(tb);
+       err = PTR_ERR(inst);
+       if (IS_ERR(inst))
+               goto put_tmpl;
+
+       if ((err = crypto_register_instance(tmpl, inst))) {
+               tmpl->free(inst);
+               goto put_tmpl;
+       }
+
+       /* Redo the lookup to use the instance we just registered. */
+       err = -EAGAIN;
+
+put_tmpl:
+       crypto_tmpl_put(tmpl);
+kill_larval:
+       crypto_larval_kill(larval);
+drop_larval:
+       crypto_mod_put(larval);
+out:
+       crypto_mod_put(alg);
+       return err;
+}
+
+static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
+                                            u32 mask)
+{
+       struct crypto_alg *alg;
+
+       alg = crypto_alg_mod_lookup(name, type, mask);
+       if (IS_ERR(alg))
+               return alg;
+
+       if (alg->cra_type == &crypto_aead_type)
+               return alg;
+
+       if (!alg->cra_aead.ivsize)
+               return alg;
+
+       return ERR_PTR(crypto_nivaead_default(alg, type, mask));
+}
+
+int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
+                    u32 type, u32 mask)
+{
+       struct crypto_alg *alg;
+       int err;
+
+       type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+       type |= CRYPTO_ALG_TYPE_AEAD;
+       mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+       mask |= CRYPTO_ALG_TYPE_MASK;
+
+       alg = crypto_lookup_aead(name, type, mask);
+       if (IS_ERR(alg))
+               return PTR_ERR(alg);
+
+       err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
+       crypto_mod_put(alg);
+       return err;
+}
+EXPORT_SYMBOL_GPL(crypto_grab_aead);
+
+struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
+{
+       struct crypto_tfm *tfm;
+       int err;
+
+       type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+       type |= CRYPTO_ALG_TYPE_AEAD;
+       mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+       mask |= CRYPTO_ALG_TYPE_MASK;
+
+       for (;;) {
+               struct crypto_alg *alg;
+
+               alg = crypto_lookup_aead(alg_name, type, mask);
+               if (IS_ERR(alg)) {
+                       err = PTR_ERR(alg);
+                       goto err;
+               }
+
+               tfm = __crypto_alloc_tfm(alg, type, mask);
+               if (!IS_ERR(tfm))
+                       return __crypto_aead_cast(tfm);
+
+               crypto_mod_put(alg);
+               err = PTR_ERR(tfm);
+
+err:
+               if (err != -EAGAIN)
+                       break;
+               if (signal_pending(current)) {
+                       err = -EINTR;
+                       break;
+               }
+       }
+
+       return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_aead);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h
index eb4eee7..d838c94 100644
--- a/include/crypto/internal/aead.h
+++ b/include/crypto/internal/aead.h
@@ -31,6 +31,9 @@ static inline void crypto_set_aead_spawn(
        crypto_set_spawn(&spawn->base, inst);
 }
 
+int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
+                    u32 type, u32 mask);
+
 static inline void crypto_drop_aead(struct crypto_aead_spawn *spawn)
 {
        crypto_drop_spawn(&spawn->base);
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 639385a..0aba104 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -723,15 +723,7 @@ static inline struct crypto_aead 
*__crypto_aead_cast(struct crypto_tfm *tfm)
        return (struct crypto_aead *)tfm;
 }
 
-static inline struct crypto_aead *crypto_alloc_aead(const char *alg_name,
-                                                   u32 type, u32 mask)
-{
-       type &= ~CRYPTO_ALG_TYPE_MASK;
-       type |= CRYPTO_ALG_TYPE_AEAD;
-       mask |= CRYPTO_ALG_TYPE_MASK;
-
-       return __crypto_aead_cast(crypto_alloc_base(alg_name, type, mask));
-}
+struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 
mask);
 
 static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm)
 {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to