aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorJames Morris <jmorris@intercode.com.au>2002-10-24 17:48:28 -0700
committerJames Morris <jmorris@intercode.com.au>2002-10-24 17:48:28 -0700
commit6c1e4919ac56f4c9ae9ed470475e6139f58a4804 (patch)
tree60a70ae9d774a9752ce0b1debb418987abb0fadd /crypto
parentcd74bb134f87eb043425494861bec1afe98015e8 (diff)
downloadhistory-6c1e4919ac56f4c9ae9ed470475e6139f58a4804.tar.gz
[CRYPTO]: Use kmod to try to autoload modules.
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/api.c152
-rw-r--r--crypto/autoload.c44
-rw-r--r--crypto/internal.h4
4 files changed, 127 insertions, 74 deletions
diff --git a/crypto/Makefile b/crypto/Makefile
index 6c7f7fb6590e4d..262cff47dd3977 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -5,6 +5,7 @@
export-objs := api.o
obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o
+obj-$(CONFIG_KMOD) += autoload.o
obj-$(CONFIG_CRYPTO_MD5) += md5.o
obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
diff --git a/crypto/api.c b/crypto/api.c
index cd245fc2afa511..ed04978a9cd0e0 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -25,76 +25,6 @@
static LIST_HEAD(crypto_alg_list);
static struct rw_semaphore crypto_alg_sem;
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
- struct list_head *v;
- loff_t n = *pos;
-
- down_read(&crypto_alg_sem);
- list_for_each(v, &crypto_alg_list)
- if (!n--)
- return list_entry(v, struct crypto_alg, cra_list);
- return NULL;
-}
-
-static void *c_next(struct seq_file *m, void *p, loff_t *pos)
-{
- struct list_head *v = p;
-
- (*pos)++;
- v = v->next;
- return (v == &crypto_alg_list) ?
- NULL : list_entry(v, struct crypto_alg, cra_list);
-}
-
-static void c_stop(struct seq_file *m, void *p)
-{
- up_read(&crypto_alg_sem);
-}
-
-static int c_show(struct seq_file *m, void *p)
-{
- struct crypto_alg *alg = (struct crypto_alg *)p;
-
- seq_printf(m, "name : %s\n", alg->cra_name);
- seq_printf(m, "id : 0x%08x\n", alg->cra_id);
- seq_printf(m, "blocksize : %Zd\n", alg->cra_blocksize);
-
- switch (alg->cra_id & CRYPTO_TYPE_MASK) {
- case CRYPTO_TYPE_CIPHER:
- seq_printf(m, "keysize : %Zd\n", alg->cra_cipher.cia_keysize);
- seq_printf(m, "ivsize : %Zd\n", alg->cra_cipher.cia_ivsize);
- break;
-
- case CRYPTO_TYPE_DIGEST:
- seq_printf(m, "digestsize : %Zd\n",
- alg->cra_digest.dia_digestsize);
- break;
- }
-
- seq_putc(m, '\n');
- return 0;
-}
-
-static struct seq_operations crypto_seq_ops = {
- .start = c_start,
- .next = c_next,
- .stop = c_stop,
- .show = c_show
-};
-
-static int crypto_info_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &crypto_seq_ops);
-}
-
-struct file_operations proc_crypto_ops = {
- .open = crypto_info_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release
-};
-
static inline int crypto_alg_get(struct crypto_alg *alg)
{
if (alg->cra_module)
@@ -105,7 +35,8 @@ static inline int crypto_alg_get(struct crypto_alg *alg)
static inline void crypto_alg_put(struct crypto_alg *alg)
{
- __MOD_DEC_USE_COUNT(alg->cra_module);
+ if (alg->cra_module)
+ __MOD_DEC_USE_COUNT(alg->cra_module);
}
struct crypto_alg *crypto_alg_lookup(u32 algid)
@@ -149,15 +80,18 @@ static void crypto_init_ops(struct crypto_tfm *tfm)
}
}
-/*
- * Todo: try and load the module if the lookup fails.
- */
struct crypto_tfm *crypto_alloc_tfm(u32 id)
{
struct crypto_tfm *tfm = NULL;
struct crypto_alg *alg;
alg = crypto_alg_lookup(id & CRYPTO_ALG_MASK);
+#ifdef CONFIG_KMOD
+ if (alg == NULL) {
+ crypto_alg_autoload(id & CRYPTO_ALG_MASK);
+ alg = crypto_alg_lookup(id & CRYPTO_ALG_MASK);
+ }
+#endif
if (alg == NULL)
goto out;
@@ -251,6 +185,76 @@ out:
return ret;
}
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ struct list_head *v;
+ loff_t n = *pos;
+
+ down_read(&crypto_alg_sem);
+ list_for_each(v, &crypto_alg_list)
+ if (!n--)
+ return list_entry(v, struct crypto_alg, cra_list);
+ return NULL;
+}
+
+static void *c_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ struct list_head *v = p;
+
+ (*pos)++;
+ v = v->next;
+ return (v == &crypto_alg_list) ?
+ NULL : list_entry(v, struct crypto_alg, cra_list);
+}
+
+static void c_stop(struct seq_file *m, void *p)
+{
+ up_read(&crypto_alg_sem);
+}
+
+static int c_show(struct seq_file *m, void *p)
+{
+ struct crypto_alg *alg = (struct crypto_alg *)p;
+
+ seq_printf(m, "name : %s\n", alg->cra_name);
+ seq_printf(m, "id : 0x%08x\n", alg->cra_id);
+ seq_printf(m, "blocksize : %Zd\n", alg->cra_blocksize);
+
+ switch (alg->cra_id & CRYPTO_TYPE_MASK) {
+ case CRYPTO_TYPE_CIPHER:
+ seq_printf(m, "keysize : %Zd\n", alg->cra_cipher.cia_keysize);
+ seq_printf(m, "ivsize : %Zd\n", alg->cra_cipher.cia_ivsize);
+ break;
+
+ case CRYPTO_TYPE_DIGEST:
+ seq_printf(m, "digestsize : %Zd\n",
+ alg->cra_digest.dia_digestsize);
+ break;
+ }
+
+ seq_putc(m, '\n');
+ return 0;
+}
+
+static struct seq_operations crypto_seq_ops = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = c_show
+};
+
+static int crypto_info_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &crypto_seq_ops);
+}
+
+struct file_operations proc_crypto_ops = {
+ .open = crypto_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
static int __init init_crypto(void)
{
struct proc_dir_entry *proc;
diff --git a/crypto/autoload.c b/crypto/autoload.c
new file mode 100644
index 00000000000000..bc263cd4e22c7e
--- /dev/null
+++ b/crypto/autoload.c
@@ -0,0 +1,44 @@
+/*
+ * Cryptographic API.
+ *
+ * Algorithm autoloader.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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/kernel.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/kmod.h>
+#include <linux/crypto.h>
+#include "internal.h"
+
+static struct {
+ u32 algid;
+ char *name;
+} alg_modmap[] = {
+ { CRYPTO_ALG_DES, "des" },
+ { CRYPTO_ALG_DES3_EDE, "des" },
+ { CRYPTO_ALG_MD5, "md5" },
+ { CRYPTO_ALG_SHA1, "sha1" },
+};
+#define ALG_MAX_MODMAP 4
+
+void crypto_alg_autoload(u32 algid)
+{
+ int i;
+
+ for (i = 0; i < ALG_MAX_MODMAP ; i++) {
+ if ((alg_modmap[i].algid & CRYPTO_ALG_MASK) == algid) {
+ request_module(alg_modmap[i].name);
+ break;
+ }
+ }
+ return;
+}
diff --git a/crypto/internal.h b/crypto/internal.h
index bf717d9186ba09..706b6e6e5c419c 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -46,6 +46,10 @@ static inline void crypto_yield(struct crypto_tfm *tfm)
cond_resched();
}
+#ifdef CONFIG_KMOD
+void crypto_alg_autoload(u32 algid);
+#endif
+
void crypto_init_digest_ops(struct crypto_tfm *tfm);
void crypto_init_cipher_ops(struct crypto_tfm *tfm);
void crypto_init_compress_ops(struct crypto_tfm *tfm);