]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MBSSID: Re-initialize group keys on the first STA seen in the MBSSID set
authorSai Pratyusha Magam <smagam@qti.qualcomm.com>
Mon, 8 Dec 2025 00:16:49 +0000 (05:46 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 23 Jan 2026 11:58:31 +0000 (13:58 +0200)
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 <smagam@qti.qualcomm.com>
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c

index b28675cb4755357c293383c5d9797398ce0e899c..b4fd2d63e292c27c7c6e72d2127330ae1bf838d7 100644 (file)
@@ -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;
+}
index 12a8b6b1a7f9002fcbaf72c657293cbb277419b5..6e40b250b1c248bbb0a81fc9a68eaf632677bdb2 100644 (file)
@@ -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);
index 8418bf8f044c35cdf11b0c2a1acf8525a02c66fc..6bff35a88199f09169be0853ac14eb413842a0df 100644 (file)
@@ -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;