[PATCH 23/29] sme: Add support to install temporal key for EPPKE Authentication Protocol

Sai Pratyusha Magam smagam at qti.qualcomm.com
Thu Dec 11 05:14:37 PST 2025


From: Kavita Kavita <kavita.kavita at oss.qualcomm.com>

Add support to install the temporal key for Enhanced Privacy Protection
Key Exchange (EPPKE) as specified in section 12.16.9 of
IEEE P802.11bi/D2.0 after authentication completes.

This commit add support to configure temporal key TK with the driver
immediately after authentication completes.

Signed-off-by: Kavita Kavita <kavita.kavita at oss.qualcomm.com>
---
 src/drivers/driver.h            |  5 +++++
 src/drivers/driver_nl80211.c    |  6 ++++++
 wpa_supplicant/ctrl_iface.c     | 20 ++++++++++----------
 wpa_supplicant/driver_i.h       |  3 ++-
 wpa_supplicant/events.c         |  2 +-
 wpa_supplicant/ibss_rsn.c       |  6 +++---
 wpa_supplicant/mesh_mpm.c       |  6 +++---
 wpa_supplicant/mesh_rsn.c       |  7 ++++---
 wpa_supplicant/sme.c            |  9 +++++++++
 wpa_supplicant/wpa_supplicant.c | 12 +++++++-----
 wpa_supplicant/wpas_glue.c      |  9 +++++----
 11 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2bbe7f621..759f9f62d 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2096,6 +2096,11 @@ struct wpa_driver_set_key_params {
 	 *
 	 * Set to a valid Link ID (0-14) when applicable, otherwise -1. */
 	int link_id;
+
+	/**
+	 * preassoc_key - Indicate key is for pre-association use
+	 */
+	bool preassoc_key;
 };
 
 enum wpa_driver_if_type {
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index a4f24fea5..fd19a1e65 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3771,6 +3771,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss,
 	int vlan_id = params->vlan_id;
 	enum key_flag key_flag = params->key_flag;
 	int link_id = params->link_id;
+	bool preassoc_key = params->preassoc_key;
 
 	/* Ignore for P2P Device */
 	if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
@@ -3903,6 +3904,10 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss,
 		if (key_flag & KEY_FLAG_DEFAULT)
 			skip_set_key = 0;
 	}
+
+	if (preassoc_key)
+		nla_put_flag(msg, NL80211_ATTR_KEY_PREASSOC);
+
 	if (nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) ||
 	    nla_put_nested(msg, NL80211_ATTR_KEY, key_msg))
 		goto fail;
@@ -3923,6 +3928,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss,
 	}
 
 	ret = send_and_recv_cmd(drv, msg);
+
 	if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
 		ret = 0;
 	if (ret)
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 750b476b9..feadfd4af 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -6021,23 +6021,23 @@ static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
 	/* MLME-DELETEKEYS.request */
 	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
+			0, KEY_FLAG_GROUP, false);
 	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
+			0, KEY_FLAG_GROUP, false);
 	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
+			0, KEY_FLAG_GROUP, false);
 	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
+			0, KEY_FLAG_GROUP, false);
 	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
+			0, KEY_FLAG_GROUP, false);
 	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
+			0, KEY_FLAG_GROUP, false);
 
 	wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0,
-			NULL, 0, KEY_FLAG_PAIRWISE);
+			NULL, 0, KEY_FLAG_PAIRWISE, false);
 	if (wpa_sm_ext_key_id(wpa_s->wpa))
 		wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 1, 0,
-				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
+				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE, false);
 	/* MLME-SETPROTECTION.request(None) */
 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
@@ -10498,7 +10498,7 @@ static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 	if (wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
 			    wpa_s->last_tk_key_idx, 1, zero, 6,
 			    zero, wpa_s->last_tk_len,
-			    KEY_FLAG_PAIRWISE_RX_TX) < 0)
+			    KEY_FLAG_PAIRWISE_RX_TX, false) < 0)
 		return -1;
 
 	/* Set the previously configured key to reset its TSC/RSC */
@@ -10506,7 +10506,7 @@ static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 			       wpa_s->last_tk_addr,
 			       wpa_s->last_tk_key_idx, 1, zero, 6,
 			       wpa_s->last_tk, wpa_s->last_tk_len,
-			       KEY_FLAG_PAIRWISE_RX_TX);
+			       KEY_FLAG_PAIRWISE_RX_TX, false);
 }
 
 
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index f259ac36f..4263ec307 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -162,7 +162,7 @@ static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, int link_id,
 				  int key_idx, int set_tx,
 				  const u8 *seq, size_t seq_len,
 				  const u8 *key, size_t key_len,
