diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index c51742b58..8fb40dcbe 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3970,15 +3970,34 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, wpa_ie -= 2; wpa_ie_len += 2; - if (sta->wpa_sm == NULL) + + if (!sta->wpa_sm) { +#ifdef CONFIG_IEEE80211BE + struct mld_info *info = &sta->mld_info; +#endif /* CONFIG_IEEE80211BE */ + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr, p2p_dev_addr); - if (sta->wpa_sm == NULL) { - wpa_printf(MSG_WARNING, "Failed to initialize WPA " - "state machine"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + + if (!sta->wpa_sm) { + wpa_printf(MSG_WARNING, + "Failed to initialize RSN state machine"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + +#ifdef CONFIG_IEEE80211BE + if (info->mld_sta) { + wpa_printf(MSG_DEBUG, + "MLD: Set ML info in RSN Authenticator"); + wpa_auth_set_ml_info(sta->wpa_sm, + hapd->mld_addr, + sta->mld_assoc_link_id, + info); + } +#endif /* CONFIG_IEEE80211BE */ } + wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg); res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, hapd->iface->freq, diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 12b49704b..a9c23b809 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -29,6 +29,7 @@ #include "drivers/driver.h" #include "ap_config.h" #include "ieee802_11.h" +#include "sta_info.h" #include "wpa_auth.h" #include "pmksa_cache_auth.h" #include "wpa_auth_i.h" @@ -695,6 +696,9 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, sm->wpa_auth = wpa_auth; sm->group = wpa_auth->group; wpa_group_get(sm->wpa_auth, sm->group); +#ifdef CONFIG_IEEE80211BE + sm->mld_assoc_link_id = -1; +#endif /* CONFIG_IEEE80211BE */ return sm; } @@ -3590,6 +3594,31 @@ static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid, #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_IEEE80211BE + +void wpa_auth_ml_get_rsn_info(struct wpa_authenticator *a, + struct wpa_auth_ml_link_rsn_info *info) +{ + info->rsn_ies = a->wpa_ie; + info->rsn_ies_len = a->wpa_ie_len; + + wpa_printf(MSG_DEBUG, "RSN: MLD: link_id=%u, rsn_ies_len=%zu", + info->link_id, info->rsn_ies_len); +} + + +static void wpa_auth_get_ml_rsn_info(struct wpa_authenticator *wpa_auth, + struct wpa_auth_ml_rsn_info *info) +{ + if (!wpa_auth->cb->get_ml_rsn_info) + return; + + wpa_auth->cb->get_ml_rsn_info(wpa_auth->cb_ctx, info); +} + +#endif /* CONFIG_IEEE80211BE */ + + SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32]; @@ -6026,3 +6055,81 @@ void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success) eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); } + + +void wpa_auth_set_ml_info(struct wpa_state_machine *sm, const u8 *mld_addr, + u8 mld_assoc_link_id, struct mld_info *info) +{ +#ifdef CONFIG_IEEE80211BE + struct wpa_auth_ml_rsn_info ml_rsn_info; + unsigned int link_id, i; + + if (!info) + return; + + os_memset(sm->mld_links, 0, sizeof(sm->mld_links)); + + wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG, + "MLD: Initialization"); + + os_memcpy(sm->own_mld_addr, mld_addr, ETH_ALEN); + os_memcpy(sm->peer_mld_addr, info->common_info.mld_addr, ETH_ALEN); + + sm->mld_assoc_link_id = mld_assoc_link_id; + + os_memset(&ml_rsn_info, 0, sizeof(ml_rsn_info)); + + for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) { + struct mld_link_info *link = &info->links[link_id]; + struct mld_link *sm_link = &sm->mld_links[link_id]; + + sm_link->valid = link->valid; + if (!link->valid) + continue; + + os_memcpy(sm_link->peer_addr, link->peer_addr, ETH_ALEN); + os_memcpy(sm_link->own_addr, link->local_addr, ETH_ALEN); + + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: id=%u, addr=" MACSTR " peer=" MACSTR, + link_id, + MAC2STR(sm_link->own_addr), + MAC2STR(sm_link->peer_addr)); + + if (link_id != mld_assoc_link_id) + sm->n_mld_affiliated_links++; + + ml_rsn_info.links[i++].link_id = link_id; + } + + ml_rsn_info.n_mld_links = i; + + wpa_auth_get_ml_rsn_info(sm->wpa_auth, &ml_rsn_info); + + for (i = 0; i < ml_rsn_info.n_mld_links; i++) { + struct mld_link *sm_link; + const u8 *rsn_ies; + u8 rsn_ies_len; + + sm_link = &sm->mld_links[ml_rsn_info.links[i].link_id]; + rsn_ies = ml_rsn_info.links[i].rsn_ies; + rsn_ies_len = ml_rsn_info.links[i].rsn_ies_len; + + /* This should not really happen */ + if (!rsn_ies || rsn_ies_len < 2 || rsn_ies[0] != WLAN_EID_RSN || + rsn_ies[1] + 2 > rsn_ies_len) { + wpa_printf(MSG_INFO, "WPA_AUTH: MLD: Invalid RSNE"); + continue; + } + + sm_link->rsne = rsn_ies; + sm_link->rsne_len = rsn_ies[1] + 2; + + if (rsn_ies[1] + 2UL + 2UL < rsn_ies_len && + rsn_ies[rsn_ies[1] + 2] == WLAN_EID_RSNX) { + sm_link->rsnxe = rsn_ies + 2 + rsn_ies[1]; + sm_link->rsnxe_len = sm_link->rsnxe[1] + 2; + } + } +#endif /* CONFIG_IEEE80211BE */ +} diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index eed016acc..311d91f7f 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -15,6 +15,7 @@ #include "common/ieee802_11_defs.h" struct vlan_description; +struct mld_info; #define MAX_OWN_IE_OVERRIDE 256 @@ -288,6 +289,16 @@ typedef enum { WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx } wpa_eapol_variable; +struct wpa_auth_ml_rsn_info { + unsigned int n_mld_links; + + struct wpa_auth_ml_link_rsn_info { + unsigned int link_id; + const u8 *rsn_ies; + size_t rsn_ies_len; + } links[MAX_NUM_MLD_LINKS]; +}; + struct wpa_auth_callbacks { void (*logger)(void *ctx, const u8 *addr, logger_level level, const char *txt); @@ -355,6 +366,9 @@ struct wpa_auth_callbacks { int (*set_ltf_keyseed)(void *ctx, const u8 *addr, const u8 *ltf_keyseed, size_t ltf_keyseed_len); #endif /* CONFIG_PASN */ +#ifdef CONFIG_IEEE80211BE + int (*get_ml_rsn_info)(void *ctx, struct wpa_auth_ml_rsn_info *info); +#endif /* CONFIG_IEEE80211BE */ }; struct wpa_authenticator * wpa_init(const u8 *addr, @@ -593,4 +607,9 @@ void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth, void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success); +void wpa_auth_set_ml_info(struct wpa_state_machine *sm, const u8 *mld_addr, + u8 mld_assoc_link_id, struct mld_info *info); +void wpa_auth_ml_get_rsn_info(struct wpa_authenticator *a, + struct wpa_auth_ml_link_rsn_info *info); + #endif /* WPA_AUTH_H */ diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 14ac4e785..41c029973 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1496,6 +1496,50 @@ static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr, #endif /* CONFIG_PASN */ +#ifdef CONFIG_IEEE80211BE +static int hostapd_wpa_auth_get_ml_rsn_info(void *ctx, + struct wpa_auth_ml_rsn_info *info) +{ + struct hostapd_data *hapd = ctx; + unsigned int i, j; + + wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get RSN info CB: n_mld_links=%u", + info->n_mld_links); + + if (!hapd->conf->mld_ap || !hapd->iface || !hapd->iface->interfaces) + return -1; + + for (i = 0; i < info->n_mld_links; i++) { + unsigned int link_id = info->links[i].link_id; + + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: Get link RSN CB: link_id=%u", + link_id); + + for (j = 0; j < hapd->iface->interfaces->count; j++) { + struct hostapd_iface *iface = + hapd->iface->interfaces->iface[j]; + + if (!iface->bss[0]->conf->mld_ap || + hapd->conf->mld_id != iface->bss[0]->conf->mld_id || + link_id != iface->bss[0]->mld_link_id) + continue; + + wpa_auth_ml_get_rsn_info(iface->bss[0]->wpa_auth, + &info->links[i]); + break; + } + + if (j == hapd->iface->interfaces->count) + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: link=%u not found", link_id); + } + + return 0; +} +#endif /* CONFIG_IEEE80211BE */ + + int hostapd_setup_wpa(struct hostapd_data *hapd) { struct wpa_auth_config _conf; @@ -1545,6 +1589,9 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) #ifdef CONFIG_PASN .set_ltf_keyseed = hostapd_set_ltf_keyseed, #endif /* CONFIG_PASN */ +#ifdef CONFIG_IEEE80211BE + .get_ml_rsn_info = hostapd_wpa_auth_get_ml_rsn_info, +#endif /* CONFIG_IEEE80211BE */ }; const u8 *wpa_ie; size_t wpa_ie_len; diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index d401550c7..74ae5ad2e 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -172,6 +172,24 @@ struct wpa_state_machine { void *eapol_status_cb_ctx1; void *eapol_status_cb_ctx2; #endif /* CONFIG_TESTING_OPTIONS */ + +#ifdef CONFIG_IEEE80211BE + u8 own_mld_addr[ETH_ALEN]; + u8 peer_mld_addr[ETH_ALEN]; + s8 mld_assoc_link_id; + u8 n_mld_affiliated_links; + + struct mld_link { + bool valid; + u8 peer_addr[ETH_ALEN]; + u8 own_addr[ETH_ALEN]; + + const u8 *rsne; + size_t rsne_len; + const u8 *rsnxe; + size_t rsnxe_len; + } mld_links[MAX_NUM_MLD_LINKS]; +#endif /* CONFIG_IEEE80211BE */ };