@@ -3592,6 +3592,75 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
35923592 ssl -> heap , ssl -> devId , ssl -> rng , ssl -> options .tls1_3 );
35933593 }
35943594
3595+ /* Zero the TLS-layer staging key buffers once the CryptoCB callback
3596+ * has imported the key into a Secure Element.
3597+ *
3598+ * Convention: after a successful wc_AesSetKey / wc_AesGcmSetKey where
3599+ * the CryptoCB handled the key import, the callback leaves
3600+ * aes->devCtx != NULL and the software key schedule (aes->key,
3601+ * aes->devKey, aes->gcm.H / aes->gcm.M0) is NOT populated. The TLS
3602+ * layer may therefore destroy its staging copy of the traffic key.
3603+ *
3604+ * Only the key buffers (client_write_key / server_write_key) are
3605+ * zeroed. The static IVs (client_write_IV / server_write_IV) and
3606+ * the AEAD implicit-IV copies (aead_{enc,dec}_imp_IV) are NOT
3607+ * zeroed: BuildTls13Nonce() in tls13.c reads keys->aead_*_imp_IV on
3608+ * every AEAD record to construct the per-record nonce
3609+ * (nonce = static_iv XOR seq_num, RFC 8446 Section 5.3). Zeroing
3610+ * them would break the record path or, if applied symmetrically on
3611+ * both peers, silently degenerate the nonce to the bare sequence
3612+ * number and break interop with any unpatched peer. The static_iv
3613+ * is not a confidentiality-critical secret in the same sense as
3614+ * the traffic key; losing it does not compromise plaintext.
3615+ *
3616+ * Scope:
3617+ * - TLS 1.3 only. TLS 1.2 additionally reads
3618+ * keys->{client,server}_write_key for rehandshake/secure
3619+ * renegotiation flows.
3620+ * - Non-DTLS. Dtls13EpochCopyKeys (called from Dtls13NewEpoch)
3621+ * references keys->*_write_key for epoch switching; DTLS 1.3
3622+ * needs separate analysis.
3623+ * - Non-QUIC. QUIC traffic secrets live outside these buffers
3624+ * but the interaction with stack-installed QUIC handlers has
3625+ * not been audited; exclude until it is.
3626+ *
3627+ * When called with ENCRYPT_SIDE_ONLY or DECRYPT_SIDE_ONLY, only the
3628+ * buffer consumed by this call is zeroed; the complementary buffer
3629+ * is written in a later SetKeysSide() from its own DeriveTls13Keys()
3630+ * and StoreKeys() pair (StoreKeys gates on PROVISION_CLIENT /
3631+ * PROVISION_SERVER so only the provisioned side is written).
3632+ *
3633+ * Ordering: this block must run AFTER SetKeys() (so offload has
3634+ * happened) and BEFORE Dtls13SetRecordNumberKeys() /
3635+ * wolfSSL_quic_keys_active() below, in case a future refactor in
3636+ * either starts reading keys->*_write_key. The DTLS and QUIC gates
3637+ * in this block mean neither currently executes on the same ssl,
3638+ * but keep the order explicit. */
3639+ #if defined(WOLF_CRYPTO_CB ) && defined(WOLF_CRYPTO_CB_AES_SETKEY )
3640+ if (ret == 0 && ssl -> options .tls1_3 && !ssl -> options .dtls
3641+ && !WOLFSSL_IS_QUIC (ssl )) {
3642+ int encOffloaded = (wc_encrypt != NULL && wc_encrypt -> aes != NULL &&
3643+ wc_encrypt -> aes -> devCtx != NULL );
3644+ int decOffloaded = (wc_decrypt != NULL && wc_decrypt -> aes != NULL &&
3645+ wc_decrypt -> aes -> devCtx != NULL );
3646+
3647+ if (encOffloaded || decOffloaded ) {
3648+ if (ssl -> options .side == WOLFSSL_CLIENT_END ) {
3649+ if (encOffloaded )
3650+ ForceZero (keys -> client_write_key , ssl -> specs .key_size );
3651+ if (decOffloaded )
3652+ ForceZero (keys -> server_write_key , ssl -> specs .key_size );
3653+ }
3654+ else {
3655+ if (encOffloaded )
3656+ ForceZero (keys -> server_write_key , ssl -> specs .key_size );
3657+ if (decOffloaded )
3658+ ForceZero (keys -> client_write_key , ssl -> specs .key_size );
3659+ }
3660+ }
3661+ }
3662+ #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_AES_SETKEY */
3663+
35953664#ifdef WOLFSSL_DTLS13
35963665 if (ret == 0 && ssl -> options .dtls && IsAtLeastTLSv1_3 (ssl -> version ))
35973666 ret = Dtls13SetRecordNumberKeys (ssl , side );
0 commit comments