-				  enum key_flag key_flag)
+				  enum key_flag key_flag, bool preassoc_key)
 {
 	struct wpa_driver_set_key_params params;
 
@@ -178,6 +178,7 @@ static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, int link_id,
 	params.key_len = key_len;
 	params.key_flag = key_flag;
 	params.link_id = link_id;
+	params.preassoc_key = preassoc_key;
 
 	if (alg != WPA_ALG_NONE) {
 		/* keyidx = 1 can be either a broadcast or--with
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 7ea1199cb..dc75efa46 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3304,7 +3304,7 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
 		if (wpa_s->conf->key_mgmt_offload &&
 		    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD) &&
 		    wpa_drv_set_key(wpa_s, -1, 0, NULL, 0, 0, NULL, 0,
-				    ssid->psk, PMK_LEN, KEY_FLAG_PMK))
+				    ssid->psk, PMK_LEN, KEY_FLAG_PMK, false))
 			wpa_dbg(wpa_s, MSG_ERROR,
 				"WPA: Cannot set PMK for key management offload");
 	}
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 06228d0ef..cfa50a3d3 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -180,7 +180,7 @@ static int supp_set_key(void *ctx, int link_id, enum wpa_alg alg,
 		addr = peer->addr;
 	return wpa_drv_set_key(peer->ibss_rsn->wpa_s, link_id, alg, addr,
 			       key_idx, set_tx, seq, seq_len, key, key_len,
-			       key_flag);
+			       key_flag, false);
 }
 
 
@@ -366,7 +366,7 @@ static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 	}
 
 	return wpa_drv_set_key(ibss_rsn->wpa_s, -1, alg, addr, idx,
-			       1, seq, 6, key, key_len, key_flag);
+			       1, seq, 6, key, key_len, key_flag, false);
 }
 
 
@@ -882,7 +882,7 @@ static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
 		wpa_printf(MSG_DEBUG, "RSN: Clear pairwise key for peer "
 			   MACSTR, MAC2STR(addr));
 		wpa_drv_set_key(ibss_rsn->wpa_s, -1, WPA_ALG_NONE, addr, 0, 0,
-				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE);
+				NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE, false);
 	}
 
 	if (peer &&
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index b2fc1271e..e23128367 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -921,7 +921,7 @@ static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
 				wpa_cipher_to_alg(conf->pairwise_cipher),
 				sta->addr, 0, 0, seq, sizeof(seq),
 				sta->mtk, sta->mtk_len,
-				KEY_FLAG_PAIRWISE_RX_TX);
+				KEY_FLAG_PAIRWISE_RX_TX, false);
 
 		wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK Key RSC",
 				sta->mgtk_rsc, sizeof(sta->mgtk_rsc));
@@ -932,7 +932,7 @@ static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
 				sta->addr, sta->mgtk_key_id, 0,
 				sta->mgtk_rsc, sizeof(sta->mgtk_rsc),
 				sta->mgtk, sta->mgtk_len,
-				KEY_FLAG_GROUP_RX);
+				KEY_FLAG_GROUP_RX, false);
 
 		if (sta->igtk_len) {
 			wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK Key RSC",
@@ -945,7 +945,7 @@ static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
 				sta->addr, sta->igtk_key_id, 0,
 				sta->igtk_rsc, sizeof(sta->igtk_rsc),
 				sta->igtk, sta->igtk_len,
-				KEY_FLAG_GROUP_RX);
+				KEY_FLAG_GROUP_RX, false);
 		}
 	}
 
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 463137353..a3ae286c5 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -119,7 +119,7 @@ static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 	wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len);
 
 	return wpa_drv_set_key(mesh_rsn->wpa_s, -1, alg, addr, idx,
-			       1, seq, 6, key, key_len, key_flag);
+			       1, seq, 6, key, key_len, key_flag, false);
 }
 
 
@@ -217,7 +217,7 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 				broadcast_ether_addr,
 				rsn->igtk_key_id, 1,
 				seq, sizeof(seq), rsn->igtk, rsn->igtk_len,
-				KEY_FLAG_GROUP_TX_DEFAULT);
+				KEY_FLAG_GROUP_TX_DEFAULT, false);
 	}
 
 	/* group privacy / data frames */
@@ -226,7 +226,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 	wpa_drv_set_key(rsn->wpa_s, -1, wpa_cipher_to_alg(rsn->group_cipher),
 			broadcast_ether_addr,
 			rsn->mgtk_key_id, 1, seq, sizeof(seq),
-			rsn->mgtk, rsn->mgtk_len, KEY_FLAG_GROUP_TX_DEFAULT);
+			rsn->mgtk, rsn->mgtk_len, KEY_FLAG_GROUP_TX_DEFAULT,
+			false);
 
 	return 0;
 }
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index b1ce116af..2287dc6fb 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -2244,6 +2244,8 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
 	if (data->auth.auth_type == WLAN_AUTH_EPPKE) {
 		struct pasn_data *pasn = &wpa_s->pasn;
 		struct wpa_pasn_params_data pasn_params;
+		enum wpa_alg alg;
+		u8 zero[WPA_TK_MAX_LEN] = {0};
 		int res;
 
 		res = wpas_parse_pasn_frame(pasn, data->auth.auth_type,
@@ -2269,6 +2271,13 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
 
 		sme_send_authentication(wpa_s, wpa_s->current_bss,
 					wpa_s->current_ssid, 0);
+
+		alg = wpa_cipher_to_alg(pasn_get_cipher(pasn));
+
+		wpa_drv_set_key(wpa_s, -1, alg, pasn->peer_addr, 0, 1,
+				zero, 6, pasn_get_ptk(pasn)->tk,
+				pasn_get_ptk(pasn)->tk_len,
+				KEY_FLAG_PAIRWISE_RX_TX, true);
 	}
 #endif /* CONFIG_ENC_ASSOC */
 #ifdef CONFIG_SAE
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6b415c0be..c81df7da4 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -153,7 +153,7 @@ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 				ssid->wep_key[i], ssid->wep_key_len[i],
 				i == ssid->wep_tx_keyidx ?
 				KEY_FLAG_GROUP_RX_TX_DEFAULT :
-				KEY_FLAG_GROUP_RX_TX);
+				KEY_FLAG_GROUP_RX_TX, false);
 	}
 
 	return set;
