Hi:

[CRYPTO] api: Split out low-level API

The crypto API is made up of the part facing users such as IPsec and the
low-level part which is used by cryptographic entities such as algorithms.
This patch splits out the latter so that the two APIs are more clearly
delineated.  As a bonus the low-level API can now be modularised if all
algorithms are built as modules.

Signed-off-by: Herbert Xu <[EMAIL PROTECTED]>

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/crypto/Kconfig b/crypto/Kconfig
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -2,16 +2,21 @@
 # Cryptographic API Configuration
 #
 
-menu "Cryptographic options"
-
 config CRYPTO
        bool "Cryptographic API"
        help
          This option provides the core Cryptographic API.
 
+if CRYPTO
+
+menu "Cryptographic options"
+
+config CRYPTO_LOWAPI
+       tristate
+
 config CRYPTO_MANAGER
        tristate "Cryptographic algorithm manager"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        default m
        help
          Create default cryptographic template instantiations such as
@@ -19,45 +24,46 @@ config CRYPTO_MANAGER
 
 config CRYPTO_HMAC
        tristate "HMAC support"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          HMAC: Keyed-Hashing for Message Authentication (RFC2104).
          This is required for IPSec.
 
 config CRYPTO_NULL
        tristate "Null algorithms"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          These are 'Null' algorithms, used by IPsec, which do nothing.
 
 config CRYPTO_MD4
        tristate "MD4 digest algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          MD4 message digest algorithm (RFC1320).
 
 config CRYPTO_MD5
        tristate "MD5 digest algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          MD5 message digest algorithm (RFC1321).
 
 config CRYPTO_SHA1
        tristate "SHA1 digest algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
 
 config CRYPTO_SHA1_S390
        tristate "SHA1 digest algorithm (s390)"
-       depends on CRYPTO && S390
+       depends on S390
+       select CRYPTO_LOWAPI
        help
          This is the s390 hardware accelerated implementation of the
          SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
 
 config CRYPTO_SHA256
        tristate "SHA256 digest algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          SHA256 secure hash standard (DFIPS 180-2).
          
@@ -66,7 +72,8 @@ config CRYPTO_SHA256
 
 config CRYPTO_SHA256_S390
        tristate "SHA256 digest algorithm (s390)"
-       depends on CRYPTO && S390
+       depends on S390
+       select CRYPTO_LOWAPI
        help
          This is the s390 hardware accelerated implementation of the
          SHA256 secure hash standard (DFIPS 180-2).
@@ -76,7 +83,7 @@ config CRYPTO_SHA256_S390
 
 config CRYPTO_SHA512
        tristate "SHA384 and SHA512 digest algorithms"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          SHA512 secure hash standard (DFIPS 180-2).
          
@@ -88,7 +95,7 @@ config CRYPTO_SHA512
 
 config CRYPTO_WP512
        tristate "Whirlpool digest algorithms"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          Whirlpool hash algorithm 512, 384 and 256-bit hashes
 
@@ -100,7 +107,7 @@ config CRYPTO_WP512
 
 config CRYPTO_TGR192
        tristate "Tiger digest algorithms"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          Tiger hash algorithm 192, 160 and 128-bit hashes
 
@@ -113,19 +120,20 @@ config CRYPTO_TGR192
 
 config CRYPTO_DES
        tristate "DES and Triple DES EDE cipher algorithms"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 
 config CRYPTO_DES_S390
        tristate "DES and Triple DES cipher algorithms (s390)"
-       depends on CRYPTO && S390
+       depends on S390
+       select CRYPTO_LOWAPI
        help
          DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 
 config CRYPTO_BLOWFISH
        tristate "Blowfish cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          Blowfish cipher algorithm, by Bruce Schneier.
          
@@ -138,7 +146,7 @@ config CRYPTO_BLOWFISH
 
 config CRYPTO_TWOFISH
        tristate "Twofish cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        select CRYPTO_TWOFISH_COMMON
        help
          Twofish cipher algorithm.
@@ -153,14 +161,14 @@ config CRYPTO_TWOFISH
 
 config CRYPTO_TWOFISH_COMMON
        tristate
-       depends on CRYPTO
        help
          Common parts of the Twofish cipher algorithm shared by the
          generic c and the assembler implementations.
 
 config CRYPTO_TWOFISH_586
        tristate "Twofish cipher algorithms (i586)"
-       depends on CRYPTO && ((X86 || UML_X86) && !64BIT)
+       depends on (X86 || UML_X86) && !64BIT
+       select CRYPTO_LOWAPI
        select CRYPTO_TWOFISH_COMMON
        help
          Twofish cipher algorithm.
@@ -175,7 +183,8 @@ config CRYPTO_TWOFISH_586
 
 config CRYPTO_TWOFISH_X86_64
        tristate "Twofish cipher algorithm (x86_64)"
-       depends on CRYPTO && ((X86 || UML_X86) && 64BIT)
+       depends on (X86 || UML_X86) && 64BIT
+       select CRYPTO_LOWAPI
        select CRYPTO_TWOFISH_COMMON
        help
          Twofish cipher algorithm (x86_64).
@@ -190,7 +199,7 @@ config CRYPTO_TWOFISH_X86_64
 
 config CRYPTO_SERPENT
        tristate "Serpent cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          Serpent cipher algorithm, by Anderson, Biham & Knudsen.
 
@@ -203,7 +212,7 @@ config CRYPTO_SERPENT
 
 config CRYPTO_AES
        tristate "AES cipher algorithms"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          AES cipher algorithms (FIPS-197). AES uses the Rijndael 
          algorithm.
