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/cipher.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/cipher.c')
-rw-r--r-- | crypto/cipher.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/crypto/cipher.c b/crypto/cipher.c index 333aab2f0277..0b2650c2014b 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c | |||
@@ -20,16 +20,43 @@ | |||
20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include "internal.h" | 21 | #include "internal.h" |
22 | 22 | ||
23 | static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | ||
24 | { | ||
25 | struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; | ||
26 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
27 | int ret; | ||
28 | u8 *buffer, *alignbuffer; | ||
29 | unsigned long absize; | ||
30 | |||
31 | absize = keylen + alignmask; | ||
32 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
33 | if (!buffer) | ||
34 | return -ENOMEM; | ||
35 | |||
36 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
37 | memcpy(alignbuffer, key, keylen); | ||
38 | ret = cia->cia_setkey(tfm, alignbuffer, keylen); | ||
39 | memset(alignbuffer, 0, absize); | ||
40 | kfree(buffer); | ||
41 | return ret; | ||
42 | |||
43 | } | ||
44 | |||
23 | static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | 45 | static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) |
24 | { | 46 | { |
25 | struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; | 47 | struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; |
26 | 48 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | |
49 | |||
27 | tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; | 50 | tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; |
28 | if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { | 51 | if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { |
29 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | 52 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; |
30 | return -EINVAL; | 53 | return -EINVAL; |
31 | } else | 54 | } |
32 | return cia->cia_setkey(tfm, key, keylen); | 55 | |
56 | if ((unsigned long)key & alignmask) | ||
57 | return setkey_unaligned(tfm, key, keylen); | ||
58 | |||
59 | return cia->cia_setkey(tfm, key, keylen); | ||
33 | } | 60 | } |
34 | 61 | ||
35 | static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, | 62 | static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, |