crypto: chelsio - fix writing tfm flags to wrong place
authorEric Biggers <ebiggers@google.com>
Tue, 31 Dec 2019 03:19:31 +0000 (21:19 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 1 Feb 2020 09:37:04 +0000 (09:37 +0000)
commit bd56cea012fc2d6381e8cd3209510ce09f9de8c9 upstream.

The chelsio crypto driver is casting 'struct crypto_aead' directly to
'struct crypto_tfm', which is incorrect because the crypto_tfm isn't the
first field of 'struct crypto_aead'.  Consequently, the calls to
crypto_tfm_set_flags() are modifying some other field in the struct.

Also, the driver is setting CRYPTO_TFM_RES_BAD_KEY_LEN in
->setauthsize(), not just in ->setkey().  This is incorrect since this
flag is for bad key lengths, not for bad authentication tag lengths.

Fix these bugs by removing the broken crypto_tfm_set_flags() calls from
->setauthsize() and by fixing them in ->setkey().

Fixes: 324429d74127 ("chcr: Support for Chelsio's Crypto Hardware")
Cc: <stable@vger.kernel.org> # v4.9+
Cc: Atul Gupta <atul.gupta@chelsio.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/crypto/chelsio/chcr_algo.c

index 010bbf6..c435f89 100644 (file)
@@ -3135,9 +3135,6 @@ static int chcr_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
                aeadctx->mayverify = VERIFY_SW;
                break;
        default:
-
-                 crypto_tfm_set_flags((struct crypto_tfm *) tfm,
-                       CRYPTO_TFM_RES_BAD_KEY_LEN);
                return -EINVAL;
        }
        return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
@@ -3162,8 +3159,6 @@ static int chcr_4106_4309_setauthsize(struct crypto_aead *tfm,
                aeadctx->mayverify = VERIFY_HW;
                break;
        default:
-               crypto_tfm_set_flags((struct crypto_tfm *)tfm,
-                                    CRYPTO_TFM_RES_BAD_KEY_LEN);
                return -EINVAL;
        }
        return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
@@ -3204,8 +3199,6 @@ static int chcr_ccm_setauthsize(struct crypto_aead *tfm,
                aeadctx->mayverify = VERIFY_HW;
                break;
        default:
-               crypto_tfm_set_flags((struct crypto_tfm *)tfm,
-                                    CRYPTO_TFM_RES_BAD_KEY_LEN);
                return -EINVAL;
        }
        return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
@@ -3230,8 +3223,7 @@ static int chcr_ccm_common_setkey(struct crypto_aead *aead,
                ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
                mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
        } else {
-               crypto_tfm_set_flags((struct crypto_tfm *)aead,
-                                    CRYPTO_TFM_RES_BAD_KEY_LEN);
+               crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
                aeadctx->enckey_len = 0;
                return  -EINVAL;
        }
@@ -3269,8 +3261,7 @@ static int chcr_aead_rfc4309_setkey(struct crypto_aead *aead, const u8 *key,
        int error;
 
        if (keylen < 3) {
-               crypto_tfm_set_flags((struct crypto_tfm *)aead,
-                                    CRYPTO_TFM_RES_BAD_KEY_LEN);
+               crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
                aeadctx->enckey_len = 0;
                return  -EINVAL;
        }
@@ -3320,8 +3311,7 @@ static int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key,
        } else if (keylen == AES_KEYSIZE_256) {
                ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
        } else {
-               crypto_tfm_set_flags((struct crypto_tfm *)aead,
-                                    CRYPTO_TFM_RES_BAD_KEY_LEN);
+               crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
                pr_err("GCM: Invalid key length %d\n", keylen);
                ret = -EINVAL;
                goto out;