[RFC 14/30] WPA: Handle SMD configuration in WPA SM

Ilan Peer ilan.peer at intel.com
Wed Oct 21 06:43:32 PDT 2026


- Indicate support for SMD in RSNXE when supported.
- Configure SMD_KDK derivation in PMK to PTK derivation,
  when SMD is supported and the PTK mode is per-AP MLD.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/rsn_supp/wpa.c    | 51 ++++++++++++++++++++++++++++++++++++++++---
 src/rsn_supp/wpa_ie.c |  3 +++
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index ab0a87fcfc15..980d659c3a4e 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -749,12 +749,31 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
 }
 
 
+static bool wpa_sm_is_smd_per_ap_mld_ptk(struct wpa_sm *sm)
+{
+	const struct ieee80211_smd_info *smd;
+
+	if (!sm->smd || !sm->ap_smd_info)
+		return false;
+
+	if (!ieee802_11_sec_prof_rsnx_capab(sm->ap_security_profile,
+					    WLAN_RSNX_CAPAB_SMD))
+		return false;
+
+	smd = (const struct ieee80211_smd_info *)sm->ap_smd_info;
+	return !!(smd->smd_capabilities & SMD_CAPA_PER_AP_MLD_PTK_MODE);
+}
+
+
 static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
 			  const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
 {
 	int ret;
 	const u8 *z = NULL, *ap_rsnxe;
-	size_t z_len = 0, kdk_len, ap_rsnxe_len;
+	const u8 *xxkey = sm->pmk;
+	size_t xxkey_len = sm->pmk_len;
+	u8 z_buf[WPA_MAX_Z_LEN];
+	size_t z_len = 0, kdk_len, ap_rsnxe_len, smd_kdk_len;
 	int akmp;
 
 	ap_rsnxe = wpa_sm_get_ap_rsnxe(sm, &ap_rsnxe_len);
@@ -771,6 +790,17 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
 	}
 #endif /* CONFIG_DPP2 */
 
+	if (sm->smd && sm->ap_smd_info) {
+		const struct ieee80211_smd_info *smd;
+
+		smd = (const struct ieee80211_smd_info *) sm->ap_smd_info;
+		if (z && z_len)
+			os_memcpy(z_buf, z, z_len);
+		os_memcpy(z_buf + z_len, smd->smd_id, ETH_ALEN);
+		z_len += ETH_ALEN;
+		z = z_buf;
+	}
+
 	akmp = sm->key_mgmt;
 #ifdef CONFIG_OWE
 	if (sm->owe_ptk_workaround && akmp == WPA_KEY_MGMT_OWE &&
@@ -788,11 +818,26 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
 	else
 		kdk_len = 0;
 
-	ret = wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
+	if (wpa_sm_is_smd_per_ap_mld_ptk(sm))
+		smd_kdk_len = sm->pmk_len;
+	else
+		smd_kdk_len = 0;
+
+	/*
+	 * The SMD_KDK is not rederived on PTK rekeying, but it is used instead
+	 * of the PMK. See section 37.16.4.2 in Draft IEEE P802.11bn/D2.0.
+	 */
+	if (smd_kdk_len && sm->ptk.smd_kdk_len) {
+		xxkey = sm->ptk.smd_kdk;
+		xxkey_len = sm->ptk.smd_kdk_len;
+		smd_kdk_len = 0;
+	}
+
+	ret = wpa_pmk_to_ptk(xxkey, xxkey_len, "Pairwise key expansion",
 			     sm->own_addr, wpa_sm_get_auth_addr(sm), sm->snonce,
 			     key->key_nonce, ptk, akmp,
 			     sm->pairwise_cipher, z, z_len,
-			     kdk_len, sm->pasn_group, 0);
+			     kdk_len, sm->pasn_group, smd_kdk_len);
 	if (ret) {
 		wpa_printf(MSG_ERROR, "WPA: PTK derivation failed");
 		return ret;
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index faca57216a22..9225aa6864e6 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -694,6 +694,9 @@ u64 wpa_sm_get_rsnxe_capab(struct wpa_sm *sm)
 		capab |= BIT(WLAN_RSNX_CAPAB_802_1X_IN_AUTH_FRAMES);
 #endif /* CONFIG_IEEE8021X_AUTH */
 
+	if (sm->smd)
+		capab |= BIT_ULL(WLAN_RSNX_CAPAB_SMD);
+
 	return capab;
 }
 
-- 
2.55.0




More information about the Hostap mailing list