@@ -223,7 +232,8 @@ config CRYPTO_AES
 
 config CRYPTO_AES_586
        tristate "AES cipher algorithms (i586)"
-       depends on CRYPTO && ((X86 || UML_X86) && !64BIT)
+       depends on (X86 || UML_X86) && !64BIT
+       select CRYPTO_LOWAPI
        help
          AES cipher algorithms (FIPS-197). AES uses the Rijndael 
          algorithm.
@@ -243,7 +253,8 @@ config CRYPTO_AES_586
 
 config CRYPTO_AES_X86_64
        tristate "AES cipher algorithms (x86_64)"
-       depends on CRYPTO && ((X86 || UML_X86) && 64BIT)
+       depends on (X86 || UML_X86) && 64BIT
+       select CRYPTO_LOWAPI
        help
          AES cipher algorithms (FIPS-197). AES uses the Rijndael 
          algorithm.
@@ -263,7 +274,8 @@ config CRYPTO_AES_X86_64
 
 config CRYPTO_AES_S390
        tristate "AES cipher algorithms (s390)"
-       depends on CRYPTO && S390
+       depends on S390
+       select CRYPTO_LOWAPI
        help
          This is the s390 hardware accelerated implementation of the
          AES cipher algorithms (FIPS-197). AES uses the Rijndael
@@ -283,21 +295,21 @@ config CRYPTO_AES_S390
 
 config CRYPTO_CAST5
        tristate "CAST5 (CAST-128) cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          The CAST5 encryption algorithm (synonymous with CAST-128) is
          described in RFC2144.
 
 config CRYPTO_CAST6
        tristate "CAST6 (CAST-256) cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          The CAST6 encryption algorithm (synonymous with CAST-256) is
          described in RFC2612.
 
 config CRYPTO_TEA
        tristate "TEA, XTEA and XETA cipher algorithms"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          TEA cipher algorithm.
 
@@ -314,7 +326,7 @@ config CRYPTO_TEA
 
 config CRYPTO_ARC4
        tristate "ARC4 cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          ARC4 cipher algorithm.
 
@@ -325,7 +337,7 @@ config CRYPTO_ARC4
 
 config CRYPTO_KHAZAD
        tristate "Khazad cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          Khazad cipher algorithm.
 
@@ -338,7 +350,7 @@ config CRYPTO_KHAZAD
 
 config CRYPTO_ANUBIS
        tristate "Anubis cipher algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          Anubis cipher algorithm.
 
@@ -353,7 +365,7 @@ config CRYPTO_ANUBIS
 
 config CRYPTO_DEFLATE
        tristate "Deflate compression algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        select ZLIB_INFLATE
        select ZLIB_DEFLATE
        help
@@ -364,7 +376,7 @@ config CRYPTO_DEFLATE
 
 config CRYPTO_MICHAEL_MIC
        tristate "Michael MIC keyed digest algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        help
          Michael MIC is used for message integrity protection in TKIP
          (IEEE 802.11i). This algorithm is required for TKIP, but it
@@ -373,7 +385,7 @@ config CRYPTO_MICHAEL_MIC
 
 config CRYPTO_CRC32C
        tristate "CRC32c CRC algorithm"
-       depends on CRYPTO
+       select CRYPTO_LOWAPI
        select LIBCRC32C
        help
          Castagnoli, et al Cyclic Redundancy-Check Algorithm.  Used
@@ -383,10 +395,13 @@ config CRYPTO_CRC32C
 
 config CRYPTO_TEST
        tristate "Testing module"
-       depends on CRYPTO && m
+       depends on m
+       select CRYPTO_LOWAPI
        help
          Quick & dirty crypto test module.
 
 source "drivers/crypto/Kconfig"
+
 endmenu
 
+endif  # if CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -2,10 +2,11 @@
 # Cryptographic API
 #
 
-proc-crypto-$(CONFIG_PROC_FS) = proc.o
+obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o
 
-obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \
-                       $(proc-crypto-y)
+crypto_lowapi-$(CONFIG_PROC_FS) += proc.o
+crypto_lowapi-objs := lowapi.o $(crypto_lowapi-y)
+obj-$(CONFIG_CRYPTO_LOWAPI) += crypto_lowapi.o
 
 obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
diff --git a/crypto/api.c b/crypto/api.c
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -15,30 +15,23 @@
  *
  */
 
-#include <linux/compiler.h>
-#include <linux/init.h>
-#include <linux/crypto.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/kmod.h>
 #include <linux/module.h>
-#include <linux/notifier.h>
 #include <linux/param.h>
-#include <linux/rwsem.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include "internal.h"
 
 LIST_HEAD(crypto_alg_list);
-static LIST_HEAD(crypto_template_list);
+EXPORT_SYMBOL_GPL(crypto_alg_list);
 DECLARE_RWSEM(crypto_alg_sem);
+EXPORT_SYMBOL_GPL(crypto_alg_sem);
 
-static BLOCKING_NOTIFIER_HEAD(crypto_chain);
-
-static void crypto_destroy_instance(struct crypto_alg *alg);
-static void crypto_remove_final(struct list_head *list);
+BLOCKING_NOTIFIER_HEAD(crypto_chain);
+EXPORT_SYMBOL_GPL(crypto_chain);
 
 static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg)
 {
@@ -46,16 +39,11 @@ static inline struct crypto_alg *crypto_
        return alg;
 }
 
-static inline void crypto_alg_put(struct crypto_alg *alg)
-{
-       if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
-               alg->cra_destroy(alg);
-}
-
-static struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
+struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
 {
        return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL;
 }
+EXPORT_SYMBOL_GPL(crypto_mod_get);
 
 void crypto_mod_put(struct crypto_alg *alg)
 {
@@ -64,28 +52,7 @@ void crypto_mod_put(struct crypto_alg *a
 }
 EXPORT_SYMBOL_GPL(crypto_mod_put);
 
-static inline int crypto_is_larval(struct crypto_alg *alg)
-{
-       return alg->cra_flags & CRYPTO_ALG_LARVAL;
-}
-
-static inline int crypto_is_dead(struct crypto_alg *alg)
-{
-       return alg->cra_flags & CRYPTO_ALG_DEAD;
-}
-
-static inline int crypto_is_moribund(struct crypto_alg *alg)
-{
-       return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING);
-}
-
-static inline int crypto_notify(unsigned long val, void *v)
-{
-       return blocking_notifier_call_chain(&crypto_chain, val, v);
-}
-
-static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
-                                             u32 mask)
+struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask)
 {
        struct crypto_alg *q, *alg = NULL;
        int best = -2;
@@ -122,6 +89,7 @@ static struct crypto_alg *__crypto_alg_l
 
        return alg;
 }
+EXPORT_SYMBOL_GPL(__crypto_alg_lookup);
 
 static void crypto_larval_destroy(struct crypto_alg *alg)
 {
@@ -193,24 +161,6 @@ static struct crypto_alg *crypto_larval_
        return alg;
 }
 
