[PATCH 24/29] Add support for temporal key removal on association failure
Sai Pratyusha Magam
smagam at qti.qualcomm.com
Thu Dec 11 05:14:38 PST 2025
From: Kavita Kavita <kavita.kavita at oss.qualcomm.com>
This change adds logic to remove the configured temporal key (TK) for
Enhanced Privacy Protection Key Exchange (EPPKE) in the event of an
association request and/or response failure.
The removal is triggered immediately upon detection of association
request/response failure.
Signed-off-by: Kavita Kavita <kavita.kavita at oss.qualcomm.com>
---
wpa_supplicant/events.c | 14 ++++++++++++--
wpa_supplicant/sme.c | 22 +++++++++++++++++++++-
wpa_supplicant/wpa_supplicant.c | 18 ++++++++++--------
wpa_supplicant/wpa_supplicant_i.h | 2 +-
4 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index dc75efa46..19ea8d7d3 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -390,6 +390,16 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
}
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+
+#ifdef CONFIG_ENC_ASSOC
+ /* Clear configured keys and PTKSA */
+
+ if (wpa_s->ptksa &&
+ ptksa_cache_get(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE)) {
+ wpa_clear_keys(wpa_s, wpa_s->bssid, true);
+ ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE);
+ }
+#endif
bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
os_memset(wpa_s->bssid, 0, ETH_ALEN);
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
@@ -4384,7 +4394,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wpas_notify_bssid_changed(wpa_s);
if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) {
- wpa_clear_keys(wpa_s, bssid);
+ wpa_clear_keys(wpa_s, bssid, false);
}
if (wpa_supplicant_select_config(wpa_s, data) < 0) {
wpa_supplicant_deauthenticate(
@@ -4776,7 +4786,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_DPP2 */
if (wpa_supplicant_dynamic_keys(wpa_s)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys");
- wpa_clear_keys(wpa_s, wpa_s->bssid);
+ wpa_clear_keys(wpa_s, wpa_s->bssid, false);
}
wpa_supplicant_mark_disassoc(wpa_s);
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 2287dc6fb..fa81d6f96 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1327,7 +1327,7 @@ no_fils:
wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
eapol_sm_notify_portValid(wpa_s->eapol, false);
- wpa_clear_keys(wpa_s, bss->bssid);
+ wpa_clear_keys(wpa_s, bss->bssid, false);
wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
if (old_ssid != wpa_s->current_ssid)
wpas_notify_network_changed(wpa_s);
@@ -2993,6 +2993,17 @@ mscs_fail:
wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
NULL);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+#ifdef CONFIG_ENC_ASSOC
+ /* Clear configured keys and PTKSA */
+
+ if (wpa_s->ptksa && ptksa_cache_get(wpa_s->ptksa,
+ wpa_s->bssid,
+ WPA_CIPHER_NONE)) {
+ wpa_clear_keys(wpa_s, wpa_s->bssid, true);
+ ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid,
+ WPA_CIPHER_NONE);
+ }
+#endif
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
}
return;
@@ -3055,6 +3066,15 @@ static void sme_deauth(struct wpa_supplicant *wpa_s, const u8 **link_bssids)
wpas_connection_failed(wpa_s, wpa_s->pending_bssid, link_bssids);
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+#ifdef CONFIG_ENC_ASSOC
+ /* Clear configured keys and PTKSA */
+
+ if (wpa_s->ptksa &&
+ ptksa_cache_get(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE)) {
+ wpa_clear_keys(wpa_s, wpa_s->bssid, true);
+ ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE);
+ }
+#endif
os_memset(wpa_s->bssid, 0, ETH_ALEN);
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
if (bssid_changed)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index c81df7da4..65dca0f72 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -882,11 +882,13 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
* wpa_clear_keys - Clear keys configured for the driver
* @wpa_s: Pointer to wpa_supplicant data
* @addr: Previously used BSSID or %NULL if not available
+ * @preassoc: Indicates that the keys are used before association and need
+ * to be removed if it is set to true.
*
* This function clears the encryption keys that has been previously configured
* for the driver.
*/
-void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
+void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr, bool preassoc)
{
int i, max = 6;
@@ -895,7 +897,7 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
if (wpa_s->keys_cleared & BIT(i))
continue;
wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
- NULL, 0, KEY_FLAG_GROUP, false);
+ NULL, 0, KEY_FLAG_GROUP, preassoc);
}
/* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
@@ -903,11 +905,11 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
if (!(wpa_s->keys_cleared & BIT(0)))
wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE,
- false);
+ preassoc);
if (!(wpa_s->keys_cleared & BIT(15)))
wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, addr, 1, 0,
NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE,
- false);
+ preassoc);
/* MLME-SETPROTECTION.request(None) */
wpa_drv_mlme_setprotection(
wpa_s, addr,
@@ -4608,7 +4610,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_supplicant_cancel_scan(wpa_s);
- wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
+ wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL, false);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
cipher_group = wpa_s->group_cipher;
@@ -5026,7 +5028,7 @@ static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
wpa_s->ml_connect_probe_ssid = NULL;
wpa_s->ml_connect_probe_bss = NULL;
wpas_connect_work_done(wpa_s);
- wpa_clear_keys(wpa_s, addr);
+ wpa_clear_keys(wpa_s, addr, false);
old_ssid = wpa_s->current_ssid;
wpa_supplicant_mark_disassoc(wpa_s);
wpa_sm_set_config(wpa_s->wpa, NULL);
@@ -6373,7 +6375,7 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
"Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
}
- wpa_clear_keys(wpa_s, NULL);
+ wpa_clear_keys(wpa_s, NULL, false);
/* Make sure that TKIP countermeasures are not left enabled (could
* happen if wpa_supplicant is killed during countermeasures. */
@@ -8101,7 +8103,7 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
wpa_drv_set_countermeasures(wpa_s, 0);
- wpa_clear_keys(wpa_s, NULL);
+ wpa_clear_keys(wpa_s, NULL, false);
} else {
wpa_msg(wpa_s, MSG_INFO,
"Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index a2497fc5b..48a93abc2 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1685,7 +1685,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s);
-void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr);
+void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr, bool preassoc);
void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
int sec, int usec);
void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff);
--
2.34.1
More information about the Hostap
mailing list