Signed-off-by: Ilan Peer <ilan.peer@xxxxxxxxx> Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@xxxxxxxxx> --- src/ap/ieee802_11.c | 28 +++++++++-- src/ap/wpa_auth.c | 111 +++++++++++++++++++++++++++++++++++++++++ src/ap/wpa_auth.h | 44 ++++++++++++++++ src/ap/wpa_auth_glue.c | 46 +++++++++++++++++ src/ap/wpa_auth_i.h | 16 ++++++ 5 files changed, 240 insertions(+), 5 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 43558a0e46..6fd9416eed 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3968,15 +3968,33 @@ 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 WPA SM"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + +#ifdef CONFIG_IEEE80211BE + if (info->mld_sta) { + wpa_printf(MSG_DEBUG, "MLD: used for WPA"); + + 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 12b49704b9..f661585611 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -33,6 +33,7 @@ #include "pmksa_cache_auth.h" #include "wpa_auth_i.h" #include "wpa_auth_ie.h" +#include "sta_info.h" #define STATE_MACHINE_DATA struct wpa_state_machine #define STATE_MACHINE_DEBUG_PREFIX "WPA" @@ -695,6 +696,7 @@ 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); + sm->mld_assoc_link_id = -1; return sm; } @@ -788,6 +790,11 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) #ifdef CONFIG_DPP2 wpabuf_clear_free(sm->dpp_z); #endif /* CONFIG_DPP2 */ + os_memset(sm->own_mld_addr, 0, sizeof(sm->own_mld_addr)); + os_memset(sm->peer_mld_addr, 0, sizeof(sm->peer_mld_addr)); + sm->mld_assoc_link_id = -1; + os_memset(sm->mld_links, 0, sizeof(sm->mld_links)); + bin_clear_free(sm, sizeof(*sm)); } @@ -3589,6 +3596,29 @@ 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, + "WPA_AUTH: MLD: RSN info: link_id=%u, rsn_ies_len=%u", + 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) { @@ -6026,3 +6056,84 @@ 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; + u32 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++) { + u8 link_id = ml_rsn_info.links[i].link_id; + struct mld_link *sm_link = &sm->mld_links[link_id]; + const u8 *rsn_ies; + u8 rsn_ies_len; + + 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) { + wpa_printf(MSG_DEBUG, + "WPA_AUTH: MLD: Invalid RSN element"); + 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 eed016accb..fbd9d84f8b 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,40 @@ typedef enum { WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx } wpa_eapol_variable; +struct wpa_auth_ml_rsn_info { + u8 n_mld_links; + + struct wpa_auth_ml_link_rsn_info { + u8 link_id; + const u8 *rsn_ies; + u8 rsn_ies_len; + } links[MAX_NUM_MLD_LINKS]; +}; + +struct wpa_auth_ml_key_info { + u8 n_mld_links; + bool mgmt_frame_prot; + bool beacon_prot; + + struct wpa_auth_ml_link_key_info { + u8 link_id; + + u8 gtkidx; + u8 gtk_len; + u8 pn[6]; + const u8 *gtk; + + u8 igtkidx; + u8 igtk_len; + const u8 *igtk; + u8 ipn[6]; + + u8 bigtkidx; + const u8 *bigtk; + u8 bipn[6]; + } links[MAX_NUM_MLD_LINKS]; +}; + struct wpa_auth_callbacks { void (*logger)(void *ctx, const u8 *addr, logger_level level, const char *txt); @@ -355,6 +390,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 +631,10 @@ 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 8517f6954a..236f2f6001 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1496,6 +1496,49 @@ 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; + u8 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++) { + u8 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) { @@ -1546,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 d401550c7a..e0f2d6fa4b 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -172,6 +172,22 @@ struct wpa_state_machine { void *eapol_status_cb_ctx1; void *eapol_status_cb_ctx2; #endif /* CONFIG_TESTING_OPTIONS */ + + 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; + const u8 *rsnxe; + u8 rsne_len; + u8 rsnxe_len; + } mld_links[MAX_NUM_MLD_LINKS]; }; -- 2.38.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap