From: Andrei Otcheretianski Date: Mon, 22 May 2023 19:33:59 +0000 (+0300) Subject: MLO: Store MLO link information in RSN Authentication X-Git-Tag: hostap_2_11~1123 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3102d7676b9f750016e63e006052849b6d45956f;p=thirdparty%2Fhostap.git MLO: Store MLO link information in RSN Authentication Make the MLO related information available for the RSN Authenticator state machine to be able to perform steps needed on an AP MLD. The actual use of this information will be in the following commits. Signed-off-by: Ilan Peer Signed-off-by: Andrei Otcheretianski --- 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 */ };