[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