-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, type, mask);
-       up_read(&crypto_alg_sem);
-
-       if (alg) {
-               if (crypto_is_larval(alg)) {
-                       struct crypto_larval *larval = (void *)alg;
-                       complete(&larval->completion);
-               }
-               crypto_mod_put(alg);
-       }
-}
-EXPORT_SYMBOL_GPL(crypto_larval_error);
-
 static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
                                            u32 mask)
 {
@@ -349,14 +299,15 @@ static unsigned int crypto_ctxsize(struc
        return len + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
 }
 
-static void crypto_shoot_alg(struct crypto_alg *alg)
+void crypto_shoot_alg(struct crypto_alg *alg)
 {
        down_write(&crypto_alg_sem);
        alg->cra_flags |= CRYPTO_ALG_DYING;
        up_write(&crypto_alg_sem);
 }
+EXPORT_SYMBOL_GPL(crypto_shoot_alg);
 
-static struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
+struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
 {
        struct crypto_tfm *tfm = NULL;
        unsigned int tfm_size;
@@ -393,6 +344,7 @@ out_free_tfm:
 out:
        return tfm;
 }
+EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
 
 struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
 {
@@ -438,366 +390,6 @@ void crypto_free_tfm(struct crypto_tfm *
        kfree(tfm);
 }
 
-static inline int crypto_set_driver_name(struct crypto_alg *alg)
-{
-       static const char suffix[] = "-generic";
-       char *driver_name = alg->cra_driver_name;
-       int len;
-
-       if (*driver_name)
-               return 0;
-
-       len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
-       if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
-               return -ENAMETOOLONG;
-
-       memcpy(driver_name + len, suffix, sizeof(suffix));
-       return 0;
-}
-
-static int crypto_check_alg(struct crypto_alg *alg)
-{
-       if (alg->cra_alignmask & (alg->cra_alignmask + 1))
-               return -EINVAL;
-
-       if (alg->cra_alignmask & alg->cra_blocksize)
-               return -EINVAL;
-
-       if (alg->cra_blocksize > PAGE_SIZE / 8)
-               return -EINVAL;
-
-       if (alg->cra_priority < 0)
-               return -EINVAL;
-       
-       return crypto_set_driver_name(alg);
-}
-
-static void crypto_remove_spawns(struct list_head *spawns,
-                                struct list_head *list)
-{
-       struct crypto_spawn *spawn, *n;
-
-       list_for_each_entry_safe(spawn, n, spawns, list) {
-               struct crypto_instance *inst = spawn->inst;
-               struct crypto_template *tmpl = inst->tmpl;
-
-               list_del_init(&spawn->list);
-               spawn->alg = NULL;
-
-               if (crypto_is_dead(&inst->alg))
-                       continue;
-
-               inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
-               if (!tmpl || !crypto_tmpl_get(tmpl))
-                       continue;
-
-               crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
-               list_move(&inst->alg.cra_list, list);
-               hlist_del(&inst->list);
-               inst->alg.cra_destroy = crypto_destroy_instance;
-
-               if (!list_empty(&inst->alg.cra_users)) {
-                       if (&n->list == spawns)
-                               n = list_entry(inst->alg.cra_users.next,
-                                              typeof(*n), list);
-                       __list_splice(&inst->alg.cra_users, spawns->prev);
-               }
-       }
-}
-
-static int __crypto_register_alg(struct crypto_alg *alg,
-                                struct list_head *list)
-{
-       struct crypto_alg *q;
-       int ret = -EAGAIN;
-
-       if (crypto_is_dead(alg))
-               goto out;
-
-       INIT_LIST_HEAD(&alg->cra_users);
-
-       ret = -EEXIST;
-       atomic_set(&alg->cra_refcnt, 1);
-       list_for_each_entry(q, &crypto_alg_list, cra_list) {
-               if (q == alg)
-                       goto out;
-
-               if (crypto_is_moribund(q))
-                       continue;
-
-               if (crypto_is_larval(q)) {
-                       struct crypto_larval *larval = (void *)q;
-
-                       if (strcmp(alg->cra_name, q->cra_name) &&
-                           strcmp(alg->cra_driver_name, q->cra_name))
-                               continue;
-
-                       if (larval->adult)
-                               continue;
-                       if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
-                               continue;
-                       if (!crypto_mod_get(alg))
-                               continue;
-
-                       larval->adult = alg;
-                       complete(&larval->completion);
-                       continue;
-               }
-
-               if (strcmp(alg->cra_name, q->cra_name))
-                       continue;
-
-               if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
-                   q->cra_priority > alg->cra_priority)
-                       continue;
-
-               crypto_remove_spawns(&q->cra_users, list);
-       }
-       
-       list_add(&alg->cra_list, &crypto_alg_list);
-
-       crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg);
-       ret = 0;
-
-out:   
-       return ret;
-}
-
-int crypto_register_alg(struct crypto_alg *alg)
-{
-       LIST_HEAD(list);
-       int err;
-
-       err = crypto_check_alg(alg);
-       if (err)
-               return err;
-
-       down_write(&crypto_alg_sem);
-       err = __crypto_register_alg(alg, &list);
-       up_write(&crypto_alg_sem);
-
-       crypto_remove_final(&list);
-       return err;
-}
-
-static void crypto_destroy_instance(struct crypto_alg *alg)
-{
-       struct crypto_instance *inst = (void *)alg;
-       struct crypto_template *tmpl = inst->tmpl;
-
-       tmpl->free(inst);
-       crypto_tmpl_put(tmpl);
-}
-
-static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
-{
-       if (unlikely(list_empty(&alg->cra_list)))
-               return -ENOENT;
-
-       alg->cra_flags |= CRYPTO_ALG_DEAD;
-
-       crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
-       list_del_init(&alg->cra_list);
-       crypto_remove_spawns(&alg->cra_users, list);
-
-       return 0;
-}
-
-static void crypto_remove_final(struct list_head *list)
-{
-       struct crypto_alg *alg;
-       struct crypto_alg *n;
-
-       list_for_each_entry_safe(alg, n, list, cra_list) {
-               list_del_init(&alg->cra_list);
-               crypto_alg_put(alg);
-       }
-}
-
-int crypto_unregister_alg(struct crypto_alg *alg)
-{
-       int ret;
-       LIST_HEAD(list);
-       
-       down_write(&crypto_alg_sem);
-       ret = crypto_remove_alg(alg, &list);
-       up_write(&crypto_alg_sem);
-
-       if (ret)
-               return ret;
-
-       BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
-       if (alg->cra_destroy)
-               alg->cra_destroy(alg);
-
-       crypto_remove_final(&list);
-       return 0;
-}
-
-int crypto_register_template(struct crypto_template *tmpl)
-{
-       struct crypto_template *q;
-       int err = -EEXIST;
-
-       down_write(&crypto_alg_sem);
-
-       list_for_each_entry(q, &crypto_template_list, list) {
-               if (q == tmpl)
-                       goto out;
-       }
-
-       list_add(&tmpl->list, &crypto_template_list);
-       crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl);
-       err = 0;
-out:
-       up_write(&crypto_alg_sem);
-       return err;
-}
-EXPORT_SYMBOL_GPL(crypto_register_template);
-
-void crypto_unregister_template(struct crypto_template *tmpl)
-{
-       struct crypto_instance *inst;
-       struct hlist_node *p, *n;
-       struct hlist_head *list;
-       LIST_HEAD(users);
-
-       down_write(&crypto_alg_sem);
-
-       BUG_ON(list_empty(&tmpl->list));
-       list_del_init(&tmpl->list);
-
-       list = &tmpl->instances;
-       hlist_for_each_entry(inst, p, list, list) {
-               int err = crypto_remove_alg(&inst->alg, &users);
-               BUG_ON(err);
-       }
-
-       crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl);
-
-       up_write(&crypto_alg_sem);
-
-       hlist_for_each_entry_safe(inst, p, n, list, list) {
-               BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1);
-               tmpl->free(inst);
-       }
-       crypto_remove_final(&users);
-}
-EXPORT_SYMBOL_GPL(crypto_unregister_template);
-
-static struct crypto_template *__crypto_lookup_template(const char *name)
-{
-       struct crypto_template *q, *tmpl = NULL;
-
-       down_read(&crypto_alg_sem);
-       list_for_each_entry(q, &crypto_template_list, list) {
-               if (strcmp(q->name, name))
-                       continue;
-               if (unlikely(!crypto_tmpl_get(q)))
-                       continue;
-
-               tmpl = q;
-               break;
-       }
-       up_read(&crypto_alg_sem);
-
-       return tmpl;
-}
-
-struct crypto_template *crypto_lookup_template(const char *name)
-{
-       return try_then_request_module(__crypto_lookup_template(name), name);
-}
-EXPORT_SYMBOL_GPL(crypto_lookup_template);
-
-int crypto_register_instance(struct crypto_template *tmpl,
-                            struct crypto_instance *inst)
-{
-       LIST_HEAD(list);
-       int err = -EINVAL;
-
-       if (inst->alg.cra_destroy)
-               goto err;
-
-       err = crypto_check_alg(&inst->alg);
-       if (err)
-               goto err;
-
-       inst->alg.cra_module = tmpl->module;
-
-       down_write(&crypto_alg_sem);
-
-       err = __crypto_register_alg(&inst->alg, &list);
-       if (err)
-               goto unlock;
-
-       hlist_add_head(&inst->list, &tmpl->instances);
-       inst->tmpl = tmpl;
-
-unlock:
-       up_write(&crypto_alg_sem);
-
-       crypto_remove_final(&list);
-
-err:
-       return err;
-}
-EXPORT_SYMBOL_GPL(crypto_register_instance);
-
-int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
-                     struct crypto_instance *inst)
-{
-       int err = -EAGAIN;
-
-       spawn->inst = inst;
-
-       down_write(&crypto_alg_sem);
-       if (!crypto_is_moribund(alg)) {
-               list_add(&spawn->list, &alg->cra_users);
-               spawn->alg = alg;
-               err = 0;
-       }
-       up_write(&crypto_alg_sem);
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(crypto_init_spawn);
-
-void crypto_drop_spawn(struct crypto_spawn *spawn)
-{
-       down_write(&crypto_alg_sem);
-       list_del(&spawn->list);
-       up_write(&crypto_alg_sem);
-}
-EXPORT_SYMBOL_GPL(crypto_drop_spawn);
-
-struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
-{
-       struct crypto_alg *alg;
-       struct crypto_alg *alg2;
-       struct crypto_tfm *tfm;
-
-       down_read(&crypto_alg_sem);
-       alg = spawn->alg;
-       alg2 = alg;
-       if (alg2)
-               alg2 = crypto_mod_get(alg2);
-       up_read(&crypto_alg_sem);
-
-       if (!alg2) {
-               if (alg)
-                       crypto_shoot_alg(alg);
-               return ERR_PTR(-EAGAIN);
-       }
-
-       tfm = __crypto_alloc_tfm(alg, 0);
-       if (IS_ERR(tfm))
-               crypto_mod_put(alg);
-
-       return tfm;
-}
-EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
-
 int crypto_alg_available(const char *name, u32 flags)
 {
        int ret = 0;
@@ -811,29 +403,6 @@ int crypto_alg_available(const char *nam
        return ret;
 }
 
-int crypto_register_notifier(struct notifier_block *nb)
-{
-       return blocking_notifier_chain_register(&crypto_chain, nb);
-}
-EXPORT_SYMBOL_GPL(crypto_register_notifier);
-
-int crypto_unregister_notifier(struct notifier_block *nb)
-{
-       return blocking_notifier_chain_unregister(&crypto_chain, nb);
-}
-EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
-
-static int __init init_crypto(void)
-{
-       printk(KERN_INFO "Initializing Cryptographic API\n");
-       crypto_init_proc();
-       return 0;
-}
-
-__initcall(init_crypto);
-
-EXPORT_SYMBOL_GPL(crypto_register_alg);
-EXPORT_SYMBOL_GPL(crypto_unregister_alg);
 EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
 EXPORT_SYMBOL_GPL(crypto_alg_available);
diff --git a/crypto/hmac.c b/crypto/hmac.c
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -15,14 +15,13 @@
  * any later version.
  *
  */
-#include <linux/crypto.h>
+#include <crypto/lowapi.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
 #include <linux/scatterlist.h>
-#include "internal.h"
 
 struct crypto_hmac_ctx {
        struct crypto_tfm *child;
diff --git a/crypto/internal.h b/crypto/internal.h
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -13,8 +13,8 @@
 #ifndef _CRYPTO_INTERNAL_H
 #define _CRYPTO_INTERNAL_H
 
+#include <crypto/lowapi.h>
 #include <linux/completion.h>
-#include <linux/crypto.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/interrupt.h>
@@ -22,9 +22,9 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/notifier.h>
 #include <linux/rwsem.h>
 #include <linux/slab.h>
-#include <linux/types.h>
 #include <asm/kmap_types.h>
 
 /* Crypto notification events. */
@@ -36,27 +36,8 @@ enum {
        CRYPTO_MSG_TMPL_UNREGISTER,
 };
 
-struct notifier_block;
-
-struct crypto_instance {
-       struct crypto_alg alg;
-
-       struct crypto_template *tmpl;
-       struct hlist_node list;
-
-       char __ctx[] __attribute__ ((__aligned__));
-};
-
-struct crypto_template {
-       struct list_head list;
-       struct hlist_head instances;
-       struct module *module;
-
-       struct crypto_instance *(*alloc)(void *param, unsigned int len);
-       void (*free)(struct crypto_instance *inst);
-
-       char name[CRYPTO_MAX_ALG_NAME];
-};
+struct crypto_instance;
+struct crypto_template;
 
 struct crypto_larval {
        struct crypto_alg alg;
@@ -65,14 +46,9 @@ struct crypto_larval {
        u32 mask;
 };
 
-struct crypto_spawn {
-       struct list_head list;
-       struct crypto_alg *alg;
-       struct crypto_instance *inst;
-};
-
 extern struct list_head crypto_alg_list;
 extern struct rw_semaphore crypto_alg_sem;
+extern struct blocking_notifier_head crypto_chain;
 
 extern enum km_type crypto_km_types[];
 
@@ -99,9 +75,12 @@ static inline void crypto_yield(struct c
 
 #ifdef CONFIG_PROC_FS
 void __init crypto_init_proc(void);
+void __exit crypto_exit_proc(void);
 #else
 static inline void crypto_init_proc(void)
 { }
+static inline void crypto_exit_proc(void)
+{ }
 #endif
 
 static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
@@ -138,6 +117,9 @@ static inline unsigned int crypto_compre
        return alg->cra_ctxsize;
 }
 
+struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
+struct crypto_alg *__crypto_alg_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);
 int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
@@ -150,27 +132,21 @@ void crypto_exit_digest_ops(struct crypt
 void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
 void crypto_exit_compress_ops(struct crypto_tfm *tfm);
 
-void crypto_mod_put(struct crypto_alg *alg);
 void crypto_larval_error(const char *name, u32 type, u32 mask);
-struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
 
-int crypto_register_template(struct crypto_template *tmpl);
-void crypto_unregister_template(struct crypto_template *tmpl);
-struct crypto_template *crypto_lookup_template(const char *name);
+void crypto_shoot_alg(struct crypto_alg *alg);
+struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags);
+
 int crypto_register_instance(struct crypto_template *tmpl,
                             struct crypto_instance *inst);
 
 int crypto_register_notifier(struct notifier_block *nb);
 int crypto_unregister_notifier(struct notifier_block *nb);
 
-int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
-                     struct crypto_instance *inst);
-void crypto_drop_spawn(struct crypto_spawn *spawn);
-struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn);
-
-static inline void *crypto_instance_ctx(struct crypto_instance *inst)
+static inline void crypto_alg_put(struct crypto_alg *alg)
 {
-       return inst->__ctx;
+       if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
+               alg->cra_destroy(alg);
 }
 
 static inline int crypto_tmpl_get(struct crypto_template *tmpl)
@@ -183,5 +159,25 @@ static inline void crypto_tmpl_put(struc
        module_put(tmpl->module);
 }
 
+static inline int crypto_is_larval(struct crypto_alg *alg)
+{
+       return alg->cra_flags & CRYPTO_ALG_LARVAL;
+}
+
+static inline int crypto_is_dead(struct crypto_alg *alg)
+{
+       return alg->cra_flags & CRYPTO_ALG_DEAD;
+}
+
+static inline int crypto_is_moribund(struct crypto_alg *alg)
+{
+       return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING);
+}
+
+static inline int crypto_notify(unsigned long val, void *v)
+{
+       return blocking_notifier_call_chain(&crypto_chain, val, v);
+}
+
 #endif /* _CRYPTO_INTERNAL_H */
 
diff --git a/crypto/lowapi.c b/crypto/lowapi.c
new file mode 100644
--- /dev/null
+++ b/crypto/lowapi.c
@@ -0,0 +1,433 @@
+/*
+ * Cryptographic API for algorithms (i.e., low-level API).
+ *
+ * Copyright (c) 2006 Herbert Xu <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "internal.h"
+
+static LIST_HEAD(crypto_template_list);
+
+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, type, mask);
+       up_read(&crypto_alg_sem);
+
+       if (alg) {
+               if (crypto_is_larval(alg)) {
+                       struct crypto_larval *larval = (void *)alg;
+                       complete(&larval->completion);
+               }
+               crypto_mod_put(alg);
+       }
+}
+EXPORT_SYMBOL_GPL(crypto_larval_error);
+
+static inline int crypto_set_driver_name(struct crypto_alg *alg)
+{
+       static const char suffix[] = "-generic";
+       char *driver_name = alg->cra_driver_name;
+       int len;
+
+       if (*driver_name)
+               return 0;
+
+       len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+       if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
+               return -ENAMETOOLONG;
+
+       memcpy(driver_name + len, suffix, sizeof(suffix));
+       return 0;
+}
+
+static int crypto_check_alg(struct crypto_alg *alg)
+{
+       if (alg->cra_alignmask & (alg->cra_alignmask + 1))
+               return -EINVAL;
+
+       if (alg->cra_alignmask & alg->cra_blocksize)
+               return -EINVAL;
+
+       if (alg->cra_blocksize > PAGE_SIZE / 8)
+               return -EINVAL;
+
+       if (alg->cra_priority < 0)
+               return -EINVAL;
+       
+       return crypto_set_driver_name(alg);
+}
+
+static void crypto_destroy_instance(struct crypto_alg *alg)
+{
+       struct crypto_instance *inst = (void *)alg;
+       struct crypto_template *tmpl = inst->tmpl;
+
+       tmpl->free(inst);
+       crypto_tmpl_put(tmpl);
+}
+
+static void crypto_remove_spawns(struct list_head *spawns,
+                                struct list_head *list)
+{
+       struct crypto_spawn *spawn, *n;
+
+       list_for_each_entry_safe(spawn, n, spawns, list) {
+               struct crypto_instance *inst = spawn->inst;
+               struct crypto_template *tmpl = inst->tmpl;
+
+               list_del_init(&spawn->list);
+               spawn->alg = NULL;
+
+               if (crypto_is_dead(&inst->alg))
+                       continue;
+
+               inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
+               if (!tmpl || !crypto_tmpl_get(tmpl))
+                       continue;
+
+               crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
+               list_move(&inst->alg.cra_list, list);
+               hlist_del(&inst->list);
+               inst->alg.cra_destroy = crypto_destroy_instance;
+
+               if (!list_empty(&inst->alg.cra_users)) {
+                       if (&n->list == spawns)
+                               n = list_entry(inst->alg.cra_users.next,
+                                              typeof(*n), list);
+                       __list_splice(&inst->alg.cra_users, spawns->prev);
+               }
+       }
+}
+
+static int __crypto_register_alg(struct crypto_alg *alg,
+                                struct list_head *list)
+{
+       struct crypto_alg *q;
+       int ret = -EAGAIN;
+
+       if (crypto_is_dead(alg))
+               goto out;
+
+       INIT_LIST_HEAD(&alg->cra_users);
+
+       ret = -EEXIST;
+       atomic_set(&alg->cra_refcnt, 1);
+       list_for_each_entry(q, &crypto_alg_list, cra_list) {
+               if (q == alg)
+                       goto out;
+
+               if (crypto_is_moribund(q))
+                       continue;
+
+               if (crypto_is_larval(q)) {
+                       struct crypto_larval *larval = (void *)q;
+
+                       if (strcmp(alg->cra_name, q->cra_name) &&
+                           strcmp(alg->cra_driver_name, q->cra_name))
+                               continue;
+
+                       if (larval->adult)
+                               continue;
+                       if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
+                               continue;
+                       if (!crypto_mod_get(alg))
+                               continue;
+
+                       larval->adult = alg;
+                       complete(&larval->completion);
+                       continue;
+               }
+
+               if (strcmp(alg->cra_name, q->cra_name))
+                       continue;
+
+               if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
+                   q->cra_priority > alg->cra_priority)
+                       continue;
+
+               crypto_remove_spawns(&q->cra_users, list);
+       }
+       
+       list_add(&alg->cra_list, &crypto_alg_list);
+
+       crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg);
+       ret = 0;
+
+out:   
+       return ret;
+}
+
+static void crypto_remove_final(struct list_head *list)
+{
+       struct crypto_alg *alg;
+       struct crypto_alg *n;
+
+       list_for_each_entry_safe(alg, n, list, cra_list) {
+               list_del_init(&alg->cra_list);
+               crypto_alg_put(alg);
+       }
+}
+
+int crypto_register_alg(struct crypto_alg *alg)
+{
+       LIST_HEAD(list);
+       int err;
+
+       err = crypto_check_alg(alg);
+       if (err)
+               return err;
+
+       down_write(&crypto_alg_sem);
+       err = __crypto_register_alg(alg, &list);
+       up_write(&crypto_alg_sem);
+
+       crypto_remove_final(&list);
+       return err;
+}
+EXPORT_SYMBOL_GPL(crypto_register_alg);
+
+static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
+{
+       if (unlikely(list_empty(&alg->cra_list)))
+               return -ENOENT;
+
+       alg->cra_flags |= CRYPTO_ALG_DEAD;
+
+       crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
+       list_del_init(&alg->cra_list);
+       crypto_remove_spawns(&alg->cra_users, list);
+
+       return 0;
+}
+
+int crypto_unregister_alg(struct crypto_alg *alg)
+{
+       int ret;
+       LIST_HEAD(list);
+       
+       down_write(&crypto_alg_sem);
+       ret = crypto_remove_alg(alg, &list);
+       up_write(&crypto_alg_sem);
+
+       if (ret)
+               return ret;
+
+       BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
+       if (alg->cra_destroy)
+               alg->cra_destroy(alg);
+
+       crypto_remove_final(&list);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_alg);
+
+int crypto_register_template(struct crypto_template *tmpl)
+{
+       struct crypto_template *q;
+       int err = -EEXIST;
+
+       down_write(&crypto_alg_sem);
+
+       list_for_each_entry(q, &crypto_template_list, list) {
+               if (q == tmpl)
+                       goto out;
+       }
+
+       list_add(&tmpl->list, &crypto_template_list);
+       crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl);
+       err = 0;
+out:
+       up_write(&crypto_alg_sem);
+       return err;
+}
+EXPORT_SYMBOL_GPL(crypto_register_template);
+
+void crypto_unregister_template(struct crypto_template *tmpl)
+{
+       struct crypto_instance *inst;
+       struct hlist_node *p, *n;
+       struct hlist_head *list;
+       LIST_HEAD(users);
+
+       down_write(&crypto_alg_sem);
+
+       BUG_ON(list_empty(&tmpl->list));
+       list_del_init(&tmpl->list);
+
+       list = &tmpl->instances;
+       hlist_for_each_entry(inst, p, list, list) {
+               int err = crypto_remove_alg(&inst->alg, &users);
+               BUG_ON(err);
+       }
+
+       crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl);
+
+       up_write(&crypto_alg_sem);
+
+       hlist_for_each_entry_safe(inst, p, n, list, list) {
+               BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1);
+               tmpl->free(inst);
+       }
+       crypto_remove_final(&users);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_template);
+
+static struct crypto_template *__crypto_lookup_template(const char *name)
+{
+       struct crypto_template *q, *tmpl = NULL;
+
+       down_read(&crypto_alg_sem);
+       list_for_each_entry(q, &crypto_template_list, list) {
+               if (strcmp(q->name, name))
+                       continue;
+               if (unlikely(!crypto_tmpl_get(q)))
+                       continue;
+
+               tmpl = q;
+               break;
+       }
+       up_read(&crypto_alg_sem);
+
+       return tmpl;
+}
+
+struct crypto_template *crypto_lookup_template(const char *name)
+{
+       return try_then_request_module(__crypto_lookup_template(name), name);
+}
+EXPORT_SYMBOL_GPL(crypto_lookup_template);
+
+int crypto_register_instance(struct crypto_template *tmpl,
+                            struct crypto_instance *inst)
+{
+       LIST_HEAD(list);
+       int err = -EINVAL;
+
+       if (inst->alg.cra_destroy)
+               goto err;
+
+       err = crypto_check_alg(&inst->alg);
+       if (err)
+               goto err;
+
+       inst->alg.cra_module = tmpl->module;
+
+       down_write(&crypto_alg_sem);
+
+       err = __crypto_register_alg(&inst->alg, &list);
+       if (err)
+               goto unlock;
+
+       hlist_add_head(&inst->list, &tmpl->instances);
+       inst->tmpl = tmpl;
+
+unlock:
+       up_write(&crypto_alg_sem);
+
+       crypto_remove_final(&list);
+
+err:
+       return err;
+}
+EXPORT_SYMBOL_GPL(crypto_register_instance);
+
+int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
+                     struct crypto_instance *inst)
+{
+       int err = -EAGAIN;
+
+       spawn->inst = inst;
+
+       down_write(&crypto_alg_sem);
+       if (!crypto_is_moribund(alg)) {
+               list_add(&spawn->list, &alg->cra_users);
+               spawn->alg = alg;
+               err = 0;
+       }
+       up_write(&crypto_alg_sem);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(crypto_init_spawn);
+
+void crypto_drop_spawn(struct crypto_spawn *spawn)
+{
+       down_write(&crypto_alg_sem);
+       list_del(&spawn->list);
+       up_write(&crypto_alg_sem);
+}
+EXPORT_SYMBOL_GPL(crypto_drop_spawn);
+
+struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
+{
+       struct crypto_alg *alg;
+       struct crypto_alg *alg2;
+       struct crypto_tfm *tfm;
+
+       down_read(&crypto_alg_sem);
+       alg = spawn->alg;
+       alg2 = alg;
+       if (alg2)
+               alg2 = crypto_mod_get(alg2);
+       up_read(&crypto_alg_sem);
+
+       if (!alg2) {
+               if (alg)
+                       crypto_shoot_alg(alg);
+               return ERR_PTR(-EAGAIN);
+       }
+
+       tfm = __crypto_alloc_tfm(alg, 0);
+       if (IS_ERR(tfm))
+               crypto_mod_put(alg);
+
+       return tfm;
+}
+EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
+
+int crypto_register_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&crypto_chain, nb);
+}
+EXPORT_SYMBOL_GPL(crypto_register_notifier);
+
+int crypto_unregister_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&crypto_chain, nb);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
+
+static int __init crypto_lowapi_init(void)
+{
+       printk(KERN_INFO "Initializing Cryptographic API\n");
+       crypto_init_proc();
+       return 0;
+}
+
+static void __exit crypto_lowapi_exit(void)
+{
+       crypto_exit_proc();
+}
+
+module_init(crypto_lowapi_init);
+module_exit(crypto_lowapi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Low-level Cryptographic API");
diff --git a/crypto/proc.c b/crypto/proc.c
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -113,3 +113,8 @@ void __init crypto_init_proc(void)
        if (proc)
                proc->proc_fops = &proc_crypto_ops;
 }
+
+void __exit crypto_exit_proc(void)
+{
+       remove_proc_entry("crypto", NULL);
+}
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -2,7 +2,7 @@ menu "Hardware crypto devices"
 
 config CRYPTO_DEV_PADLOCK
        tristate "Support for VIA PadLock ACE"
-       depends on CRYPTO && X86_32
+       depends on X86_32
        default m
        help
          Some VIA processors come with an integrated crypto engine
@@ -26,6 +26,7 @@ config CRYPTO_DEV_PADLOCK
 config CRYPTO_DEV_PADLOCK_AES
        tristate "PadLock driver for AES algorithm"
        depends on CRYPTO_DEV_PADLOCK
+       select CRYPTO_LOWAPI
        default m
        help
          Use VIA PadLock for AES algorithm.
@@ -38,6 +39,7 @@ config CRYPTO_DEV_PADLOCK_AES
 config CRYPTO_DEV_PADLOCK_SHA
        tristate "PadLock driver for SHA1 and SHA256 algorithms"
        depends on CRYPTO_DEV_PADLOCK
+       select CRYPTO_LOWAPI
        select CRYPTO_SHA1
        select CRYPTO_SHA256
        default m
diff --git a/include/crypto/lowapi.h b/include/crypto/lowapi.h
new file mode 100644
--- /dev/null
+++ b/include/crypto/lowapi.h
@@ -0,0 +1,65 @@
+/*
+ * Cryptographic API for algorithms (i.e., low-level API).
+ *
+ * Copyright (c) 2006 Herbert Xu <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_LOWAPI_H
+#define _CRYPTO_LOWAPI_H
+
+#include <linux/crypto.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+
+struct module;
+
+struct crypto_instance {
+       struct crypto_alg alg;
+
+       struct crypto_template *tmpl;
+       struct hlist_node list;
+
+       char __ctx[] __attribute__ ((__aligned__));
+};
+
+struct crypto_template {
+       struct list_head list;
+       struct hlist_head instances;
+       struct module *module;
+
+       struct crypto_instance *(*alloc)(void *param, unsigned int len);
+       void (*free)(struct crypto_instance *inst);
+
+       char name[CRYPTO_MAX_ALG_NAME];
+};
+
+struct crypto_spawn {
+       struct list_head list;
+       struct crypto_alg *alg;
+       struct crypto_instance *inst;
+};
+
+void crypto_mod_put(struct crypto_alg *alg);
+struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
+
+int crypto_register_template(struct crypto_template *tmpl);
+void crypto_unregister_template(struct crypto_template *tmpl);
+struct crypto_template *crypto_lookup_template(const char *name);
+
+int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
+                     struct crypto_instance *inst);
+void crypto_drop_spawn(struct crypto_spawn *spawn);
+struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn);
+
+static inline void *crypto_instance_ctx(struct crypto_instance *inst)
+{
+       return inst->__ctx;
+}
+
+#endif /* _CRYPTO_LOWAPI_H */
+
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to