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/blkcipher.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/blkcipher.c')
-rw-r--r-- | crypto/blkcipher.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 8edf40c835a7..40a3dcff15bb 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c | |||
@@ -336,16 +336,41 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc, | |||
336 | return blkcipher_walk_next(desc, walk); | 336 | return blkcipher_walk_next(desc, walk); |
337 | } | 337 | } |
338 | 338 | ||
339 | static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | ||
340 | { | ||
341 | struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; | ||
342 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
343 | int ret; | ||
344 | u8 *buffer, *alignbuffer; | ||
345 | unsigned long absize; | ||
346 | |||
347 | absize = keylen + alignmask; | ||
348 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
349 | if (!buffer) | ||
350 | return -ENOMEM; | ||
351 | |||
352 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
353 | memcpy(alignbuffer, key, keylen); | ||
354 | ret = cipher->setkey(tfm, alignbuffer, keylen); | ||
355 | memset(alignbuffer, 0, absize); | ||
356 | kfree(buffer); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
339 | static int setkey(struct crypto_tfm *tfm, const u8 *key, | 360 | static int setkey(struct crypto_tfm *tfm, const u8 *key, |
340 | unsigned int keylen) | 361 | unsigned int keylen) |
341 | { | 362 | { |
342 | struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; | 363 | struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; |
364 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
343 | 365 | ||
344 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { | 366 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { |
345 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | 367 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; |
346 | return -EINVAL; | 368 | return -EINVAL; |
347 | } | 369 | } |
348 | 370 | ||
371 | if ((unsigned long)key & alignmask) | ||
372 | return setkey_unaligned(tfm, key, keylen); | ||
373 | |||
349 | return cipher->setkey(tfm, key, keylen); | 374 | return cipher->setkey(tfm, key, keylen); |
350 | } | 375 | } |
351 | 376 | ||