From: Muna Sinada Date: Mon, 9 Jun 2025 18:06:16 +0000 (-0700) Subject: VLAN: Use VLAN group keys for EAPOL frames and FT reassoc for MLO X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dd65e53c94767509e8736f5fc7b300cf9c6676c9;p=thirdparty%2Fhostap.git VLAN: Use VLAN group keys for EAPOL frames and FT reassoc for MLO When MLO Dynamic VLAN is enabled and non-AP MLDs in a VLAN group are exchanging EAPOL messages, the AP MLD was 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 frame. Signed-off-by: Muna Sinada Signed-off-by: Pradeep Kumar Chitrapu --- diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index ca1210c87..51badb7c1 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -788,7 +788,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 d6ac425ab..52547bfc0 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -5327,7 +5327,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 bc711f53d..625b99969 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -4296,7 +4296,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]; @@ -4305,6 +4305,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; @@ -4346,12 +4349,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); } @@ -4435,7 +4438,8 @@ u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos, } ml_key_info.n_mld_links = i; - 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; i < ml_key_info.n_mld_links; i++) { @@ -7697,3 +7701,34 @@ void wpa_reset_assoc_sm_info(struct wpa_state_machine *assoc_sm, assoc_sm->mld_assoc_link_id = mld_assoc_link_id; #endif /* CONFIG_IEEE80211BE */ } + + +#ifdef CONFIG_IEEE80211BE +/* wpa_select_vlan_wpa_group - Traverse through the wpa_group list and select + * the one that matches the vlan_id. + * + * @gsm: Head of wpa_group list + * @vlan_id: vlan_id used to search the group key state machine data that + * corresponds to the specified VLAN group + * Returns: Pointer to wpa_group that corresponds to the VLAN group on success, + * or pointer to the head of wpa_group list that was passed in. + */ +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, "%s: VLAN group not found", __func__); + vlan_gsm = gsm; + } + + return vlan_gsm; +} +#endif /* CONFIG_IEEE80211BE */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 7b82b0881..47a248957 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -429,7 +429,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); struct wpa_authenticator * (*next_primary_auth)(void *ctx); #endif /* CONFIG_IEEE80211BE */ int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2); @@ -556,7 +556,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, bool 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, @@ -684,7 +684,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, u8 link_id, bool rejected); @@ -712,5 +712,7 @@ static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf) bool wpa_auth_sm_known_sta_identification(struct wpa_state_machine *sm, const u8 *timestamp, const u8 *mic, size_t mic_len); +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 d5400a9f7..759871c27 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, + bool 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; @@ -2545,7 +2551,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, bool reassoc, int vlan_id) { u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; u8 *fte_mic, *elem_count; @@ -2635,7 +2641,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 ca9d67df8..fc47b381b 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1598,7 +1598,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; @@ -1623,7 +1623,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; } @@ -1635,7 +1635,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; }