diff options
Diffstat (limited to 'crypto/api.c')
| -rw-r--r-- | crypto/api.c | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/crypto/api.c b/crypto/api.c index 40ae42e9b6a6..e26156f71839 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)) |
| @@ -218,13 +251,20 @@ int crypto_register_alg(struct crypto_alg *alg) | |||
| 218 | if (alg->cra_alignmask & alg->cra_blocksize) | 251 | if (alg->cra_alignmask & alg->cra_blocksize) |
| 219 | return -EINVAL; | 252 | return -EINVAL; |
| 220 | 253 | ||
| 221 | if (alg->cra_blocksize > PAGE_SIZE) | 254 | if (alg->cra_blocksize > PAGE_SIZE / 8) |
| 255 | return -EINVAL; | ||
| 256 | |||
| 257 | if (alg->cra_priority < 0) | ||
| 222 | return -EINVAL; | 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 | } |
