diff options
Diffstat (limited to 'crypto')
| -rw-r--r-- | crypto/skcipher.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 014af741fc6a..4faa0fd53b0c 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c | |||
| @@ -764,6 +764,44 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) | |||
| 764 | return 0; | 764 | return 0; |
| 765 | } | 765 | } |
| 766 | 766 | ||
| 767 | static int skcipher_setkey_unaligned(struct crypto_skcipher *tfm, | ||
| 768 | const u8 *key, unsigned int keylen) | ||
| 769 | { | ||
| 770 | unsigned long alignmask = crypto_skcipher_alignmask(tfm); | ||
| 771 | struct skcipher_alg *cipher = crypto_skcipher_alg(tfm); | ||
| 772 | u8 *buffer, *alignbuffer; | ||
| 773 | unsigned long absize; | ||
| 774 | int ret; | ||
| 775 | |||
| 776 | absize = keylen + alignmask; | ||
| 777 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
| 778 | if (!buffer) | ||
| 779 | return -ENOMEM; | ||
| 780 | |||
| 781 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
| 782 | memcpy(alignbuffer, key, keylen); | ||
| 783 | ret = cipher->setkey(tfm, alignbuffer, keylen); | ||
| 784 | kzfree(buffer); | ||
| 785 | return ret; | ||
| 786 | } | ||
| 787 | |||
| 788 | static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, | ||
| 789 | unsigned int keylen) | ||
| 790 | { | ||
| 791 | struct skcipher_alg *cipher = crypto_skcipher_alg(tfm); | ||
| 792 | unsigned long alignmask = crypto_skcipher_alignmask(tfm); | ||
| 793 | |||
| 794 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { | ||
| 795 | crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | ||
| 796 | return -EINVAL; | ||
| 797 | } | ||
| 798 | |||
| 799 | if ((unsigned long)key & alignmask) | ||
| 800 | return skcipher_setkey_unaligned(tfm, key, keylen); | ||
| 801 | |||
| 802 | return cipher->setkey(tfm, key, keylen); | ||
| 803 | } | ||
| 804 | |||
| 767 | static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm) | 805 | static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm) |
| 768 | { | 806 | { |
| 769 | struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); | 807 | struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); |
| @@ -784,7 +822,7 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) | |||
| 784 | tfm->__crt_alg->cra_type == &crypto_givcipher_type) | 822 | tfm->__crt_alg->cra_type == &crypto_givcipher_type) |
| 785 | return crypto_init_skcipher_ops_ablkcipher(tfm); | 823 | return crypto_init_skcipher_ops_ablkcipher(tfm); |
| 786 | 824 | ||
| 787 | skcipher->setkey = alg->setkey; | 825 | skcipher->setkey = skcipher_setkey; |
| 788 | skcipher->encrypt = alg->encrypt; | 826 | skcipher->encrypt = alg->encrypt; |
| 789 | skcipher->decrypt = alg->decrypt; | 827 | skcipher->decrypt = alg->decrypt; |
| 790 | skcipher->ivsize = alg->ivsize; | 828 | skcipher->ivsize = alg->ivsize; |
