diff options
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 | ||
