]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Fix Link KDE validation in EAPOL-Key msg 2/4
authorRameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Thu, 10 Apr 2025 20:07:49 +0000 (01:37 +0530)
committerJouni Malinen <j@w1.fi>
Sat, 12 Apr 2025 07:27:23 +0000 (10:27 +0300)
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 <drohan@qti.qualcomm.com>
Signed-off-by: Rohan Dutta <drohan@qti.qualcomm.com>
Co-developed-by: Abishek Ganapathy <abishekg@qti.qualcomm.com>
Signed-off-by: Abishek Ganapathy <abishekg@qti.qualcomm.com>
Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
src/ap/ieee802_11.c
src/ap/sta_info.c
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_i.h

index 7a33dd48779fc85bd0c2a020d93d298477c0ce44..f57b1619a9bd40b828fbd7f9fd11040950414c6a 100644 (file)
@@ -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;
index f78820813a9c80e4a7c6bfa1e1774f64eadc44d2..49f7c898457c13e254e0c0b9e0bddcb66ef00900 100644 (file)
@@ -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 */
index fb9a74a879f591dffc12a5d47f14edfeb072fbb2..f2330bc9d4b47f5e7f58d16f0cd7c7e23f207d0c 100644 (file)
@@ -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;
 
index 1de467e01904daa46ddde8aeeb1d87bc58f66b10..c412633cd719e913e8f8b64a618a5fc09c8dea01 100644 (file)
@@ -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++)       \
index 0aa25b9030ccaba67b4e17c00c6f3af99e1720dc..276582821a0e6c9772596f015e58cc06324ec9f9 100644 (file)
@@ -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;