summaryrefslogtreecommitdiff
path: root/linux/crypto/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/crypto/api.c')
-rw-r--r--linux/crypto/api.c227
1 files changed, 52 insertions, 175 deletions
diff --git a/linux/crypto/api.c b/linux/crypto/api.c
index 513a48aa..2d24630e 100644
--- a/linux/crypto/api.c
+++ b/linux/crypto/api.c
@@ -1,12 +1,7 @@
/*
- * Scatterlist Cryptographic API.
+ * Cryptographic API for algorithms (i.e., low-level API).
*
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Copyright (c) 2002 David S. Miller (davem@redhat.com)
- * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
- *
- * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
- * and Nettle, by Niels Möller.
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.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
@@ -19,183 +14,80 @@
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/string.h>
+
+#include <crypto/algapi.h>
#include "internal.h"
-LIST_HEAD(crypto_alg_list);
-DECLARE_RWSEM(crypto_alg_sem);
+static LIST_HEAD(crypto_alg_list);
+static DECLARE_RWSEM(crypto_alg_sem);
-static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
- u32 mask)
+static unsigned crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
{
- struct crypto_alg *q, *alg = NULL;
- int best = -2;
-
- list_for_each_entry(q, &crypto_alg_list, cra_list) {
- int exact, fuzzy;
-
- if ((q->cra_flags ^ type) & mask)
- continue;
-
- exact = !strcmp(q->cra_driver_name, name);
- fuzzy = !strcmp(q->cra_name, name);
- if (!exact && !(fuzzy && q->cra_priority > best))
- continue;
-
- if (unlikely(!crypto_alg_get(q)))
- continue;
-
- best = q->cra_priority;
- if (alg)
- crypto_alg_put(alg);
- alg = q;
-
- if (exact)
- break;
- }
+ return alg->cra_type->ctxsize(alg, type, mask);
+}
- return alg;
+unsigned crypto_alg_extsize(struct crypto_alg *alg)
+{
+ return alg->cra_ctxsize;
}
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
- /*
- * If the internal flag is set for a cipher, require a caller to
- * to invoke the cipher with the internal flag to use that cipher.
- * Also, if a caller wants to allocate a cipher that may or may
- * not be an internal cipher, use type | CRYPTO_ALG_INTERNAL and
- * !(mask & CRYPTO_ALG_INTERNAL).
- */
- if (!((type | mask) & CRYPTO_ALG_INTERNAL))
- mask |= CRYPTO_ALG_INTERNAL;
-
down_read(&crypto_alg_sem);
- alg = __crypto_alg_lookup(name, type, mask);
- up_read(&crypto_alg_sem);
+ list_for_each_entry(alg, &crypto_alg_list, cra_list)
+ if (!((alg->cra_flags ^ type) & mask) &&
+ !strcmp(alg->cra_name, name))
+ goto found;
- return alg ?: ERR_PTR(-ENOENT);
-}
-
-static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
-{
- const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
-
- if (type_obj)
- return type_obj->init(tfm, type, mask);
-
- switch (crypto_tfm_alg_type(tfm)) {
- case CRYPTO_ALG_TYPE_CIPHER:
- return crypto_init_cipher_ops(tfm);
- default:
- break;
- }
+ alg = ERR_PTR(-ENOENT);
+found:
+ up_read(&crypto_alg_sem);
- BUG();
- return -EINVAL;
+ return alg;
}
static void crypto_exit_ops(struct crypto_tfm *tfm)
{
- const struct crypto_type *type = tfm->__crt_alg->cra_type;
-
- if (type) {
- if (tfm->exit)
- tfm->exit(tfm);
- return;
- }
-
- switch (crypto_tfm_alg_type(tfm)) {
- case CRYPTO_ALG_TYPE_CIPHER:
- crypto_exit_cipher_ops(tfm);
- break;
-
- default:
- BUG();
- }
-}
-
-static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
-{
- const struct crypto_type *type_obj = alg->cra_type;
- unsigned int len;
-
- len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
- if (type_obj)
- return len + type_obj->ctxsize(alg, type, mask);
-
- switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
- default:
- BUG();
-
- case CRYPTO_ALG_TYPE_CIPHER:
- len += crypto_cipher_ctxsize(alg);
- break;
- }
-
- return len;
+ if (tfm->exit)
+ tfm->exit(tfm);
}
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
- u32 mask)
+static struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg,
+ u32 type, u32 mask)
{
struct crypto_tfm *tfm = NULL;
- unsigned int tfm_size;
+ unsigned tfm_size;
int err = -ENOMEM;
tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
tfm = kzalloc(tfm_size, GFP_KERNEL);
if (tfm == NULL)
- goto out_err;
+ return ERR_PTR(-ENOMEM);
tfm->__crt_alg = alg;
- err = crypto_init_ops(tfm, type, mask);
+ err = alg->cra_type->init(tfm, type, mask);
if (err)
goto out_free_tfm;
if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
goto cra_init_failed;
- goto out;
+ return tfm;
cra_init_failed:
crypto_exit_ops(tfm);
out_free_tfm:
kfree(tfm);
-out_err:
- tfm = ERR_PTR(err);
-out:
- return tfm;
+ return ERR_PTR(err);
}
-/*
- * crypto_alloc_base - Locate algorithm and allocate transform
- * @alg_name: Name of algorithm
- * @type: Type of algorithm
- * @mask: Mask for type comparison
- *
- * This function should not be used by new algorithm types.
- * Please use crypto_alloc_tfm instead.
- *
- * crypto_alloc_base() will first attempt to locate an already loaded
- * algorithm. If that fails and the kernel supports dynamically loadable
- * modules, it will then attempt to load a module of the same name or
- * alias. If that fails it will send a query to any loaded crypto manager
- * to construct an algorithm on the fly. A refcount is grabbed on the
- * algorithm which is then associated with the new transform.
- *
- * The returned transform is of a non-determinate type. Most people
- * should use one of the more specific allocation functions such as
- * crypto_alloc_blkcipher.
- *
- * In case of error the return value is an error pointer.
- */
struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
{
struct crypto_alg *alg;
@@ -208,31 +100,29 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
}
tfm = __crypto_alloc_tfm(alg, type, mask);
- if (IS_ERR(tfm)) {
- crypto_alg_put(alg);
+ if (IS_ERR(tfm))
return tfm;
- }
return tfm;
}
-void *crypto_create_tfm(struct crypto_alg *alg,
- const struct crypto_type *frontend)
+static void *crypto_create_tfm(struct crypto_alg *alg,
+ const struct crypto_type *frontend)
{
- char *mem;
struct crypto_tfm *tfm = NULL;
- unsigned int tfmsize;
- unsigned int total;
+ unsigned tfmsize;
+ unsigned total;
+ void *mem;
int err = -ENOMEM;
tfmsize = frontend->tfmsize;
total = tfmsize + sizeof(*tfm) + frontend->extsize(alg);
mem = kzalloc(total, GFP_KERNEL);
- if (mem == NULL)
+ if (!mem)
goto out_err;
- tfm = (struct crypto_tfm *)(mem + tfmsize);
+ tfm = mem + tfmsize;
tfm->__crt_alg = alg;
err = frontend->init_tfm(tfm);
@@ -254,28 +144,23 @@ out:
return mem;
}
-struct crypto_alg *crypto_find_alg(const char *alg_name,
- const struct crypto_type *frontend,
- u32 type, u32 mask)
+static struct crypto_alg *crypto_find_alg(const char *alg_name,
+ const struct crypto_type *frontend,
+ u32 type, u32 mask)
{
- struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask) =
- crypto_alg_mod_lookup;
-
if (frontend) {
type &= frontend->maskclear;
mask &= frontend->maskclear;
type |= frontend->type;
mask |= frontend->maskset;
-
- if (frontend->lookup)
- lookup = frontend->lookup;
}
- return lookup(alg_name, type, mask);
+ return crypto_alg_mod_lookup(alg_name, type, mask);
}
void *crypto_alloc_tfm(const char *alg_name,
- const struct crypto_type *frontend, u32 type, u32 mask)
+ const struct crypto_type *frontend,
+ u32 type, u32 mask)
{
struct crypto_alg *alg;
void *tfm;
@@ -285,10 +170,8 @@ void *crypto_alloc_tfm(const char *alg_name,
return ERR_CAST(alg);
tfm = crypto_create_tfm(alg, frontend);
- if (IS_ERR(tfm)) {
- crypto_alg_put(alg);
+ if (IS_ERR(tfm))
return tfm;
- }
return tfm;
}
@@ -305,22 +188,16 @@ void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
if (!tfm->exit && alg->cra_exit)
alg->cra_exit(tfm);
crypto_exit_ops(tfm);
- crypto_alg_put(alg);
kzfree(mem);
}
-int crypto_has_alg(const char *name, u32 type, u32 mask)
+int crypto_register_alg(struct crypto_alg *alg)
{
- int ret = 0;
- struct crypto_alg *alg = crypto_alg_mod_lookup(name, type, mask);
+ INIT_LIST_HEAD(&alg->cra_users);
- if (!IS_ERR(alg)) {
- crypto_alg_put(alg);
- ret = 1;
- }
+ down_write(&crypto_alg_sem);
+ list_add(&alg->cra_list, &crypto_alg_list);
+ up_write(&crypto_alg_sem);
- return ret;
+ return 0;
}
-
-MODULE_DESCRIPTION("Cryptographic core API");
-MODULE_LICENSE("GPL");