crypto: api - Add new template create function
[safe/jmp/linux-2.6] / crypto / ablkcipher.c
index 3bcb099..03fb5fa 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <crypto/internal/skcipher.h>
+#include <linux/cpumask.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -25,6 +26,8 @@
 
 #include "internal.h"
 
+static const char *skcipher_default_geniv __read_mostly;
+
 static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key,
                            unsigned int keylen)
 {
@@ -180,7 +183,8 @@ EXPORT_SYMBOL_GPL(crypto_givcipher_type);
 
 const char *crypto_default_geniv(const struct crypto_alg *alg)
 {
-       return alg->cra_flags & CRYPTO_ALG_ASYNC ? "eseqiv" : "chainiv";
+       return alg->cra_flags & CRYPTO_ALG_ASYNC ?
+              "eseqiv" : skcipher_default_geniv;
 }
 
 static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
@@ -201,8 +205,9 @@ static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
        int err;
 
        larval = crypto_larval_lookup(alg->cra_driver_name,
+                                     (type & ~CRYPTO_ALG_TYPE_MASK) |
                                      CRYPTO_ALG_TYPE_GIVCIPHER,
-                                     CRYPTO_ALG_TYPE_MASK);
+                                     mask | CRYPTO_ALG_TYPE_MASK);
        err = PTR_ERR(larval);
        if (IS_ERR(larval))
                goto out;
@@ -282,6 +287,25 @@ static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
                                          alg->cra_ablkcipher.ivsize))
                return alg;
 
+       crypto_mod_put(alg);
+       alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED,
+                                   mask & ~CRYPTO_ALG_TESTED);
+       if (IS_ERR(alg))
+               return alg;
+
+       if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+           CRYPTO_ALG_TYPE_GIVCIPHER) {
+               if ((alg->cra_flags ^ type ^ ~mask) & CRYPTO_ALG_TESTED) {
+                       crypto_mod_put(alg);
+                       alg = ERR_PTR(-ENOENT);
+               }
+               return alg;
+       }
+
+       BUG_ON(!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+                CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
+                                            alg->cra_ablkcipher.ivsize));
+
        return ERR_PTR(crypto_givcipher_default(alg, type, mask));
 }
 
@@ -342,5 +366,16 @@ err:
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher);
 
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Asynchronous block chaining cipher type");
+static int __init skcipher_module_init(void)
+{
+       skcipher_default_geniv = num_possible_cpus() > 1 ?
+                                "eseqiv" : "chainiv";
+       return 0;
+}
+
+static void skcipher_module_exit(void)
+{
+}
+
+module_init(skcipher_module_init);
+module_exit(skcipher_module_exit);