From: Ilan Peer <ilan.peer@xxxxxxxxx> Signed-off-by: Ilan Peer <ilan.peer@xxxxxxxxx> Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@xxxxxxxxx> --- src/ap/wpa_auth.c | 71 +++++++++++++++++++++++++++++++++++++++++ src/common/wpa_common.h | 3 ++ 2 files changed, 74 insertions(+) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index a5ec013b02..e0f3c30186 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3128,6 +3128,71 @@ int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth, #endif /* CONFIG_OCV */ +static int wpa_auth_validate_ml_kdes_m2(struct wpa_state_machine *sm, + struct wpa_eapol_ie_parse *kde) +{ +#ifdef CONFIG_IEEE80211BE + u8 i, n_links = 0; + + if (sm->mld_assoc_link_id < 0) + return 0; + + /* MLD MAC address must be the same */ + if (!kde->mac_addr || + os_memcmp(kde->mac_addr, sm->peer_mld_addr, ETH_ALEN)) { + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: invalid MLD address"); + return -1; + } + + /* Find matching link ID and the MAC address for each link */ + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(kde->valid_mlo_links & BIT(i))) + continue; + + /* + * Each entry should contain the link information and the MAC + * address + */ + if (kde->mlo_link_len[i] != 7) { + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: invalid MLO link KDE len=%zu", + kde->mlo_link_len[i]); + return -1; + } + + if (!sm->mld_links[i].valid || i == sm->mld_assoc_link_id) { + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: invalid link id=%u", i); + return -1; + } + + if (os_memcmp(sm->mld_links[i].peer_addr, + kde->mlo_link[i] + 1, + ETH_ALEN)) { + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: invalid MAC address=" MACSTR, + MAC2STR(kde->mlo_link[i] + 1)); + return -1; + } + + n_links++; + } + + /* Must have the same number of MLO links (excluding the local one) */ + if (n_links != sm->n_mld_affiliated_links) { + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: expecting %u mld links in m2, but got %u", + sm->n_mld_affiliated_links, n_links); + return -1; + } + +#endif /* CONFIG_IEEE80211BE */ + + return 0; +} + + SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) { struct wpa_authenticator *wpa_auth = sm->wpa_auth; @@ -3398,6 +3463,12 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) } #endif /* CONFIG_DPP2 */ + if (wpa_auth_validate_ml_kdes_m2(sm, &kde) < 0) { + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + #ifdef CONFIG_IEEE80211R_AP if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { /* diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 05b1a8a05a..e4b4c3489b 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -152,6 +152,9 @@ WPA_CIPHER_BIP_CMAC_256) #define RSN_NUM_REPLAY_COUNTERS_4 2 #define RSN_NUM_REPLAY_COUNTERS_16 3 +#define RSN_KEY_DATA_MLO_LINK_INFO_LINK_ID_MASK 0x0f +#define RSN_KEY_DATA_MLO_LINK_INFO_RSNE_PRESENT 0x10 +#define RSN_KEY_DATA_MLO_LINK_INFO_RSNXE_PRESENT 0x20 #ifdef _MSC_VER #pragma pack(push, 1) -- 2.38.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap