struct wpa_group *group);
static int ieee80211w_kde_len(struct wpa_state_machine *sm);
static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
+static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group);
+
static const u32 eapol_key_timeout_first = 100; /* ms */
static const u32 eapol_key_timeout_subseq = 1000; /* ms */
static void wpa_gkeydone_sta(struct wpa_state_machine *sm)
{
+#ifdef CONFIG_IEEE80211BE
+ int link_id;
+#endif /* CONFIG_IEEE80211BE */
+
if (!sm->wpa_auth)
return;
sm->wpa_auth->group->GKeyDoneStations--;
sm->GUpdateStationKeys = false;
+
+#ifdef CONFIG_IEEE80211BE
+ for_each_sm_auth(sm, link_id)
+ sm->mld_links[link_id].wpa_auth->group->GKeyDoneStations--;
+#endif /* CONFIG_IEEE80211BE */
}
return 1;
}
+#endif /* CONFIG_IEEE80211BE */
+
static struct wpa_authenticator *
wpa_get_primary_auth(struct wpa_authenticator *wpa_auth)
{
+#ifdef CONFIG_IEEE80211BE
struct wpa_get_link_auth_ctx ctx;
if (!wpa_auth || !wpa_auth->is_ml || wpa_auth->primary_auth)
wpa_auth_for_each_auth(wpa_auth, wpa_get_primary_auth_cb, &ctx);
return ctx.wpa_auth;
-}
-
+#else /* CONFIG_IEEE80211BE */
+ return wpa_auth;
#endif /* CONFIG_IEEE80211BE */
+}
static inline int wpa_auth_mic_failure_report(
}
-static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
+static void wpa_rekey_all_groups(struct wpa_authenticator *wpa_auth)
{
- struct wpa_authenticator *wpa_auth = eloop_ctx;
struct wpa_group *group, *next;
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
group = wpa_auth->group;
while (group) {
+ wpa_printf(MSG_DEBUG, "GTK rekey start for authenticator ("
+ MACSTR "), group vlan %d",
+ MAC2STR(wpa_auth->addr), group->vlan_id);
wpa_group_get(wpa_auth, group);
group->GTKReKey = true;
wpa_group_put(wpa_auth, group);
group = next;
}
+}
+
+
+#ifdef CONFIG_IEEE80211BE
+
+static void wpa_update_all_gtks(struct wpa_authenticator *wpa_auth)
+{
+ struct wpa_group *group, *next;
+
+ group = wpa_auth->group;
+ while (group) {
+ wpa_group_get(wpa_auth, group);
+
+ wpa_group_update_gtk(wpa_auth, group);
+ next = group->next;
+ wpa_group_put(wpa_auth, group);
+ group = next;
+ }
+}
+
+
+static int wpa_update_all_gtks_cb(struct wpa_authenticator *wpa_auth, void *ctx)
+{
+ const u8 *mld_addr = ctx;
+
+ if (!ether_addr_equal(wpa_auth->mld_addr, mld_addr))
+ return 0;
+
+ wpa_update_all_gtks(wpa_auth);
+ return 0;
+}
+
+
+static int wpa_rekey_all_groups_cb(struct wpa_authenticator *wpa_auth,
+ void *ctx)
+{
+ const u8 *mld_addr = ctx;
+
+ if (!ether_addr_equal(wpa_auth->mld_addr, mld_addr))
+ return 0;
+
+ wpa_rekey_all_groups(wpa_auth);
+ return 0;
+}
+
+#endif /* CONFIG_IEEE80211BE */
+
+
+static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_authenticator *wpa_auth = eloop_ctx;
+
+#ifdef CONFIG_IEEE80211BE
+ if (wpa_auth->is_ml) {
+ /* Non-primary ML authenticator eloop timer for group rekey is
+ * never started and shouldn't fire. Check and warn just in
+ * case. */
+ if (!wpa_auth->primary_auth) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: Cannot start GTK rekey on non-primary ML authenticator");
+ return;
+ }
+
+ /* Generate all the new group keys */
+ wpa_auth_for_each_auth(wpa_auth, wpa_update_all_gtks_cb,
+ wpa_auth->mld_addr);
+
+ /* Send all the generated group keys to the respective stations
+ * with group key handshake. */
+ wpa_auth_for_each_auth(wpa_auth, wpa_rekey_all_groups_cb,
+ wpa_auth->mld_addr);
+ } else {
+ wpa_rekey_all_groups(wpa_auth);
+ }
+#else /* CONFIG_IEEE80211BE */
+ wpa_rekey_all_groups(wpa_auth);
+#endif /* CONFIG_IEEE80211BE */
if (wpa_auth->conf.wpa_group_rekey) {
eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
wpa_rekey_gmk, wpa_auth, NULL);
}
+#ifdef CONFIG_IEEE80211BE
+ /* For AP MLD, run group rekey timer only on one link (first) and
+ * whenever it fires do rekey on all associated ML links in one shot.
+ */
+ if ((!wpa_auth->is_ml || !conf->first_link_auth) &&
+ wpa_auth->conf.wpa_group_rekey) {
+#else /* CONFIG_IEEE80211BE */
if (wpa_auth->conf.wpa_group_rekey) {
+#endif /* CONFIG_IEEE80211BE */
eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
wpa_rekey_gtk, wpa_auth, NULL);
}
struct wpa_group *group, *prev;
eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
+
+ /* TODO: Assign ML primary authenticator to next link authenticator and
+ * start rekey timer. */
eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
pmksa_cache_auth_deinit(wpa_auth->pmksa);
wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
LOGGER_INFO,
"received EAPOL-Key Request for GTK rekeying");
- eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
+
+ eloop_cancel_timeout(wpa_rekey_gtk,
+ wpa_get_primary_auth(wpa_auth),
+ NULL);
if (wpa_auth_gtk_rekey_in_process(wpa_auth))
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
"skip new GTK rekey - already in process");
else
- wpa_rekey_gtk(wpa_auth, NULL);
+ wpa_rekey_gtk(wpa_get_primary_auth(wpa_auth),
+ NULL);
}
} else {
/* Do not allow the same key replay counter to be reused. */
#endif /* CONFIG_WNM_AP */
-static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
- struct wpa_group *group)
+static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group)
{
int tmp;
- wpa_printf(MSG_DEBUG,
- "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
- group->vlan_id);
- group->changed = true;
- group->wpa_group_state = WPA_GROUP_SETKEYS;
- group->GTKReKey = false;
tmp = group->GM;
group->GM = group->GN;
group->GN = tmp;
* counting the STAs that are marked with GUpdateStationKeys instead of
* including all STAs that could be in not-yet-completed state. */
wpa_gtk_update(wpa_auth, group);
+}
+
+
+static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group)
+{
+ wpa_printf(MSG_DEBUG,
+ "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
+ group->vlan_id);
+ group->changed = true;
+ group->wpa_group_state = WPA_GROUP_SETKEYS;
+ group->GTKReKey = false;
+
+#ifdef CONFIG_IEEE80211BE
+ if (wpa_auth->is_ml)
+ goto skip_update;
+#endif /* CONFIG_IEEE80211BE */
+
+ wpa_group_update_gtk(wpa_auth, group);
if (group->GKeyDoneStations) {
wpa_printf(MSG_DEBUG,
group->GKeyDoneStations);
group->GKeyDoneStations = 0;
}
+
+#ifdef CONFIG_IEEE80211BE
+skip_update:
+#endif /* CONFIG_IEEE80211BE */
wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
group->GKeyDoneStations);
{
if (!wpa_auth)
return -1;
- eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
- return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
+ eloop_cancel_timeout(wpa_rekey_gtk,
+ wpa_get_primary_auth(wpa_auth), NULL);
+ return eloop_register_timeout(0, 0, wpa_rekey_gtk,
+ wpa_get_primary_auth(wpa_auth), NULL);
}