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/hash.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/hash.c')
-rw-r--r-- | crypto/hash.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/crypto/hash.c b/crypto/hash.c index 4ccd22deef3..4d75ca7b57b 100644 --- a/crypto/hash.c +++ b/crypto/hash.c | |||
@@ -22,6 +22,42 @@ static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type, | |||
22 | return alg->cra_ctxsize; | 22 | return alg->cra_ctxsize; |
23 | } | 23 | } |
24 | 24 | ||
25 | static int hash_setkey_unaligned(struct crypto_hash *crt, const u8 *key, | ||
26 | unsigned int keylen) | ||
27 | { | ||
28 | struct crypto_tfm *tfm = crypto_hash_tfm(crt); | ||
29 | struct hash_alg *alg = &tfm->__crt_alg->cra_hash; | ||
30 | unsigned long alignmask = crypto_hash_alignmask(crt); | ||
31 | int ret; | ||
32 | u8 *buffer, *alignbuffer; | ||
33 | unsigned long absize; | ||
34 | |||
35 | absize = keylen + alignmask; | ||
36 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
37 | if (!buffer) | ||
38 | return -ENOMEM; | ||
39 | |||
40 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
41 | memcpy(alignbuffer, key, keylen); | ||
42 | ret = alg->setkey(crt, alignbuffer, keylen); | ||
43 | memset(alignbuffer, 0, absize); | ||
44 | kfree(buffer); | ||
45 | return ret; | ||
46 | } | ||
47 | |||
48 | static int hash_setkey(struct crypto_hash *crt, const u8 *key, | ||
49 | unsigned int keylen) | ||
50 | { | ||
51 | struct crypto_tfm *tfm = crypto_hash_tfm(crt); | ||
52 | struct hash_alg *alg = &tfm->__crt_alg->cra_hash; | ||
53 | unsigned long alignmask = crypto_hash_alignmask(crt); | ||
54 | |||
55 | if ((unsigned long)key & alignmask) | ||
56 | return hash_setkey_unaligned(crt, key, keylen); | ||
57 | |||
58 | return alg->setkey(crt, key, keylen); | ||
59 | } | ||
60 | |||
25 | static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | 61 | static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) |
26 | { | 62 | { |
27 | struct hash_tfm *crt = &tfm->crt_hash; | 63 | struct hash_tfm *crt = &tfm->crt_hash; |
@@ -34,7 +70,7 @@ static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | |||
34 | crt->update = alg->update; | 70 | crt->update = alg->update; |
35 | crt->final = alg->final; | 71 | crt->final = alg->final; |
36 | crt->digest = alg->digest; | 72 | crt->digest = alg->digest; |
37 | crt->setkey = alg->setkey; | 73 | crt->setkey = hash_setkey; |
38 | crt->digestsize = alg->digestsize; | 74 | crt->digestsize = alg->digestsize; |
39 | 75 | ||
40 | return 0; | 76 | return 0; |