@@ -213,7 +213,7 @@ int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
 	 * and RX from each STA.. */
 
 	ret = wpa_drv_set_key(wpa_s, -1, alg, NULL, 0, 1, seq, 6, key, keylen,
-			      KEY_FLAG_GROUP_RX_TX_DEFAULT);
+			      KEY_FLAG_GROUP_RX_TX_DEFAULT, false);
 	os_memset(key, 0, sizeof(key));
 	return ret;
 }
@@ -895,17 +895,19 @@ 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);
+				NULL, 0, KEY_FLAG_GROUP, false);
 	}
 	/* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
 	if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
 	    !is_zero_ether_addr(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);
+					NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE,
+					false);
 		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);
+					NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE,
+					false);
 		/* MLME-SETPROTECTION.request(None) */
 		wpa_drv_mlme_setprotection(
 			wpa_s, addr,
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 247dc1d7d..b0a70e8a0 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -261,7 +261,7 @@ static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
 			       unicast ? wpa_s->bssid : NULL,
 			       keyidx, unicast, NULL, 0, key, keylen,
 			       unicast ? KEY_FLAG_PAIRWISE_RX_TX :
-			       KEY_FLAG_GROUP_RX_TX_DEFAULT);
+			       KEY_FLAG_GROUP_RX_TX_DEFAULT, false);
 }
 #endif /* CONFIG_WEP */
 
@@ -376,7 +376,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
 			"handshake", pmk, pmk_len);
 
 	if (wpa_drv_set_key(wpa_s, -1, 0, NULL, 0, 0, NULL, 0, pmk,
-			    pmk_len, KEY_FLAG_PMK)) {
+			    pmk_len, KEY_FLAG_PMK, false)) {
 		wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
 	}
 
@@ -586,7 +586,7 @@ static int wpa_supplicant_set_key(void *_wpa_s, int link_id, enum wpa_alg alg,
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	ret = wpa_drv_set_key(wpa_s, link_id, alg, addr, key_idx, set_tx, seq,
-			      seq_len, key, key_len, key_flag);
+			      seq_len, key, key_len, key_flag, false);
 	if (ret == 0 && (key_idx == 6 || key_idx == 7) &&
 	    alg != WPA_ALG_NONE && key_len > 0)
 		wpa_s->bigtk_set = true;
@@ -1280,7 +1280,8 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
 	if (wpa_s->conf->key_mgmt_offload &&
 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
 		return wpa_drv_set_key(wpa_s, -1, 0, NULL, 0, 0,
-				       NULL, 0, pmk, pmk_len, KEY_FLAG_PMK);
+				       NULL, 0, pmk, pmk_len, KEY_FLAG_PMK,
+				       false);
 	else
 		return 0;
 }
-- 
2.34.1




More information about the Hostap mailing list