From: Rameshkumar Sundaram Date: Thu, 10 Apr 2025 20:07:49 +0000 (+0530) Subject: AP MLD: Fix Link KDE validation in EAPOL-Key msg 2/4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e7f6730e75a6b316c476197616db0ae5555f78b;p=thirdparty%2Fhostap.git AP MLD: Fix Link KDE validation in EAPOL-Key msg 2/4 As per IEEE Std 802.11be-2024, for MLO, when more than one link is requested and the message 2 is used for the initial 4-way handshake, an MLO Link KDE for each affiliated STA link containing the affiliated STA MAC address shall be included by the non-AP MLD for all the affiliated links present in the Multi-Link element of (Re)Association Request frame. When a subset of links are rejected by AP MLD in association response, its corresponding authenticator object and valid flag is reset in wpa_state_machine(sm->mld_links[]). n_mld_affiliated_links also gets decremented. This causes EAPOL-Key msg 2/4 failure as the non-AP MLD will include Link KDEs for all affiliated links that it requested in association request, whereas the AP MLD is expecting it only for accepted links. Fix this by not decrementing n_mld_affiliated_links when a subset of links is rejected during association and skipping Link KDE validation for rejected links. Fixes: d0a78255dfb5 ("AP MLD: Clear rejected links in wpa_state_machine") Co-developed-by: Rohan Dutta Signed-off-by: Rohan Dutta Co-developed-by: Abishek Ganapathy Signed-off-by: Abishek Ganapathy Signed-off-by: Rameshkumar Sundaram --- diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 7a33dd487..f57b1619a 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4886,7 +4886,7 @@ out: wpa_printf(MSG_DEBUG, "MLD: link: status=%u", status); if (status != WLAN_STATUS_SUCCESS) { wpa_release_link_auth_ref(origin_sta->wpa_sm, - hapd->mld_link_id); + hapd->mld_link_id, true); if (sta) ap_free_sta(hapd, sta); return -1; diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index f78820813..49f7c8984 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -351,7 +351,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) /* Release group references in case non-association link STA is removed * before association link STA */ if (hostapd_sta_is_link_sta(hapd, sta)) - wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id); + wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id, + false); #else /* CONFIG_IEEE80211BE */ wpa_auth_sta_deinit(sta->wpa_sm); #endif /* CONFIG_IEEE80211BE */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index fb9a74a87..f2330bc9d 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -125,7 +125,8 @@ static void wpa_gkeydone_sta(struct wpa_state_machine *sm) #ifdef CONFIG_IEEE80211BE -void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id) +void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id, + bool rejected) { struct wpa_authenticator *wpa_auth; struct mld_link *link; @@ -136,12 +137,12 @@ void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id) link = &sm->mld_links[link_id]; if (link->valid) { link->valid = false; + link->rejected = rejected; wpa_auth = link->wpa_auth; if (wpa_auth) { link->wpa_auth = NULL; wpa_group_put(wpa_auth, wpa_auth->group); } - sm->n_mld_affiliated_links--; } } @@ -3679,6 +3680,12 @@ static int wpa_auth_validate_ml_kdes_m2(struct wpa_state_machine *sm, return -1; } + /* Skip rejected links although the non-AP MLD will send them in + * M2 of the initial 4-way handshake. */ + if (sm->mld_links[i].rejected) { + n_links++; + continue; + } if (!sm->mld_links[i].valid || i == sm->mld_assoc_link_id) { wpa_printf(MSG_DEBUG, "RSN: MLD: Invalid link ID=%u", i); @@ -7589,6 +7596,7 @@ void wpa_auth_set_ml_info(struct wpa_state_machine *sm, struct wpa_get_link_auth_ctx ctx; sm_link->valid = link->valid; + sm_link->rejected = false; if (!link->valid) continue; diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 1de467e01..c412633cd 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -683,7 +683,8 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a, bool mgmt_frame_prot, bool beacon_prot, bool rekey); -void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id); +void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id, + bool rejected); #define for_each_sm_auth(sm, link_id) \ for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) \ diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 0aa25b903..276582821 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -184,6 +184,7 @@ struct wpa_state_machine { struct mld_link { bool valid; + bool rejected; u8 peer_addr[ETH_ALEN]; struct wpa_authenticator *wpa_auth;