diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2017-05-09 15:48:23 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2017-05-18 01:04:05 -0400 |
commit | 9933e113c2e87a9f46a40fde8dafbf801dca1ab9 (patch) | |
tree | 2dfb79292d8b5799355667d5fbacfbff06d1e2e2 | |
parent | 2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff) |
crypto: skcipher - Add missing API setkey checks
The API setkey checks for key sizes and alignment went AWOL during the
skcipher conversion. This patch restores them.
Cc: <stable@vger.kernel.org>
Fixes: 4e6c3df4d729 ("crypto: skcipher - Add low-level skcipher...")
Reported-by: Baozeng <sploving1@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-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; |