AP MLD: Support group rekeying for MLO
Group rekeying was not supported for ML stations when non-association link initiates a group rekey. Support this by arming the group key rekey timer on one of the affiliated links and whenever this timer fires, rekey group keys on all the affiliated links. Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com> Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com> Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com> Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
This commit is contained in:
parent
62a8f96e5b
commit
12acda633b
1 changed files with 145 additions and 16 deletions
|
@ -71,6 +71,9 @@ static void wpa_group_put(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_group *group);
|
struct wpa_group *group);
|
||||||
static int ieee80211w_kde_len(struct wpa_state_machine *sm);
|
static int ieee80211w_kde_len(struct wpa_state_machine *sm);
|
||||||
static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
|
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_first = 100; /* ms */
|
||||||
static const u32 eapol_key_timeout_subseq = 1000; /* ms */
|
static const u32 eapol_key_timeout_subseq = 1000; /* ms */
|
||||||
|
@ -105,11 +108,20 @@ static const u8 * wpa_auth_get_spa(const struct wpa_state_machine *sm)
|
||||||
|
|
||||||
static void wpa_gkeydone_sta(struct wpa_state_machine *sm)
|
static void wpa_gkeydone_sta(struct wpa_state_machine *sm)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
int link_id;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
if (!sm->wpa_auth)
|
if (!sm->wpa_auth)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sm->wpa_auth->group->GKeyDoneStations--;
|
sm->wpa_auth->group->GKeyDoneStations--;
|
||||||
sm->GUpdateStationKeys = false;
|
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,10 +175,13 @@ static int wpa_get_primary_auth_cb(struct wpa_authenticator *wpa_auth,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
static struct wpa_authenticator *
|
static struct wpa_authenticator *
|
||||||
wpa_get_primary_auth(struct wpa_authenticator *wpa_auth)
|
wpa_get_primary_auth(struct wpa_authenticator *wpa_auth)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
struct wpa_get_link_auth_ctx ctx;
|
struct wpa_get_link_auth_ctx ctx;
|
||||||
|
|
||||||
if (!wpa_auth || !wpa_auth->is_ml || wpa_auth->primary_auth)
|
if (!wpa_auth || !wpa_auth->is_ml || wpa_auth->primary_auth)
|
||||||
|
@ -177,9 +192,10 @@ wpa_get_primary_auth(struct wpa_authenticator *wpa_auth)
|
||||||
wpa_auth_for_each_auth(wpa_auth, wpa_get_primary_auth_cb, &ctx);
|
wpa_auth_for_each_auth(wpa_auth, wpa_get_primary_auth_cb, &ctx);
|
||||||
|
|
||||||
return ctx.wpa_auth;
|
return ctx.wpa_auth;
|
||||||
}
|
#else /* CONFIG_IEEE80211BE */
|
||||||
|
return wpa_auth;
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int wpa_auth_mic_failure_report(
|
static inline int wpa_auth_mic_failure_report(
|
||||||
|
@ -447,14 +463,16 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
struct wpa_group *group, *next;
|
||||||
|
|
||||||
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
|
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
|
||||||
group = wpa_auth->group;
|
group = wpa_auth->group;
|
||||||
while (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);
|
wpa_group_get(wpa_auth, group);
|
||||||
|
|
||||||
group->GTKReKey = true;
|
group->GTKReKey = true;
|
||||||
|
@ -467,6 +485,83 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
|
||||||
wpa_group_put(wpa_auth, group);
|
wpa_group_put(wpa_auth, group);
|
||||||
group = next;
|
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) {
|
if (wpa_auth->conf.wpa_group_rekey) {
|
||||||
eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
|
eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
|
||||||
|
@ -672,7 +767,15 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
|
||||||
wpa_rekey_gmk, wpa_auth, NULL);
|
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) {
|
if (wpa_auth->conf.wpa_group_rekey) {
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
|
eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
|
||||||
wpa_rekey_gtk, wpa_auth, NULL);
|
wpa_rekey_gtk, wpa_auth, NULL);
|
||||||
}
|
}
|
||||||
|
@ -736,6 +839,9 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
|
||||||
struct wpa_group *group, *prev;
|
struct wpa_group *group, *prev;
|
||||||
|
|
||||||
eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
|
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);
|
eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
|
||||||
|
|
||||||
pmksa_cache_auth_deinit(wpa_auth->pmksa);
|
pmksa_cache_auth_deinit(wpa_auth->pmksa);
|
||||||
|
@ -1704,12 +1810,16 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
|
wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
|
||||||
LOGGER_INFO,
|
LOGGER_INFO,
|
||||||
"received EAPOL-Key Request for GTK rekeying");
|
"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))
|
if (wpa_auth_gtk_rekey_in_process(wpa_auth))
|
||||||
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
|
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
|
||||||
"skip new GTK rekey - already in process");
|
"skip new GTK rekey - already in process");
|
||||||
else
|
else
|
||||||
wpa_rekey_gtk(wpa_auth, NULL);
|
wpa_rekey_gtk(wpa_get_primary_auth(wpa_auth),
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Do not allow the same key replay counter to be reused. */
|
/* Do not allow the same key replay counter to be reused. */
|
||||||
|
@ -5466,17 +5576,11 @@ int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
|
||||||
#endif /* CONFIG_WNM_AP */
|
#endif /* CONFIG_WNM_AP */
|
||||||
|
|
||||||
|
|
||||||
static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
|
static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_group *group)
|
struct wpa_group *group)
|
||||||
{
|
{
|
||||||
int tmp;
|
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;
|
tmp = group->GM;
|
||||||
group->GM = group->GN;
|
group->GM = group->GN;
|
||||||
group->GN = tmp;
|
group->GN = tmp;
|
||||||
|
@ -5490,6 +5594,25 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
|
||||||
* counting the STAs that are marked with GUpdateStationKeys instead of
|
* counting the STAs that are marked with GUpdateStationKeys instead of
|
||||||
* including all STAs that could be in not-yet-completed state. */
|
* including all STAs that could be in not-yet-completed state. */
|
||||||
wpa_gtk_update(wpa_auth, group);
|
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) {
|
if (group->GKeyDoneStations) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
@ -5497,6 +5620,10 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
|
||||||
group->GKeyDoneStations);
|
group->GKeyDoneStations);
|
||||||
group->GKeyDoneStations = 0;
|
group->GKeyDoneStations = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
skip_update:
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
|
wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
|
||||||
wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
|
wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
|
||||||
group->GKeyDoneStations);
|
group->GKeyDoneStations);
|
||||||
|
@ -6857,8 +6984,10 @@ int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
|
||||||
{
|
{
|
||||||
if (!wpa_auth)
|
if (!wpa_auth)
|
||||||
return -1;
|
return -1;
|
||||||
eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
|
eloop_cancel_timeout(wpa_rekey_gtk,
|
||||||
return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
|
wpa_get_primary_auth(wpa_auth), NULL);
|
||||||
|
return eloop_register_timeout(0, 0, wpa_rekey_gtk,
|
||||||
|
wpa_get_primary_auth(wpa_auth), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue