From: Sai Pratyusha Magam Date: Mon, 8 Dec 2025 00:16:49 +0000 (+0530) Subject: MBSSID: Re-initialize group keys on the first STA seen in the MBSSID set X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=47fa843b1a2dcb0006c3ab014dc110ec64b629f7;p=thirdparty%2Fhostap.git MBSSID: Re-initialize group keys on the first STA seen in the MBSSID set In the current implementation, group keys are re-initialized for the first station association (first_sta_seen) in the BSS. In a scenario where the non-transmitting BSS sees a client association before the transmitting BSS, group keys (GTK/IGTK) are re-initialized in wpa_gtk_update() for the non-Tx BSS. It is checked if a BIGTK key is already set on the Tx BSS (bigtk_set). Since BIGTK was set for the Tx BSS during its bringup time, it simply returns from wpa_gtk_update() for the non-Tx BSS. If this is followed by the first station association on the Tx BSS, a new BIGTK key is generated for the Tx BSS in wpa_gtk_update() and the same is installed to the driver. This would mean that the Beacon frames are being sent using the new BIGTK that is not known to the stations associated to the non-Tx BSSs, posing the risk for a potential beacon miss due to beacon protection validation failures. Fix this by allowing re-initialization of group keys if and only if it is the first station association seen across the entire MBSSID set. Signed-off-by: Sai Pratyusha Magam --- diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index b28675cb4..b4fd2d63e 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2606,11 +2606,38 @@ SM_STATE(WPA_PTK, AUTHENTICATION) } +static bool wpa_group_first_sta_seen_mbssid(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + if (!wpa_auth->cb->first_sta_seen_mbssid) + return false; + + return wpa_auth->cb->first_sta_seen_mbssid(wpa_auth->cb_ctx, + group->vlan_id); +} + + static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - if (group->first_sta_seen) + bool first_sta_seen_mbssid = + wpa_group_first_sta_seen_mbssid(wpa_auth, group); + + /* Skip group keys renewal for below cases: + * This is not the first station association on this authenticator. + * In MBSSID case, this is not the first station association in the + * MBSSID set. + */ + if (group->first_sta_seen || first_sta_seen_mbssid) return; + + if (!first_sta_seen_mbssid && wpa_auth->conf.tx_bss_auth) { + struct wpa_group *tx_group = + wpa_auth->conf.tx_bss_auth->group; + tx_group->bigtk_set = false; + tx_group->bigtk_configured = false; + } + /* * System has run bit further than at the time hostapd was started * potentially very early during boot up. This provides better chances @@ -7888,3 +7915,16 @@ void wpa_auth_set_sae_pw_id(struct wpa_state_machine *sm, sm->sae_pw_id_counter = counter; } } + + +bool wpa_auth_get_first_sta_seen(struct wpa_authenticator *wpa_auth, + int vlan_id) +{ + struct wpa_group *group; + + if (!wpa_auth) + return false; + + group = wpa_select_vlan_wpa_group(wpa_auth->group, vlan_id); + return group->first_sta_seen; +} diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 12a8b6b1a..6e40b250b 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -437,6 +437,7 @@ struct wpa_auth_callbacks { #endif /* CONFIG_IEEE80211BE */ int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2); int (*remove_pmkid)(void *ctx, const u8 *sta_addr, const u8 *pmkid); + bool (*first_sta_seen_mbssid)(void *ctx, int vlan_id); }; struct wpa_authenticator * wpa_init(const u8 *addr, @@ -498,6 +499,8 @@ int wpa_auth_get_pairwise(struct wpa_state_machine *sm); const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len); const u8 * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm); int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); +bool wpa_auth_get_first_sta_seen(struct wpa_authenticator *wpa_auth, + int vlan_id); int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm); diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 8418bf8f0..6bff35a88 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1670,6 +1670,26 @@ static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr, #endif /* CONFIG_PASN */ +static bool hostapd_first_sta_seen_mbssid(void *ctx, int vlan_id) +{ + struct hostapd_data *hapd = ctx; + + if (hapd->iconf->mbssid) { + size_t i; + + for (i = 0; i < hapd->iface->num_bss; i++) { + struct hostapd_data *tmp_hapd = hapd->iface->bss[i]; + + if (wpa_auth_get_first_sta_seen(tmp_hapd->wpa_auth, + vlan_id)) + return true; + } + } + + return false; +} + + #ifdef CONFIG_IEEE80211BE static int hostapd_wpa_auth_get_ml_key_info(void *ctx, @@ -1821,6 +1841,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) #endif /* CONFIG_IEEE80211BE */ .get_drv_flags = hostapd_wpa_auth_get_drv_flags, .remove_pmkid = hostapd_wpa_auth_remove_pmkid, + .first_sta_seen_mbssid = hostapd_first_sta_seen_mbssid, }; const u8 *wpa_ie; size_t wpa_ie_len;