aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/api.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-11-05 00:58:14 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-09 17:15:37 -0500
commit5cb1454b862ab3040b78364d58330262fea1ddba (patch)
tree7e62126fa1f1398bb6a6b7f9e136aece32b0e112 /crypto/api.c
parent06ace7a9bafeb9047352707eb79e8eaa0dfdf5f2 (diff)
[CRYPTO] Allow multiple implementations of the same algorithm
This is the first step on the road towards asynchronous support in the Crypto API. It adds support for having multiple crypto_alg objects for the same algorithm registered in the system. For example, each device driver would register a crypto_alg object for each algorithm that it supports. While at the same time the user may load software implementations of those same algorithms. Users of the Crypto API may then select a specific implementation by name, or choose any implementation for a given algorithm with the highest priority. The priority field is a 32-bit signed integer. In future it will be possible to modify it from user-space. This also provides a solution to the problem of selecting amongst various AES implementations, that is, aes vs. aes-i586 vs. aes-padlock. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/api.c')
-rw-r--r--crypto/api.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/crypto/api.c b/crypto/api.c
index 40ae42e9b6a6..2715afdf678c 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 4 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
5 * Copyright (c) 2002 David S. Miller (davem@redhat.com) 5 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
6 * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
6 * 7 *
7 * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> 8 * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
8 * and Nettle, by Niels Möller. 9 * and Nettle, by Niels Möller.
@@ -18,9 +19,11 @@
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/crypto.h> 20#include <linux/crypto.h>
20#include <linux/errno.h> 21#include <linux/errno.h>
22#include <linux/kernel.h>
21#include <linux/kmod.h> 23#include <linux/kmod.h>
22#include <linux/rwsem.h> 24#include <linux/rwsem.h>
23#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/string.h>
24#include "internal.h" 27#include "internal.h"
25 28
26LIST_HEAD(crypto_alg_list); 29LIST_HEAD(crypto_alg_list);
@@ -39,6 +42,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg)
39static struct crypto_alg *crypto_alg_lookup(const char *name) 42static struct crypto_alg *crypto_alg_lookup(const char *name)
40{ 43{
41 struct crypto_alg *q, *alg = NULL; 44 struct crypto_alg *q, *alg = NULL;
45 int best = -1;
42 46
43 if (!name) 47 if (!name)
44 return NULL; 48 return NULL;
@@ -46,11 +50,23 @@ static struct crypto_alg *crypto_alg_lookup(const char *name)
46 down_read(&crypto_alg_sem); 50 down_read(&crypto_alg_sem);
47 51
48 list_for_each_entry(q, &crypto_alg_list, cra_list) { 52 list_for_each_entry(q, &crypto_alg_list, cra_list) {
49 if (!(strcmp(q->cra_name, name))) { 53 int exact, fuzzy;
50 if (crypto_alg_get(q)) 54
51 alg = q; 55 exact = !strcmp(q->cra_driver_name, name);
56 fuzzy = !strcmp(q->cra_name, name);
57 if (!exact && !(fuzzy && q->cra_priority > best))
58 continue;
59
60 if (unlikely(!crypto_alg_get(q)))
61 continue;
62
63 best = q->cra_priority;
64 if (alg)
65 crypto_alg_put(alg);
66 alg = q;
67
68 if (exact)
52 break; 69 break;
53 }
54 } 70 }
55 71
56 up_read(&crypto_alg_sem); 72 up_read(&crypto_alg_sem);
@@ -207,9 +223,26 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
207 kfree(tfm); 223 kfree(tfm);
208} 224}
209 225
226static inline int crypto_set_driver_name(struct crypto_alg *alg)
227{
228 static const char suffix[] = "-generic";
229 char *driver_name = (char *)alg->cra_driver_name;
230 int len;
231
232 if (*driver_name)
233 return 0;
234
235 len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
236 if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
237 return -ENAMETOOLONG;
238
239 memcpy(driver_name + len, suffix, sizeof(suffix));
240 return 0;
241}
242
210int crypto_register_alg(struct crypto_alg *alg) 243int crypto_register_alg(struct crypto_alg *alg)
211{ 244{
212 int ret = 0; 245 int ret;
213 struct crypto_alg *q; 246 struct crypto_alg *q;
214 247
215 if (alg->cra_alignmask & (alg->cra_alignmask + 1)) 248 if (alg->cra_alignmask & (alg->cra_alignmask + 1))
@@ -220,11 +253,18 @@ int crypto_register_alg(struct crypto_alg *alg)
220 253
221 if (alg->cra_blocksize > PAGE_SIZE) 254 if (alg->cra_blocksize > PAGE_SIZE)
222 return -EINVAL; 255 return -EINVAL;
256
257 if (alg->cra_priority < 0)
258 return -EINVAL;
223 259
260 ret = crypto_set_driver_name(alg);
261 if (unlikely(ret))
262 return ret;
263
224 down_write(&crypto_alg_sem); 264 down_write(&crypto_alg_sem);
225 265
226 list_for_each_entry(q, &crypto_alg_list, cra_list) { 266 list_for_each_entry(q, &crypto_alg_list, cra_list) {
227 if (!(strcmp(q->cra_name, alg->cra_name))) { 267 if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) {
228 ret = -EEXIST; 268 ret = -EEXIST;
229 goto out; 269 goto out;
230 } 270 }