When MLO Dynamic VLAN is enabled and non-APs in a VLAN group are exchanging EAPOL messages, the AP is providing the primary authenticator's GTKs instead of the VLAN's GTKs. This results in STAs being unable to decrypt the VLAN's multicast frames due to incorrect keys. In wpa_auth_ml_get_key_info(), if vlan_id is provided, traverse through the wpa_group list and select the one that matches the vlan_id. From the matched wpa_group, the correct GTKs are taken. Similarly in the case of FT + MLO + Dynamic VLAN, handle selecting VLAN's wpa_group for the FT protocol Reassociation Response. Signed-off-by: Muna Sinada <quic_msinada@xxxxxxxxxxx> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@xxxxxxxxxxx> --- src/ap/drv_callbacks.c | 2 +- src/ap/ieee802_11.c | 3 ++- src/ap/wpa_auth.c | 35 +++++++++++++++++++++++++++++++---- src/ap/wpa_auth.h | 8 +++++--- src/ap/wpa_auth_ft.c | 13 ++++++++++--- src/ap/wpa_auth_glue.c | 6 +++--- 6 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index d660beefcfa8..584b5af59bb5 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -754,7 +754,7 @@ skip_wpa_check: #ifdef CONFIG_IEEE80211R_AP p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), sta->auth_alg, req_ies, req_ies_len, - !elems.rsnxe); + !elems.rsnxe, reassoc, sta->vlan_id); if (!p) { wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 7ad59276ab84..58a64deeb6e7 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4997,7 +4997,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, buf + buflen - p, sta->auth_alg, ies, ies_len, - omit_rsnxe); + omit_rsnxe, reassoc, + sta->vlan_id); if (!p) { wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 5432e1541be7..93a142258cf0 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -4203,7 +4203,7 @@ static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid, void wpa_auth_ml_get_key_info(struct wpa_authenticator *a, struct wpa_auth_ml_link_key_info *info, bool mgmt_frame_prot, bool beacon_prot, - bool rekey) + bool rekey, int vlan_id) { struct wpa_group *gsm = a->group; u8 rsc[WPA_KEY_RSC_LEN]; @@ -4212,6 +4212,9 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a, "MLD: Get group key info: link_id=%u, IGTK=%u, BIGTK=%u", info->link_id, mgmt_frame_prot, beacon_prot); + if (vlan_id) + gsm = wpa_select_vlan_wpa_group(gsm, vlan_id); + info->gtkidx = gsm->GN & 0x03; info->gtk = gsm->GTK[gsm->GN - 1]; info->gtk_len = gsm->GTK_len; @@ -4253,12 +4256,12 @@ void wpa_auth_ml_get_key_info(struct wpa_authenticator *a, static void wpa_auth_get_ml_key_info(struct wpa_authenticator *wpa_auth, struct wpa_auth_ml_key_info *info, - bool rekey) + bool rekey, int vlan_id) { if (!wpa_auth->cb->get_ml_key_info) return; - wpa_auth->cb->get_ml_key_info(wpa_auth->cb_ctx, info, rekey); + wpa_auth->cb->get_ml_key_info(wpa_auth->cb_ctx, info, rekey, vlan_id); } @@ -4335,7 +4338,8 @@ static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos) ml_key_info.links[i++].link_id = link_id; } - wpa_auth_get_ml_key_info(sm->wpa_auth, &ml_key_info, rekey); + wpa_auth_get_ml_key_info(sm->wpa_auth, &ml_key_info, rekey, + sm->group->vlan_id); /* Add MLO GTK KDEs */ for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) { @@ -7471,3 +7475,26 @@ void wpa_auth_set_ml_info(struct wpa_state_machine *sm, } #endif /* CONFIG_IEEE80211BE */ } + +/* Traverse through the wpa_group list and select the one that matches the + * vlan_id. + */ +struct wpa_group * wpa_select_vlan_wpa_group(struct wpa_group *gsm, + int vlan_id) +{ + struct wpa_group *vlan_gsm = gsm; + + while (vlan_gsm) { + if (vlan_gsm->vlan_id == vlan_id) + break; + + vlan_gsm = vlan_gsm->next; + } + + if (!vlan_gsm) { + wpa_printf(MSG_DEBUG, "vlan group not found"); + vlan_gsm = gsm; + } + + return vlan_gsm; +} diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 9514e55b7f55..4713077d6965 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -425,7 +425,7 @@ struct wpa_auth_callbacks { #endif /* CONFIG_PASN */ #ifdef CONFIG_IEEE80211BE int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info, - bool rekey); + bool rekey, int vlan_id); #endif /* CONFIG_IEEE80211BE */ int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2); }; @@ -547,7 +547,7 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t max_len, int auth_alg, const u8 *req_ies, size_t req_ies_len, - int omit_rsnxe); + int omit_rsnxe, int reassoc, int vlan_id); void wpa_ft_process_auth(struct wpa_state_machine *sm, u16 auth_transaction, const u8 *ies, size_t ies_len, void (*cb)(void *ctx, const u8 *dst, @@ -675,7 +675,7 @@ void wpa_auth_set_ml_info(struct wpa_state_machine *sm, void wpa_auth_ml_get_key_info(struct wpa_authenticator *a, struct wpa_auth_ml_link_key_info *info, bool mgmt_frame_prot, bool beacon_prot, - bool rekey); + bool rekey, int vlan_id); void wpa_release_link_auth_ref(struct wpa_state_machine *sm, int release_link_id); @@ -686,4 +686,6 @@ void wpa_release_link_auth_ref(struct wpa_state_machine *sm, sm->mld_links[link_id].wpa_auth && \ sm->wpa_auth != sm->mld_links[link_id].wpa_auth) +struct wpa_group * wpa_select_vlan_wpa_group(struct wpa_group *gsm, + int vlan_id); #endif /* WPA_AUTH_H */ diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index de16c314de8e..ee632287c7b8 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2212,7 +2212,8 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, } -static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) +static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len, + int reassoc, int vlan_id) { u8 *subelem; struct wpa_auth_config *conf = &sm->wpa_auth->conf; @@ -2224,6 +2225,11 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) const u8 *kek; size_t kek_len; +#ifdef CONFIG_IEEE80211BE + if (reassoc && vlan_id) + gsm = wpa_select_vlan_wpa_group(gsm, vlan_id); +#endif /* CONFIG_IEEE80211BE */ + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { kek = sm->PTK.kek2; kek_len = sm->PTK.kek2_len; @@ -2558,7 +2564,7 @@ static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end, u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t max_len, int auth_alg, const u8 *req_ies, size_t req_ies_len, - int omit_rsnxe) + int omit_rsnxe, int reassoc, int vlan_id) { u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; u8 *fte_mic, *elem_count; @@ -2648,7 +2654,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, /* Fast BSS Transition Information */ if (auth_alg == WLAN_AUTH_FT) { - subelem = wpa_ft_gtk_subelem(sm, &subelem_len); + subelem = wpa_ft_gtk_subelem(sm, &subelem_len, reassoc, + vlan_id); if (!subelem) { wpa_printf(MSG_DEBUG, "FT: Failed to add GTK subelement"); diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 5d7884199f17..d5755e3e3b4e 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1597,7 +1597,7 @@ static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr, static int hostapd_wpa_auth_get_ml_key_info(void *ctx, struct wpa_auth_ml_key_info *info, - bool rekey) + bool rekey, int vlan_id) { struct hostapd_data *hapd = ctx; unsigned int i; @@ -1622,7 +1622,7 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx, &info->links[i], info->mgmt_frame_prot, info->beacon_prot, - rekey); + rekey, vlan_id); continue; } @@ -1634,7 +1634,7 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx, &info->links[i], info->mgmt_frame_prot, info->beacon_prot, - rekey); + rekey, vlan_id); link_bss_found = true; break; } -- 2.34.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap