@@ -132,6 +132,14 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
132132 }
133133#endif
134134
135+ /* TLS-safe default:
136+ * When TLS is enabled, AES-GCM must always retain software fallback.
137+ * CryptoCB may accelerate, but must not remove fallback implicitly.
138+ */
139+ #if !defined(NO_TLS)
140+ #define WOLFSSL_AES_GCM_TLS_SAFE
141+ #endif
142+
135143/* Define AES implementation includes and functions */
136144#if defined(STM32_CRYPTO)
137145 /* STM32F2/F4/F7/L4/L5/H7/WB55 hardware AES support for ECB, CBC, CTR and GCM modes */
@@ -4366,31 +4374,37 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
43664374 ret = wc_CryptoCb_AesSetKey(aes, userKey, keylen, &capabilities);
43674375
43684376 if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
4369- /* Callback handled it (success or error) */
4370- if (ret == 0) {
4371- /* Check if callback declared full GCM offload capability.
4372- * If NOT, fall through to software path - we don't support
4373- * key-import-only mode for GCM (need key for table generation). */
4374- if (!(capabilities & WC_CRYPTOCB_AES_GCM)) {
4375- /* Fall through to software path */
4376- goto cryptocb_aes_setkey_sw_fallback;
4377- }
4378-
4379- /* Full GCM offload mode */
4377+ if (ret != 0) {
4378+ /* real error from callback */
4379+ return ret;
4380+ }
4381+
4382+ /* Callback handled SetKey */
4383+ if (capabilities & WC_CRYPTOCB_AES_GCM) {
43804384 aes->gcmCryptoCbOffload = 1;
43814385 aes->keylen = (int)keylen;
4382-
4386+
4387+ #ifdef WOLFSSL_AES_GCM_TLS_SAFE
4388+ /* TLS-safe: DO NOT return
4389+ * We must still set up software AES key for fallback.
4390+ */
4391+ goto cryptocb_aes_setkey_fallback;
4392+ #else
4393+ /* Cryptonly build: full offload allowed */
43834394 /* Set IV if provided */
43844395 if (iv != NULL) {
43854396 XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE);
43864397 } else {
43874398 XMEMSET(aes->reg, 0, WC_AES_BLOCK_SIZE);
43884399 }
4400+ return 0;
4401+ #endif
43894402 }
4390- return ret;
4403+
4404+ /* Key-import-only or partial support -> fallback */
43914405 }
4392- /* CRYPTOCB_UNAVAILABLE: fall through to software path */
4393- cryptocb_aes_setkey_sw_fallback : (void)0;
4406+ /* Either UNAVAILABLE or TLS-safe fallback */
4407+ cryptocb_aes_setkey_fallback : (void)0;
43944408 #else
43954409 /* Standard CryptoCB path - copy key to devKey */
43964410 if (keylen > sizeof(aes->devKey)) {
@@ -4830,31 +4844,37 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
48304844 ret = wc_CryptoCb_AesSetKey(aes, userKey, keylen, &capabilities);
48314845
48324846 if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
4833- /* Callback handled it (success or error) */
4834- if (ret == 0) {
4835- /* Check if callback declared full GCM offload capability.
4836- * If NOT, fall through to software path - we don't support
4837- * key-import-only mode for GCM (need key for table generation). */
4838- if (!(capabilities & WC_CRYPTOCB_AES_GCM)) {
4839- /* Fall through to software path */
4840- goto cryptocb_aes_setkey_sw_fallback2;
4841- }
4842-
4843- /* Full GCM offload mode */
4847+ if (ret != 0) {
4848+ /* real error from callback */
4849+ return ret;
4850+ }
4851+
4852+ /* Callback handled SetKey */
4853+ if (capabilities & WC_CRYPTOCB_AES_GCM) {
48444854 aes->gcmCryptoCbOffload = 1;
48454855 aes->keylen = (int)keylen;
4846-
4856+
4857+ #ifdef WOLFSSL_AES_GCM_TLS_SAFE
4858+ /* TLS-safe: DO NOT return
4859+ * We must still set up software AES key for fallback.
4860+ */
4861+ goto cryptocb_aes_setkey_fallback2;
4862+ #else
4863+ /* Cryptonly build: full offload allowed */
48474864 /* Set IV if provided */
48484865 if (iv != NULL) {
48494866 XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE);
48504867 } else {
48514868 XMEMSET(aes->reg, 0, WC_AES_BLOCK_SIZE);
48524869 }
4870+ return 0;
4871+ #endif
48534872 }
4854- return ret;
4873+
4874+ /* Key-import-only or partial support -> fallback */
48554875 }
4856- /* CRYPTOCB_UNAVAILABLE: fall through to software path */
4857- cryptocb_aes_setkey_sw_fallback2 : (void)0;
4876+ /* Either UNAVAILABLE or TLS-safe fallback */
4877+ cryptocb_aes_setkey_fallback2 : (void)0;
48584878 #else
48594879 /* Copy key to devKey for standard CryptoCB path */
48604880 XMEMCPY(aes->devKey, userKey, keylen);
@@ -7533,24 +7553,16 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
75337553#if !defined(FREESCALE_LTC_AES_GCM) && !defined(WOLFSSL_PSOC6_CRYPTO)
75347554 if (ret == 0) {
75357555#ifdef WOLF_CRYPTO_CB_AES_SETKEY
7536- /* CRITICAL FIX: Only skip H table if callback EXPLICITLY declared
7537- * full AES-GCM offload capability via WC_CRYPTOCB_AES_GCM flag.
7538- *
7539- * Checking devCtx alone is NOT sufficient because:
7540- * - Callback may only support key import, not GCM operations
7541- * - If we skip tables and GCM ops return UNAVAILABLE, software fallback fails
7542- * - This was a critical bug in the original implementation
7543- *
7544- * The callback must explicitly opt-in to GCM offload by setting the
7545- * WC_CRYPTOCB_AES_GCM capability flag during SetKey. Only then do we
7546- * skip table generation.
7547- */
7548- if (aes->devId != INVALID_DEVID &&
7556+ #ifdef WOLFSSL_AES_GCM_TLS_SAFE
7557+ /* TLS-safe: always generate H for fallback */
7558+ #else
7559+ if (aes->devId != INVALID_DEVID &&
75497560 aes->devCtx != NULL &&
75507561 aes->gcmCryptoCbOffload) {
7551- /* H table not needed - callback confirmed full GCM offload */
7562+ /* full offload allowed: skip H */
75527563 }
75537564 else
7565+ #endif
75547566#endif
75557567 {
75567568 VECTOR_REGISTERS_PUSH;
@@ -7561,14 +7573,16 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
75617573 }
75627574 if (ret == 0) {
75637575#ifdef WOLF_CRYPTO_CB_AES_SETKEY
7564- /* CRITICAL FIX: Same logic as H table.
7565- * Only skip M0 generation if callback explicitly declared full GCM offload. */
7566- if (aes->devId != INVALID_DEVID &&
7576+ #ifdef WOLFSSL_AES_GCM_TLS_SAFE
7577+ /* TLS-safe: always generate M0 for fallback */
7578+ #else
7579+ if (aes->devId != INVALID_DEVID &&
75677580 aes->devCtx != NULL &&
75687581 aes->gcmCryptoCbOffload) {
7569- /* M0 table not needed - callback confirmed full GCM offload */
7582+ /* full offload allowed: skip M0 */
75707583 }
75717584 else
7585+ #endif
75727586#endif
75737587 {
75747588#if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
@@ -7610,14 +7624,16 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
76107624#ifdef WOLF_CRYPTO_CB
76117625 if (aes->devId != INVALID_DEVID) {
76127626 #ifdef WOLF_CRYPTO_CB_AES_SETKEY
7627+ #if !defined(WOLFSSL_AES_GCM_TLS_SAFE)
76137628 /* In CryptoCB key import mode, key is in SE - devKey not used */
76147629 if (aes->devCtx != NULL) {
76157630 /* Skip - key handled by CryptoCB */
76167631 }
76177632 else
7633+ #endif
76187634 #endif
76197635 {
7620- /* Copy key to devKey for standard CryptoCB path */
7636+ /* Copy key to devKey for standard CryptoCB path or TLS-safe fallback */
76217637 XMEMCPY(aes->devKey, key, len);
76227638 }
76237639 }
0 commit comments