diff options
Diffstat (limited to 'crypto/api.c')
-rw-r--r-- | crypto/api.c | 52 |
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 | ||
26 | LIST_HEAD(crypto_alg_list); | 29 | LIST_HEAD(crypto_alg_list); |
@@ -39,6 +42,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg) | |||
39 | static struct crypto_alg *crypto_alg_lookup(const char *name) | 42 | static 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 | ||
226 | static 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 | |||
210 | int crypto_register_alg(struct crypto_alg *alg) | 243 | int 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 | } |