diff options
Diffstat (limited to 'crypto/api.c')
| -rw-r--r-- | crypto/api.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/crypto/api.c b/crypto/api.c index 394169a8577d..b4728811ce3b 100644 --- a/crypto/api.c +++ b/crypto/api.c | |||
| @@ -13,9 +13,12 @@ | |||
| 13 | * any later version. | 13 | * any later version. |
| 14 | * | 14 | * |
| 15 | */ | 15 | */ |
| 16 | |||
| 17 | #include <linux/compiler.h> | ||
| 16 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 17 | #include <linux/crypto.h> | 19 | #include <linux/crypto.h> |
| 18 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
| 21 | #include <linux/kmod.h> | ||
| 19 | #include <linux/rwsem.h> | 22 | #include <linux/rwsem.h> |
| 20 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 21 | #include "internal.h" | 24 | #include "internal.h" |
| @@ -33,7 +36,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg) | |||
| 33 | module_put(alg->cra_module); | 36 | module_put(alg->cra_module); |
| 34 | } | 37 | } |
| 35 | 38 | ||
| 36 | struct crypto_alg *crypto_alg_lookup(const char *name) | 39 | static struct crypto_alg *crypto_alg_lookup(const char *name) |
| 37 | { | 40 | { |
| 38 | struct crypto_alg *q, *alg = NULL; | 41 | struct crypto_alg *q, *alg = NULL; |
| 39 | 42 | ||
| @@ -54,6 +57,13 @@ struct crypto_alg *crypto_alg_lookup(const char *name) | |||
| 54 | return alg; | 57 | return alg; |
| 55 | } | 58 | } |
| 56 | 59 | ||
| 60 | /* A far more intelligent version of this is planned. For now, just | ||
| 61 | * try an exact match on the name of the algorithm. */ | ||
| 62 | static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) | ||
| 63 | { | ||
| 64 | return try_then_request_module(crypto_alg_lookup(name), name); | ||
| 65 | } | ||
| 66 | |||
| 57 | static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) | 67 | static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) |
| 58 | { | 68 | { |
| 59 | tfm->crt_flags = 0; | 69 | tfm->crt_flags = 0; |
| @@ -117,20 +127,46 @@ static void crypto_exit_ops(struct crypto_tfm *tfm) | |||
| 117 | } | 127 | } |
| 118 | } | 128 | } |
| 119 | 129 | ||
| 130 | static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags) | ||
| 131 | { | ||
| 132 | unsigned int len; | ||
| 133 | |||
| 134 | switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { | ||
| 135 | default: | ||
| 136 | BUG(); | ||
| 137 | |||
| 138 | case CRYPTO_ALG_TYPE_CIPHER: | ||
| 139 | len = crypto_cipher_ctxsize(alg, flags); | ||
| 140 | break; | ||
| 141 | |||
| 142 | case CRYPTO_ALG_TYPE_DIGEST: | ||
| 143 | len = crypto_digest_ctxsize(alg, flags); | ||
| 144 | break; | ||
| 145 | |||
| 146 | case CRYPTO_ALG_TYPE_COMPRESS: | ||
| 147 | len = crypto_compress_ctxsize(alg, flags); | ||
| 148 | break; | ||
| 149 | } | ||
| 150 | |||
| 151 | return len + alg->cra_alignmask; | ||
| 152 | } | ||
| 153 | |||
| 120 | struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) | 154 | struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) |
| 121 | { | 155 | { |
| 122 | struct crypto_tfm *tfm = NULL; | 156 | struct crypto_tfm *tfm = NULL; |
| 123 | struct crypto_alg *alg; | 157 | struct crypto_alg *alg; |
| 158 | unsigned int tfm_size; | ||
| 124 | 159 | ||
| 125 | alg = crypto_alg_mod_lookup(name); | 160 | alg = crypto_alg_mod_lookup(name); |
| 126 | if (alg == NULL) | 161 | if (alg == NULL) |
| 127 | goto out; | 162 | goto out; |
| 128 | 163 | ||
| 129 | tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); | 164 | tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags); |
| 165 | tfm = kmalloc(tfm_size, GFP_KERNEL); | ||
| 130 | if (tfm == NULL) | 166 | if (tfm == NULL) |
| 131 | goto out_put; | 167 | goto out_put; |
| 132 | 168 | ||
| 133 | memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize); | 169 | memset(tfm, 0, tfm_size); |
| 134 | 170 | ||
| 135 | tfm->__crt_alg = alg; | 171 | tfm->__crt_alg = alg; |
| 136 | 172 | ||
| @@ -155,8 +191,14 @@ out: | |||
| 155 | 191 | ||
| 156 | void crypto_free_tfm(struct crypto_tfm *tfm) | 192 | void crypto_free_tfm(struct crypto_tfm *tfm) |
| 157 | { | 193 | { |
| 158 | struct crypto_alg *alg = tfm->__crt_alg; | 194 | struct crypto_alg *alg; |
| 159 | int size = sizeof(*tfm) + alg->cra_ctxsize; | 195 | int size; |
| 196 | |||
| 197 | if (unlikely(!tfm)) | ||
| 198 | return; | ||
| 199 | |||
| 200 | alg = tfm->__crt_alg; | ||
| 201 | size = sizeof(*tfm) + alg->cra_ctxsize; | ||
| 160 | 202 | ||
| 161 | crypto_exit_ops(tfm); | 203 | crypto_exit_ops(tfm); |
| 162 | crypto_alg_put(alg); | 204 | crypto_alg_put(alg); |
| @@ -168,6 +210,12 @@ int crypto_register_alg(struct crypto_alg *alg) | |||
| 168 | { | 210 | { |
| 169 | int ret = 0; | 211 | int ret = 0; |
| 170 | struct crypto_alg *q; | 212 | struct crypto_alg *q; |
| 213 | |||
| 214 | if (alg->cra_alignmask & (alg->cra_alignmask + 1)) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | if (alg->cra_alignmask > PAGE_SIZE) | ||
| 218 | return -EINVAL; | ||
| 171 | 219 | ||
| 172 | down_write(&crypto_alg_sem); | 220 | down_write(&crypto_alg_sem); |
| 173 | 221 | ||
