diff options
author | Sebastian Siewior <linux-crypto@ml.breakpoint.cc> | 2007-05-19 05:51:21 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2007-07-11 08:58:54 -0400 |
commit | ca7c39385ce1a7b44894a4b225a4608624e90730 (patch) | |
tree | 107948d1bd8010ccb5185f34e2c2ef93098586cb /crypto/ablkcipher.c | |
parent | fe3c5206adc5d7395828185ab73e9a522655b984 (diff) |
[CRYPTO] api: Handle unaligned keys in setkey
setkey() in {cipher,blkcipher,ablkcipher,hash}.c does not respect the
requested alignment by the algorithm. This patch fixes it. The extra
memory is allocated by kmalloc() with GFP_ATOMIC flag.
Signed-off-by: Sebastian Siewior <linux-crypto@ml.breakpoint.cc>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/ablkcipher.c')
-rw-r--r-- | crypto/ablkcipher.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 9348ddd84a56..d45fa16dff81 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c | |||
@@ -19,16 +19,41 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | 21 | ||
22 | static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) | ||
23 | { | ||
24 | struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); | ||
25 | unsigned long alignmask = crypto_ablkcipher_alignmask(tfm); | ||
26 | int ret; | ||
27 | u8 *buffer, *alignbuffer; | ||
28 | unsigned long absize; | ||
29 | |||
30 | absize = keylen + alignmask; | ||
31 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
32 | if (!buffer) | ||
33 | return -ENOMEM; | ||
34 | |||
35 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
36 | memcpy(alignbuffer, key, keylen); | ||
37 | ret = cipher->setkey(tfm, alignbuffer, keylen); | ||
38 | memset(alignbuffer, 0, absize); | ||
39 | kfree(buffer); | ||
40 | return ret; | ||
41 | } | ||
42 | |||
22 | static int setkey(struct crypto_ablkcipher *tfm, const u8 *key, | 43 | static int setkey(struct crypto_ablkcipher *tfm, const u8 *key, |
23 | unsigned int keylen) | 44 | unsigned int keylen) |
24 | { | 45 | { |
25 | struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); | 46 | struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); |
47 | unsigned long alignmask = crypto_ablkcipher_alignmask(tfm); | ||
26 | 48 | ||
27 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { | 49 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { |
28 | crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | 50 | crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); |
29 | return -EINVAL; | 51 | return -EINVAL; |
30 | } | 52 | } |
31 | 53 | ||
54 | if ((unsigned long)key & alignmask) | ||
55 | return setkey_unaligned(tfm, key, keylen); | ||
56 | |||
32 | return cipher->setkey(tfm, key, keylen); | 57 | return cipher->setkey(tfm, key, keylen); |
33 | } | 58 | } |
34 | 59 | ||