From dc029f6b951aa6c88dd60e6c7bb5b5dd07564d2f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jun 2026 15:18:09 +0200 Subject: [PATCH 1/8] FROMLIST: crypto: qce - Remove unsafe/deprecated algorithms Remove algorithms that are either unsafe or deprecated and have no in-kernel users that cannot be served by the ARM CE implementations. AES-ECB reveals plaintext patterns (identical plaintext blocks produce identical ciphertext blocks) and should not be exposed as a hardware- accelerated primitive. DES, Triple DES and HMAC-SHA1 have been deprecated for years. Remove sha1, ecb(aes), ecb(des), cbc(des), ecb(des3_ede), cbc(des3_ede), hmac(sha1) and all AEAD variants built on these primitives as well as authenc(hmac(sha256),cbc(des)). Also clean up the - now dead - code, flags and constants. Cc: stable@vger.kernel.org Acked-by: Eric Biggers Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-1-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/aead.c | 56 +------------------- drivers/crypto/qce/common.c | 55 +++++--------------- drivers/crypto/qce/common.h | 16 ++---- drivers/crypto/qce/regs-v5.h | 4 -- drivers/crypto/qce/sha.c | 30 +---------- drivers/crypto/qce/sha.h | 1 - drivers/crypto/qce/skcipher.c | 97 +---------------------------------- 7 files changed, 20 insertions(+), 239 deletions(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 8831adb7b0f56..48ea7fb9a91e6 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -9,8 +9,6 @@ #include #include #include -#include -#include #include #include #include "aead.h" @@ -592,7 +590,6 @@ static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); struct crypto_authenc_keys authenc_keys; unsigned long flags = to_aead_tmpl(tfm)->alg_flags; - u32 _key[6]; int err; err = crypto_authenc_extractkeys(&authenc_keys, key, keylen); @@ -603,26 +600,7 @@ static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int authenc_keys.authkeylen > QCE_MAX_KEY_SIZE) return -EINVAL; - if (IS_DES(flags)) { - err = verify_aead_des_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); - if (err) - return err; - } else if (IS_3DES(flags)) { - err = verify_aead_des3_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); - if (err) - return err; - /* - * The crypto engine does not support any two keys - * being the same for triple des algorithms. The - * verify_skcipher_des3_key does not check for all the - * below conditions. Schedule fallback in this case. - */ - memcpy(_key, authenc_keys.enckey, DES3_EDE_KEY_SIZE); - if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || - !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || - !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) - ctx->need_fallback = true; - } else if (IS_AES(flags)) { + if (IS_AES(flags)) { /* No random key sizes */ if (authenc_keys.enckeylen != AES_KEYSIZE_128 && authenc_keys.enckeylen != AES_KEYSIZE_192 && @@ -693,38 +671,6 @@ struct qce_aead_def { }; static const struct qce_aead_def aead_def[] = { - { - .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, - .name = "authenc(hmac(sha1),cbc(des))", - .drv_name = "authenc-hmac-sha1-cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .maxauthsize = SHA1_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, - .name = "authenc(hmac(sha1),cbc(des3_ede))", - .drv_name = "authenc-hmac-sha1-cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .maxauthsize = SHA1_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, - .name = "authenc(hmac(sha256),cbc(des))", - .drv_name = "authenc-hmac-sha256-cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .maxauthsize = SHA256_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, - .name = "authenc(hmac(sha256),cbc(des3_ede))", - .drv_name = "authenc-hmac-sha256-cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .maxauthsize = SHA256_DIGEST_SIZE, - }, { .flags = QCE_ALG_AES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, .name = "authenc(hmac(sha256),cbc(aes))", diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c index 37bb6f03244d3..5930933412e94 100644 --- a/drivers/crypto/qce/common.c +++ b/drivers/crypto/qce/common.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "cipher.h" @@ -119,18 +118,16 @@ static u32 qce_auth_cfg(unsigned long flags, u32 key_size, u32 auth_size) cfg |= AUTH_KEY_SZ_AES256 << AUTH_KEY_SIZE_SHIFT; } - if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) - cfg |= AUTH_SIZE_SHA1 << AUTH_SIZE_SHIFT; - else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) + if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) cfg |= AUTH_SIZE_SHA256 << AUTH_SIZE_SHIFT; else if (IS_CMAC(flags)) cfg |= AUTH_SIZE_ENUM_16_BYTES << AUTH_SIZE_SHIFT; else if (IS_CCM(flags)) cfg |= (auth_size - 1) << AUTH_SIZE_SHIFT; - if (IS_SHA1(flags) || IS_SHA256(flags)) + if (IS_SHA256(flags)) cfg |= AUTH_MODE_HASH << AUTH_MODE_SHIFT; - else if (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) + else if (IS_SHA256_HMAC(flags)) cfg |= AUTH_MODE_HMAC << AUTH_MODE_SHIFT; else if (IS_CCM(flags)) cfg |= AUTH_MODE_CCM << AUTH_MODE_SHIFT; @@ -195,7 +192,7 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req) else qce_cpu_to_be32p_array(auth, rctx->digest, digestsize); - iv_words = (IS_SHA1(rctx->flags) || IS_SHA1_HMAC(rctx->flags)) ? 5 : 8; + iv_words = 8; qce_write_array(qce, REG_AUTH_IV0, (u32 *)auth, iv_words); if (rctx->first_blk) @@ -245,19 +242,8 @@ static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) if (IS_AES(flags)) cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; - else if (IS_DES(flags) || IS_3DES(flags)) - cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; - - if (IS_DES(flags)) - cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; - - if (IS_3DES(flags)) - cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; switch (flags & QCE_MODE_MASK) { - case QCE_MODE_ECB: - cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; - break; case QCE_MODE_CBC: cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; break; @@ -342,13 +328,7 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) encr_cfg = qce_encr_cfg(flags, keylen); - if (IS_DES(flags)) { - enciv_words = 2; - enckey_words = 2; - } else if (IS_3DES(flags)) { - enciv_words = 2; - enckey_words = 6; - } else if (IS_AES(flags)) { + if (IS_AES(flags)) { if (IS_XTS(flags)) qce_xtskey(qce, ctx->enc_key, ctx->enc_keylen, rctx->cryptlen); @@ -359,14 +339,12 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) qce_write_array(qce, REG_ENCR_KEY0, (u32 *)enckey, enckey_words); - if (!IS_ECB(flags)) { - if (IS_XTS(flags)) - qce_xts_swapiv(enciv, rctx->iv, ivsize); - else - qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize); + if (IS_XTS(flags)) + qce_xts_swapiv(enciv, rctx->iv, ivsize); + else + qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize); - qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words); - } + qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words); if (IS_ENCRYPT(flags)) encr_cfg |= BIT(ENCODE_SHIFT); @@ -393,10 +371,6 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) #endif #ifdef CONFIG_CRYPTO_DEV_QCE_AEAD -static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = { - SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0 -}; - static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 @@ -473,13 +447,8 @@ static int qce_setup_regs_aead(struct crypto_async_request *async_req) /* Write initial authentication IV only for HMAC algorithms */ if (IS_SHA_HMAC(rctx->flags)) { /* Write default authentication iv */ - if (IS_SHA1_HMAC(rctx->flags)) { - auth_ivsize = SHA1_DIGEST_SIZE; - memcpy(authiv, std_iv_sha1, auth_ivsize); - } else if (IS_SHA256_HMAC(rctx->flags)) { - auth_ivsize = SHA256_DIGEST_SIZE; - memcpy(authiv, std_iv_sha256, auth_ivsize); - } + auth_ivsize = SHA256_DIGEST_SIZE; + memcpy(authiv, std_iv_sha256, auth_ivsize); authiv_words = auth_ivsize / sizeof(u32); qce_write_array(qce, REG_AUTH_IV0, (u32 *)authiv, authiv_words); } else if (IS_CCM(rctx->flags)) { diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h index 02e63ad9f2455..9cd2e6ed8bbb0 100644 --- a/drivers/crypto/qce/common.h +++ b/drivers/crypto/qce/common.h @@ -22,7 +22,7 @@ /* IV length in bytes */ #define QCE_AES_IV_LENGTH AES_BLOCK_SIZE -/* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ +/* max of AES_BLOCK_SIZE */ #define QCE_MAX_IV_SIZE AES_BLOCK_SIZE /* maximum nonce bytes */ @@ -33,14 +33,10 @@ #define QCE_MAX_ALIGN_SIZE 64 /* cipher algorithms */ -#define QCE_ALG_DES BIT(0) -#define QCE_ALG_3DES BIT(1) #define QCE_ALG_AES BIT(2) /* hash and hmac algorithms */ -#define QCE_HASH_SHA1 BIT(3) #define QCE_HASH_SHA256 BIT(4) -#define QCE_HASH_SHA1_HMAC BIT(5) #define QCE_HASH_SHA256_HMAC BIT(6) #define QCE_HASH_AES_CMAC BIT(7) @@ -58,21 +54,15 @@ #define QCE_ENCRYPT BIT(30) #define QCE_DECRYPT BIT(31) -#define IS_DES(flags) (flags & QCE_ALG_DES) -#define IS_3DES(flags) (flags & QCE_ALG_3DES) #define IS_AES(flags) (flags & QCE_ALG_AES) -#define IS_SHA1(flags) (flags & QCE_HASH_SHA1) #define IS_SHA256(flags) (flags & QCE_HASH_SHA256) -#define IS_SHA1_HMAC(flags) (flags & QCE_HASH_SHA1_HMAC) #define IS_SHA256_HMAC(flags) (flags & QCE_HASH_SHA256_HMAC) #define IS_CMAC(flags) (flags & QCE_HASH_AES_CMAC) -#define IS_SHA(flags) (IS_SHA1(flags) || IS_SHA256(flags)) -#define IS_SHA_HMAC(flags) \ - (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) +#define IS_SHA(flags) IS_SHA256(flags) +#define IS_SHA_HMAC(flags) IS_SHA256_HMAC(flags) #define IS_CBC(mode) (mode & QCE_MODE_CBC) -#define IS_ECB(mode) (mode & QCE_MODE_ECB) #define IS_CTR(mode) (mode & QCE_MODE_CTR) #define IS_XTS(mode) (mode & QCE_MODE_XTS) #define IS_CCM(mode) (mode & QCE_MODE_CCM) diff --git a/drivers/crypto/qce/regs-v5.h b/drivers/crypto/qce/regs-v5.h index d59ed27989062..431a7db1a4e72 100644 --- a/drivers/crypto/qce/regs-v5.h +++ b/drivers/crypto/qce/regs-v5.h @@ -203,7 +203,6 @@ #define AUTH_SIZE_SHIFT 9 #define AUTH_SIZE_MASK GENMASK(13, 9) -#define AUTH_SIZE_SHA1 0 #define AUTH_SIZE_SHA256 1 #define AUTH_SIZE_ENUM_1_BYTES 0 #define AUTH_SIZE_ENUM_2_BYTES 1 @@ -284,15 +283,12 @@ #define ENCR_KEY_SZ_SHIFT 3 #define ENCR_KEY_SZ_MASK GENMASK(5, 3) -#define ENCR_KEY_SZ_DES 0 -#define ENCR_KEY_SZ_3DES 1 #define ENCR_KEY_SZ_AES128 0 #define ENCR_KEY_SZ_AES256 2 #define ENCR_ALG_SHIFT 0 #define ENCR_ALG_MASK GENMASK(2, 0) #define ENCR_ALG_NONE 0 -#define ENCR_ALG_DES 1 #define ENCR_ALG_AES 2 #define ENCR_ALG_KASUMI 4 #define ENCR_ALG_SNOW_3G 5 diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index 508b4c18d2119..d7923c85a2bbc 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -25,10 +25,6 @@ struct qce_sha_saved_state { static LIST_HEAD(ahash_algs); -static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = { - SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0 -}; - static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 @@ -349,9 +345,7 @@ static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, return 0; } - if (digestsize == SHA1_DIGEST_SIZE) - alg_name = "sha1-qce"; - else if (digestsize == SHA256_DIGEST_SIZE) + if (digestsize == SHA256_DIGEST_SIZE) alg_name = "sha256-qce"; else return -EINVAL; @@ -412,15 +406,6 @@ struct qce_ahash_def { }; static const struct qce_ahash_def ahash_def[] = { - { - .flags = QCE_HASH_SHA1, - .name = "sha1", - .drv_name = "sha1-qce", - .digestsize = SHA1_DIGEST_SIZE, - .blocksize = SHA1_BLOCK_SIZE, - .statesize = sizeof(struct qce_sha_saved_state), - .std_iv = std_iv_sha1, - }, { .flags = QCE_HASH_SHA256, .name = "sha256", @@ -430,15 +415,6 @@ static const struct qce_ahash_def ahash_def[] = { .statesize = sizeof(struct qce_sha_saved_state), .std_iv = std_iv_sha256, }, - { - .flags = QCE_HASH_SHA1_HMAC, - .name = "hmac(sha1)", - .drv_name = "hmac-sha1-qce", - .digestsize = SHA1_DIGEST_SIZE, - .blocksize = SHA1_BLOCK_SIZE, - .statesize = sizeof(struct qce_sha_saved_state), - .std_iv = std_iv_sha1, - }, { .flags = QCE_HASH_SHA256_HMAC, .name = "hmac(sha256)", @@ -476,9 +452,7 @@ static int qce_ahash_register_one(const struct qce_ahash_def *def, alg->halg.digestsize = def->digestsize; alg->halg.statesize = def->statesize; - if (IS_SHA1(def->flags)) - tmpl->hash_zero = sha1_zero_message_hash; - else if (IS_SHA256(def->flags)) + if (IS_SHA256(def->flags)) tmpl->hash_zero = sha256_zero_message_hash; base = &alg->halg.base; diff --git a/drivers/crypto/qce/sha.h b/drivers/crypto/qce/sha.h index a22695361f165..cb822fc334dc1 100644 --- a/drivers/crypto/qce/sha.h +++ b/drivers/crypto/qce/sha.h @@ -7,7 +7,6 @@ #define _SHA_H_ #include -#include #include #include "common.h" diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 78fe3c3611cfe..06688af6f1549 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "cipher.h" @@ -209,51 +208,6 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, return ret; } -static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, - unsigned int keylen) -{ - struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); - int err; - - err = verify_skcipher_des_key(ablk, key); - if (err) - return err; - - ctx->enc_keylen = keylen; - memcpy(ctx->enc_key, key, keylen); - return 0; -} - -static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, - unsigned int keylen) -{ - struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); - u32 _key[6]; - int err; - - err = verify_skcipher_des3_key(ablk, key); - if (err) - return err; - - /* - * The crypto engine does not support any two keys - * being the same for triple des algorithms. The - * verify_skcipher_des3_key does not check for all the - * below conditions. Return -ENOKEY in case any two keys - * are the same. Revisit to see if a fallback cipher - * is needed to handle this condition. - */ - memcpy(_key, key, DES3_EDE_KEY_SIZE); - if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || - !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || - !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) - return -ENOKEY; - - ctx->enc_keylen = keylen; - memcpy(ctx->enc_key, key, keylen); - return 0; -} - static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -276,7 +230,7 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * ECB and CBC algorithms require message lengths to be * multiples of block size. */ - if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) + if (IS_CBC(rctx->flags)) if (!IS_ALIGNED(req->cryptlen, blocksize)) return -EINVAL; @@ -359,15 +313,6 @@ struct qce_skcipher_def { }; static const struct qce_skcipher_def skcipher_def[] = { - { - .flags = QCE_ALG_AES | QCE_MODE_ECB, - .name = "ecb(aes)", - .drv_name = "ecb-aes-qce", - .blocksize = AES_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - }, { .flags = QCE_ALG_AES | QCE_MODE_CBC, .name = "cbc(aes)", @@ -396,42 +341,6 @@ static const struct qce_skcipher_def skcipher_def[] = { .min_keysize = AES_MIN_KEY_SIZE * 2, .max_keysize = AES_MAX_KEY_SIZE * 2, }, - { - .flags = QCE_ALG_DES | QCE_MODE_ECB, - .name = "ecb(des)", - .drv_name = "ecb-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - }, - { - .flags = QCE_ALG_DES | QCE_MODE_CBC, - .name = "cbc(des)", - .drv_name = "cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_ECB, - .name = "ecb(des3_ede)", - .drv_name = "ecb-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC, - .name = "cbc(des3_ede)", - .drv_name = "cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - }, }; static int qce_skcipher_register_one(const struct qce_skcipher_def *def, @@ -455,9 +364,7 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, alg->ivsize = def->ivsize; alg->min_keysize = def->min_keysize; alg->max_keysize = def->max_keysize; - alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : - IS_DES(def->flags) ? qce_des_setkey : - qce_skcipher_setkey; + alg->setkey = qce_skcipher_setkey; alg->encrypt = qce_skcipher_encrypt; alg->decrypt = qce_skcipher_decrypt; From 07a521ddb8b35028c50f69ab4117451ada4dca87 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jun 2026 15:18:10 +0200 Subject: [PATCH 2/8] FROMLIST: crypto: qce - Fix HMAC self-test failures for empty messages BAM DMA cannot process zero-length transfers. For plain hashes this is handled by returning the precomputed hash of the empty message (tmpl->hash_zero), but for keyed HMAC the result depends on the key and cannot be a constant. As a result, hmac(sha256) produced an incorrect digest for an empty message and the crypto self-tests failed. Allocate a software fallback ahash for the HMAC transforms and use it to compute the digest whenever the message is empty (in both the .final() and .digest() paths). The fallback is allocated in a dedicated cra_init for the HMAC algorithms and is excluded from matching the crypto engine's own algorithm to avoid recursion. It is kept keyed in sync with the hardware transform in .setkey(). Cc: stable@vger.kernel.org Fixes: ec8f5d8f6f76 ("crypto: qce - Qualcomm crypto engine driver") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-2-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/sha.c | 84 +++++++++++++++++++++++++++++++++++++++- drivers/crypto/qce/sha.h | 1 + 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index d7923c85a2bbc..44659bf0dc891 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -270,6 +270,36 @@ static int qce_ahash_update(struct ahash_request *req) return qce->async_req_enqueue(tmpl->qce, &req->base); } +/* + * BAM DMA cannot handle zero-length transfers. For plain hashes the result of + * an empty message is a known constant (hash_zero), for keyed HMAC it depends + * on the key, so compute it with the software fallback. + */ +static int qce_ahash_hmac_zero(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct qce_sha_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); + struct ahash_request *subreq; + struct crypto_wait wait; + struct scatterlist sg; + int ret; + + subreq = ahash_request_alloc(ctx->fallback, GFP_ATOMIC); + if (!subreq) + return -ENOMEM; + + crypto_init_wait(&wait); + ahash_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &wait); + sg_init_one(&sg, NULL, 0); + ahash_request_set_crypt(subreq, &sg, req->result, 0); + + ret = crypto_wait_req(crypto_ahash_digest(subreq), &wait); + + ahash_request_free(subreq); + return ret; +} + static int qce_ahash_final(struct ahash_request *req) { struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req); @@ -280,6 +310,8 @@ static int qce_ahash_final(struct ahash_request *req) if (tmpl->hash_zero) memcpy(req->result, tmpl->hash_zero, tmpl->alg.ahash.halg.digestsize); + else if (IS_SHA_HMAC(rctx->flags)) + return qce_ahash_hmac_zero(req); return 0; } @@ -317,6 +349,8 @@ static int qce_ahash_digest(struct ahash_request *req) if (tmpl->hash_zero) memcpy(req->result, tmpl->hash_zero, tmpl->alg.ahash.halg.digestsize); + else if (IS_SHA_HMAC(rctx->flags)) + return qce_ahash_hmac_zero(req); return 0; } @@ -340,6 +374,17 @@ static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); memset(ctx->authkey, 0, sizeof(ctx->authkey)); + /* + * Keep the software fallback keyed in sync - it is used for empty + * messages, which the DMA engine cannot process. + */ + crypto_ahash_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK); + crypto_ahash_set_flags(ctx->fallback, + crypto_ahash_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); + ret = crypto_ahash_setkey(ctx->fallback, key, keylen); + if (ret) + return ret; + if (keylen <= blocksize) { memcpy(ctx->authkey, key, keylen); return 0; @@ -395,6 +440,36 @@ static int qce_ahash_cra_init(struct crypto_tfm *tfm) return 0; } +static int qce_ahash_hmac_cra_init(struct crypto_tfm *tfm) +{ + struct qce_sha_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_ahash *fallback; + int ret; + + ret = qce_ahash_cra_init(tfm); + if (ret) + return ret; + + /* + * The fallback is used to compute HMACs of empty messages, which the + * DMA engine cannot process. + */ + fallback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(fallback)) + return PTR_ERR(fallback); + + ctx->fallback = fallback; + return 0; +} + +static void qce_ahash_hmac_cra_exit(struct crypto_tfm *tfm) +{ + struct qce_sha_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto_free_ahash(ctx->fallback); +} + struct qce_ahash_def { unsigned long flags; const char *name; @@ -462,7 +537,14 @@ static int qce_ahash_register_one(const struct qce_ahash_def *def, base->cra_ctxsize = sizeof(struct qce_sha_ctx); base->cra_alignmask = 0; base->cra_module = THIS_MODULE; - base->cra_init = qce_ahash_cra_init; + + if (IS_SHA_HMAC(def->flags)) { + base->cra_flags |= CRYPTO_ALG_NEED_FALLBACK; + base->cra_init = qce_ahash_hmac_cra_init; + base->cra_exit = qce_ahash_hmac_cra_exit; + } else { + base->cra_init = qce_ahash_cra_init; + } strscpy(base->cra_name, def->name); strscpy(base->cra_driver_name, def->drv_name); diff --git a/drivers/crypto/qce/sha.h b/drivers/crypto/qce/sha.h index cb822fc334dc1..2fa173ff2b2ec 100644 --- a/drivers/crypto/qce/sha.h +++ b/drivers/crypto/qce/sha.h @@ -17,6 +17,7 @@ struct qce_sha_ctx { u8 authkey[QCE_SHA_MAX_BLOCKSIZE]; + struct crypto_ahash *fallback; }; /** From 493ea680e82737d24d2afd05a92fc3aea8c07a3c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jun 2026 15:18:11 +0200 Subject: [PATCH 3/8] FROMLIST: crypto: qce - Reject empty messages for AES-XTS XTS is not defined for an empty plaintext: it requires at least one full block of data. The driver treated a zero-length request as a successful no-op, so the crypto self-tests "unexpectedly succeeded" when -EINVAL was expected. Return -EINVAL for empty XTS requests while keeping the no-op behavior for the other ciphers, which the crypto engine simply cannot process due to its DMA not supporting zero-length transfers. Cc: stable@vger.kernel.org Fixes: f08789462255 ("crypto: qce - Return error for zero length messages") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-3-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/skcipher.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 06688af6f1549..b576d0ab6dced 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -223,8 +223,12 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; /* CE does not handle 0 length messages */ - if (!req->cryptlen) + if (!req->cryptlen) { + /* XTS requires at least one full block of data */ + if (IS_XTS(rctx->flags)) + return -EINVAL; return 0; + } /* * ECB and CBC algorithms require message lengths to be From be38a8a9566110fc60206b99c46b05c5f0f5f848 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 22 Jun 2026 15:18:12 +0200 Subject: [PATCH 4/8] FROMLIST: crypto: qce - Fix CTR-AES for partial block requests In CTR mode, the IV acts as the initial counter block. APer NIST SP 800-38A, after a CTR mode operation the next unused counter value is: IV_next = IV_in + ceil(cryptlen / AES_BLOCK_SIZE) The skcipher requires req->iv to hold this updated counter on completion, ensuring chained requests produce correct results. Referring to Crypto6.0 documentation, Section 2.2.5 says: "The count value increments automatically once per block of data (in AES, a block is 16 bytes) based on the value in the CRYPTO_ENCR_CNTR_MASK registers." QCE increments internal counter register once per full 16-byte block(for ctr-aes) is processed. In case of partial request length, the hardware uses the current counter to generate keystreams but does not increment the counter register afterwards. So the counter value written in CRYPTO_ENCR_CNTRn_IVn later once read by software is one less than the expected value. Crypto selftest framework capture this scenario with test vector 4 comprising of a 499-byte payload (31 full blocks + 3 partial bytes). Error: [ 5.606169] alg: skcipher: ctr-aes-qce encryption test failed (wrong output IV) on test vector 4, cfg="in-place (one sglist)" [ 5.606176] 00000000: e7 82 1d b8 53 11 ac 47 e2 7d 18 d6 71 0c a7 61 [ 5.606192] alg: self-tests for ctr(aes) using ctr-aes-qce failed (rc=-22) Expected iv_out: 0x62 (iv_in + 32) Obtained iv_out: 0x61 (iv_in + 31, partial block not counted) To fix this, just increase the counter value for partial block requests by 1 and for the full block size requests, don't take any action as expected value is already returned by the hardware. Cc: stable@vger.kernel.org Fixes: 3e806a12d10a ("crypto: qce - update the skcipher IV") Signed-off-by: Kuldeep Singh Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-4-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/skcipher.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index b576d0ab6dced..99f6c8b01a8b7 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -33,6 +33,7 @@ static void qce_skcipher_done(void *data) struct qce_device *qce = tmpl->qce; struct qce_result_dump *result_buf = qce->dma.result_buf; enum dma_data_direction dir_src, dir_dst; + unsigned int blocks; u32 status; int error; bool diff_dst; @@ -56,7 +57,21 @@ static void qce_skcipher_done(void *data) if (error < 0) dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); - memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + if (IS_CTR(rctx->flags)) { + /* + * QCE hardware does not increment the counter for a partial + * final block. Increment it in software so that iv_out + * reflects the correct next counter value expected by the CTR + * mode. + */ + blocks = DIV_ROUND_UP(rctx->cryptlen, AES_BLOCK_SIZE); + + while (blocks--) + crypto_inc(rctx->iv, rctx->ivsize); + } else { + memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + } + qce->async_req_done(tmpl->qce, error); } From 92b6fd9b7bd7d4d811b95d4c5c37a4f2b1da1080 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jun 2026 15:18:13 +0200 Subject: [PATCH 5/8] FROMLIST: crypto: qce - Use a fallback for AES-CTR with a partial final block ctr(aes) is registered with a block size of 1, so the crypto API hands the driver requests whose length is not a multiple of the AES block size. The crypto engine, however, stalls waiting for a full block of input in that case, leaving the operation incomplete and failing the request (and the crypto self-tests) with a hardware operation error. Route AES-CTR requests with a partial final block to the software fallback, which already handles the other cases the engine cannot. Cc: stable@vger.kernel.org Fixes: bb5c863b3d3c ("crypto: qce - fix ctr-aes-qce block, chunk sizes") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-5-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/skcipher.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 99f6c8b01a8b7..525170877ba1e 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -260,9 +260,12 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * AES-XTS request with len > QCE_SECTOR_SIZE and * is not a multiple of it.(Revisit this condition to check if it is * needed in all versions of CE) + * AES-CTR with a partial final block (the CE stalls waiting for a full + * block of input). */ if (IS_AES(rctx->flags) && ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || + (IS_CTR(rctx->flags) && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE)) || (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || (req->cryptlen > QCE_SECTOR_SIZE && req->cryptlen % QCE_SECTOR_SIZE))))) { From f8bbb4c6dfc12a21791e03aadf1c98618c073373 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 22 Jun 2026 15:18:14 +0200 Subject: [PATCH 6/8] FROMLIST: crypto: qce - Fix xts-aes-qce for weak keys The QCE hardware does not support AES XTS mode when key1 and key2 are equal. The driver was handling this by unconditionally rejecting the keys with -ENOKEY(-126), regardless of whether FIPS mode is active or the FORBID_WEAK_KEYS flag is set. [ 5.599170] alg: skcipher: xts-aes-qce setkey failed on test vector 0; expected_error=0, actual_error=-126, flags=0x1 [ 5.599184] alg: self-tests for xts(aes) using xts-aes-qce failed (rc=-126) In general for weak keys, - If FIPS mode is active or FORBID_WEAK_KEYS is set: return -EINVAL. - In non-FIPS mode, Accept the key and encrypt successfully. Since QCE was returning -ENOKEY for non-FIPS mode whereas the expectation is to encrypt content and return success, the selftest saw a mismatch and failed. There are two problems in QCE behavior: * -ENOKEY is returned instead of -EINVAL for the FIPS/weak-key rejection case. * key1 == key2 is rejected even in non-FIPS mode Fix xts-aes-qce behavior by using generic helper xts_verify_key() to reject keys early with -EINVAL for FIPS mode active(or FORBID_WEAK_KEYS set). For non-FIPS mode, since QCE hardware cannot accept the keys, use software fallback mechanism to encrypt the data. Cc: stable@vger.kernel.org Fixes: f0d078dd6c49 ("crypto: qce - Return unsupported if key1 and key 2 are same for AES XTS algorithm") Signed-off-by: Kuldeep Singh Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-6-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/cipher.h | 1 + drivers/crypto/qce/skcipher.c | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h index 850f257d00f3a..daea07551118d 100644 --- a/drivers/crypto/qce/cipher.h +++ b/drivers/crypto/qce/cipher.h @@ -14,6 +14,7 @@ struct qce_cipher_ctx { u8 enc_key[QCE_MAX_KEY_SIZE]; unsigned int enc_keylen; + bool use_fallback; struct crypto_skcipher *fallback; }; diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 525170877ba1e..286028b39f8fd 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "cipher.h" @@ -194,14 +195,17 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, if (!key || !keylen) return -EINVAL; - /* - * AES XTS key1 = key2 not supported by crypto engine. - * Revisit to request a fallback cipher in this case. - */ if (IS_XTS(flags)) { + ret = xts_verify_key(ablk, key, keylen); + if (ret) + return ret; __keylen = keylen >> 1; - if (!memcmp(key, key + __keylen, __keylen)) - return -ENOKEY; + /* + * QCE does not support key1 == key2 for XTS. + * Use fallback cipher in this case. + */ + ctx->use_fallback = !crypto_memneq(key, key + __keylen, + __keylen); } else { __keylen = keylen; } @@ -262,13 +266,15 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * needed in all versions of CE) * AES-CTR with a partial final block (the CE stalls waiting for a full * block of input). + * AES-XTS with key1 == key2 (not supported by the CE). */ if (IS_AES(rctx->flags) && ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || (IS_CTR(rctx->flags) && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE)) || (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || (req->cryptlen > QCE_SECTOR_SIZE && - req->cryptlen % QCE_SECTOR_SIZE))))) { + req->cryptlen % QCE_SECTOR_SIZE))) || + (IS_XTS(rctx->flags) && ctx->use_fallback))) { skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback); skcipher_request_set_callback(&rctx->fallback_req, req->base.flags, From e49989b545a7e495bbfb74ecbb57efac13d1fc5d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jun 2026 15:18:15 +0200 Subject: [PATCH 7/8] FROMLIST: crypto: qce - Use a fallback for CCM with a partial final block CCM builds on AES-CTR for encryption, and the crypto engine stalls on a partial final block just as it does for plain ctr(aes): a payload whose length is not a multiple of the AES block size leaves the operation incomplete and fails with a hardware operation error. This was caught by the ccm(aes) crypto self-tests. Force the software fallback for CCM requests whose message length is not block aligned, reusing the driver's existing need_fallback mechanism. Cc: stable@vger.kernel.org Fixes: 9363efb4181c ("crypto: qce - Add support for AEAD algorithms") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-7-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/aead.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 48ea7fb9a91e6..a6b2ebe36c7fb 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -514,6 +514,14 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) ctx->need_fallback = true; } + /* + * CCM uses AES-CTR internally and the CE stalls on a partial final + * block, so a payload that is not a multiple of the block size has to + * be handled by the fallback. + */ + if (IS_CCM(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, AES_BLOCK_SIZE)) + ctx->need_fallback = true; + /* If fallback is needed, schedule and exit */ if (ctx->need_fallback) { /* Reset need_fallback in case the same ctx is used for another transaction */ From 0952547d1f1530ed19cbb04cb5cc6cc9a4377feb Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jun 2026 15:18:16 +0200 Subject: [PATCH 8/8] FROMLIST: crypto: qce - Use fallback for CCM with a fragmented payload The crypto engine reliably processes CCM only when the message payload is a single contiguous buffer. The associated data is already linearized into a bounce buffer before being submitted, but when the payload itself is split across multiple scatterlist entries the engine stalls waiting for input and the request fails with a hardware operation error. This was uncovered by the crypto self-tests, which feed the algorithms randomly fragmented buffers. Detect a payload that spans more than one scatterlist entry (in either the source or the destination, skipping past the associated data) and route the request to the software fallback. Cc: stable@vger.kernel.org Fixes: 9363efb4181c ("crypto: qce - Add support for AEAD algorithms") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/linux-arm-msm/20260622-qce-fix-self-tests-v4-8-4f82ffa716c6@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/crypto/qce/aead.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index a6b2ebe36c7fb..37265bd141609 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -498,7 +498,8 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req); struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); struct qce_alg_template *tmpl = to_aead_tmpl(tfm); - unsigned int blocksize = crypto_aead_blocksize(tfm); + unsigned int blocksize = crypto_aead_blocksize(tfm), authsize; + struct scatterlist __sg[2], *msg_sg; rctx->flags = tmpl->alg_flags; rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; @@ -522,6 +523,27 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) if (IS_CCM(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, AES_BLOCK_SIZE)) ctx->need_fallback = true; + /* + * The CE reliably processes CCM only when the message payload is a + * single contiguous buffer. The associated data is linearized into a + * bounce buffer before being handed to the engine, but a fragmented + * payload makes the engine stall waiting for input, so route those + * requests to the fallback. + */ + if (IS_CCM(rctx->flags) && rctx->cryptlen) { + authsize = ctx->authsize; + + msg_sg = scatterwalk_ffwd(__sg, req->src, req->assoclen); + if (sg_nents_for_len(msg_sg, rctx->cryptlen + + (encrypt ? 0 : authsize)) > 1) + ctx->need_fallback = true; + + msg_sg = scatterwalk_ffwd(__sg, req->dst, req->assoclen); + if (sg_nents_for_len(msg_sg, rctx->cryptlen + + (encrypt ? authsize : 0)) > 1) + ctx->need_fallback = true; + } + /* If fallback is needed, schedule and exit */ if (ctx->need_fallback) { /* Reset need_fallback in case the same ctx is used for another transaction */