diff options
-rw-r--r-- | crypto/api.c | 52 | ||||
-rw-r--r-- | crypto/internal.h | 6 | ||||
-rw-r--r-- | crypto/proc.c | 6 | ||||
-rw-r--r-- | include/linux/crypto.h | 5 |
4 files changed, 60 insertions, 9 deletions
diff --git a/crypto/api.c b/crypto/api.c index 40ae42e..2715afd 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -3,6 +3,7 @@ * * 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. @@ -18,9 +19,11 @@ #include <linux/init.h> #include <linux/crypto.h> #include <linux/errno.h> +#include <linux/kernel.h> #include <linux/kmod.h> #include <linux/rwsem.h> #include <linux/slab.h> +#include <linux/string.h> #include "internal.h" LIST_HEAD(crypto_alg_list); @@ -39,6 +42,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg) static struct crypto_alg *crypto_alg_lookup(const char *name) { struct crypto_alg *q, *alg = NULL; + int best = -1; if (!name) return NULL; @@ -46,11 +50,23 @@ static struct crypto_alg *crypto_alg_lookup(const char *name) down_read(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, name))) { - if (crypto_alg_get(q)) - alg = q; + int exact, fuzzy; + + 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; - } } up_read(&crypto_alg_sem); @@ -207,9 +223,26 @@ void crypto_free_tfm(struct crypto_tfm *tfm) kfree(tfm); } +static inline int crypto_set_driver_name(struct crypto_alg *alg) +{ + static const char suffix[] = "-generic"; + char *driver_name = (char *)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; +} + int crypto_register_alg(struct crypto_alg *alg) { - int ret = 0; + int ret; struct crypto_alg *q; if (alg->cra_alignmask & (alg->cra_alignmask + 1)) @@ -220,11 +253,18 @@ int crypto_register_alg(struct crypto_alg *alg) if (alg->cra_blocksize > PAGE_SIZE) return -EINVAL; + + if (alg->cra_priority < 0) + return -EINVAL; + ret = crypto_set_driver_name(alg); + if (unlikely(ret)) + return ret; + down_write(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, alg->cra_name))) { + if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) { ret = -EEXIST; goto out; } diff --git a/crypto/internal.h b/crypto/internal.h index 37aa652..959e602 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -2,6 +2,7 @@ * Cryptographic API. * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2005 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 @@ -16,10 +17,15 @@ #include <linux/highmem.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/list.h> #include <linux/kernel.h> +#include <linux/rwsem.h> #include <linux/slab.h> #include <asm/kmap_types.h> +extern struct list_head crypto_alg_list; +extern struct rw_semaphore crypto_alg_sem; + extern enum km_type crypto_km_types[]; static inline enum km_type crypto_kmap_type(int out) diff --git a/crypto/proc.c b/crypto/proc.c index 630ba91..c0a5dd7 100644 --- a/crypto/proc.c +++ b/crypto/proc.c @@ -4,6 +4,7 @@ * Procfs information. * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2005 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 @@ -18,9 +19,6 @@ #include <linux/seq_file.h> #include "internal.h" -extern struct list_head crypto_alg_list; -extern struct rw_semaphore crypto_alg_sem; - static void *c_start(struct seq_file *m, loff_t *pos) { struct list_head *v; @@ -53,7 +51,9 @@ 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, "driver : %s\n", alg->cra_driver_name); seq_printf(m, "module : %s\n", module_name(alg->cra_module)); + seq_printf(m, "priority : %d\n", alg->cra_priority); switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_CIPHER: diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 3c89df6..d88bf8a 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -3,6 +3,7 @@ * * 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. @@ -126,7 +127,11 @@ struct crypto_alg { unsigned int cra_blocksize; unsigned int cra_ctxsize; unsigned int cra_alignmask; + + int cra_priority; + const char cra_name[CRYPTO_MAX_ALG_NAME]; + const char cra_driver_name[CRYPTO_MAX_ALG_NAME]; union { struct cipher_alg cipher; |