summaryrefslogtreecommitdiffstats
path: root/crypto/skcipher.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-01-06 21:47:43 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2019-01-18 05:40:24 -0500
commitb1f6b4bf416b49f00f3abc49c639371cdecaaad1 (patch)
treeebdeae9666108a5ceac5e28a2138a967a149543d /crypto/skcipher.c
parentba7d7433a0e998c902132bd47330e355a1eaa894 (diff)
crypto: skcipher - set CRYPTO_TFM_NEED_KEY if ->setkey() fails
Some algorithms have a ->setkey() method that is not atomic, in the sense that setting a key can fail after changes were already made to the tfm context. In this case, if a key was already set the tfm can end up in a state that corresponds to neither the old key nor the new key. For example, in lrw.c, if gf128mul_init_64k_bbe() fails due to lack of memory, then priv::table will be left NULL. After that, encryption with that tfm will cause a NULL pointer dereference. It's not feasible to make all ->setkey() methods atomic, especially ones that have to key multiple sub-tfms. Therefore, make the crypto API set CRYPTO_TFM_NEED_KEY if ->setkey() fails and the algorithm requires a key, to prevent the tfm from being used until a new key is set. [Cc stable mainly because when introducing the NEED_KEY flag I changed AF_ALG to rely on it; and unlike in-kernel crypto API users, AF_ALG previously didn't have this problem. So these "incompletely keyed" states became theoretically accessible via AF_ALG -- though, the opportunities for causing real mischief seem pretty limited.] Fixes: f8d33fac8480 ("crypto: skcipher - prevent using skciphers without setting key") Cc: <stable@vger.kernel.org> # v4.16+ Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/skcipher.c')
-rw-r--r--crypto/skcipher.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index 040ae6377b32..bcf13d95f54a 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -585,6 +585,12 @@ static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg)
585 return crypto_alg_extsize(alg); 585 return crypto_alg_extsize(alg);
586} 586}
587 587
588static void skcipher_set_needkey(struct crypto_skcipher *tfm)
589{
590 if (tfm->keysize)
591 crypto_skcipher_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
592}
593
588static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm, 594static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm,
589 const u8 *key, unsigned int keylen) 595 const u8 *key, unsigned int keylen)
590{ 596{
@@ -598,8 +604,10 @@ static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm,
598 err = crypto_blkcipher_setkey(blkcipher, key, keylen); 604 err = crypto_blkcipher_setkey(blkcipher, key, keylen);
599 crypto_skcipher_set_flags(tfm, crypto_blkcipher_get_flags(blkcipher) & 605 crypto_skcipher_set_flags(tfm, crypto_blkcipher_get_flags(blkcipher) &
600 CRYPTO_TFM_RES_MASK); 606 CRYPTO_TFM_RES_MASK);
601 if (err) 607 if (unlikely(err)) {
608 skcipher_set_needkey(tfm);
602 return err; 609 return err;
610 }
603 611
604 crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); 612 crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
605 return 0; 613 return 0;
@@ -677,8 +685,7 @@ static int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm)
677 skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher); 685 skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher);
678 skcipher->keysize = calg->cra_blkcipher.max_keysize; 686 skcipher->keysize = calg->cra_blkcipher.max_keysize;
679 687
680 if (skcipher->keysize) 688 skcipher_set_needkey(skcipher);
681 crypto_skcipher_set_flags(skcipher, CRYPTO_TFM_NEED_KEY);
682 689
683 return 0; 690 return 0;
684} 691}
@@ -698,8 +705,10 @@ static int skcipher_setkey_ablkcipher(struct crypto_skcipher *tfm,
698 crypto_skcipher_set_flags(tfm, 705 crypto_skcipher_set_flags(tfm,
699 crypto_ablkcipher_get_flags(ablkcipher) & 706 crypto_ablkcipher_get_flags(ablkcipher) &
700 CRYPTO_TFM_RES_MASK); 707 CRYPTO_TFM_RES_MASK);
701 if (err) 708 if (unlikely(err)) {
709 skcipher_set_needkey(tfm);
702 return err; 710 return err;
711 }
703 712
704 crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); 713 crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
705 return 0; 714 return 0;
@@ -776,8 +785,7 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
776 sizeof(struct ablkcipher_request); 785 sizeof(struct ablkcipher_request);
777 skcipher->keysize = calg->cra_ablkcipher.max_keysize; 786 skcipher->keysize = calg->cra_ablkcipher.max_keysize;
778 787
779 if (skcipher->keysize) 788 skcipher_set_needkey(skcipher);
780 crypto_skcipher_set_flags(skcipher, CRYPTO_TFM_NEED_KEY);
781 789
782 return 0; 790 return 0;
783} 791}
@@ -820,8 +828,10 @@ static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
820 else 828 else
821 err = cipher->setkey(tfm, key, keylen); 829 err = cipher->setkey(tfm, key, keylen);
822 830
823 if (err) 831 if (unlikely(err)) {
832 skcipher_set_needkey(tfm);
824 return err; 833 return err;
834 }
825 835
826 crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); 836 crypto_skcipher_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
827 return 0; 837 return 0;
@@ -852,8 +862,7 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
852 skcipher->ivsize = alg->ivsize; 862 skcipher->ivsize = alg->ivsize;
853 skcipher->keysize = alg->max_keysize; 863 skcipher->keysize = alg->max_keysize;
854 864
855 if (skcipher->keysize) 865 skcipher_set_needkey(skcipher);
856 crypto_skcipher_set_flags(skcipher, CRYPTO_TFM_NEED_KEY);
857 866
858 if (alg->exit) 867 if (alg->exit)
859 skcipher->base.exit = crypto_skcipher_exit_tfm; 868 skcipher->base.exit = crypto_skcipher_exit_tfm;