[PATCH v3 2/3] FT: Add ft_rsnxe_used_only_with_rsnxe interoperability workaround
Koral Ilgun
koralilgun at gmail.com
Fri Oct 30 07:58:18 PDT 2026
From: Koral Ilgun <koral.ilgun at adtran.com>
The AP sets the RSNXE Used subfield of the FTE MIC Control field in an
FT Reassociation Response frame whenever it uses the RSNXE in other
frames. For a STA that sent no RSNXE, the response carries no RSNXE
either, but the subfield is still set.
Some STAs check the subfield against the elements of the response
itself. An iPad that uses SAE without H2E discards such a response and
sends the Reassociation Request frame again, four to five times, and
the FT protocol never completes, so it stays with the old AP.
Add a per-BSS option ft_rsnxe_used_only_with_rsnxe that does not set the
subfield in the response to a STA that sent no RSNXE. The option
defaults to 0, which keeps the current behavior. Enabling it removes an
indication that a STA without an RSNXE of its own could use to detect an
RSNXE removed from the Beacon frame. A STA that sends an RSNXE gets the
same response as before, unless rsn_override_omit_rsnxe is set: the AP
then omits the RSNXE from every response, so the option also applies
to a STA that sent an RSNXE.
Signed-off-by: Koral Ilgun <koral.ilgun at adtran.com>
---
hostapd/config_file.c | 2 ++
hostapd/hostapd.conf | 11 +++++++++++
src/ap/ap_config.h | 3 +++
src/ap/wpa_auth.h | 1 +
src/ap/wpa_auth_ft.c | 1 +
src/ap/wpa_auth_glue.c | 2 ++
6 files changed, 20 insertions(+)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 396d145b5..b9aafa5e3 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3300,6 +3300,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->ft_over_ds = atoi(pos);
} else if (os_strcmp(buf, "ft_psk_generate_local") == 0) {
bss->ft_psk_generate_local = atoi(pos);
+ } else if (os_strcmp(buf, "ft_rsnxe_used_only_with_rsnxe") == 0) {
+ bss->ft_rsnxe_used_only_with_rsnxe = atoi(pos);
#endif /* CONFIG_IEEE80211R_AP */
#ifndef CONFIG_NO_CTRL_IFACE
} else if (os_strcmp(buf, "ctrl_interface") == 0) {
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 639556ef4..85f2319b9 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -2787,6 +2787,17 @@ own_ip_addr=127.0.0.1
# 1 = enabled
#ft_psk_generate_local=0
+# Do not set the RSNXE Used subfield in an FT Reassociation Response frame to a
+# STA that sent no RSNXE
+# By default (0), the AP sets RSNXE Used whenever it uses the RSNXE in other
+# frames, also in a response without the RSNXE to a STA that sent none. Some
+# STAs reject such a response and repeat the FT reassociation. This option is a
+# workaround for those STAs. Enabling it removes an indication that a STA could
+# use to detect an RSNXE removed from the Beacon frame.
+# 0 = disabled (default)
+# 1 = enabled
+#ft_rsnxe_used_only_with_rsnxe=0
+
##### IEEE 802.11bi related configuration #####################################
# IEEE Std 802.11bi introduces following Enhanced Privacy Protection (EPP)
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index bde816591..fd7bee9c9 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -422,6 +422,9 @@ struct hostapd_bss_config {
int pmk_r1_push;
int ft_over_ds;
int ft_psk_generate_local;
+ /* Interoperability workaround: do not set RSNXE Used in an FT
+ * Reassociation Response to a STA that sent no RSNXE */
+ bool ft_rsnxe_used_only_with_rsnxe;
int r1_max_key_lifetime;
char *rxkh_file;
#endif /* CONFIG_IEEE80211R_AP */
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 9e5e38459..264fdf398 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -223,6 +223,7 @@ struct wpa_auth_config {
int pmk_r1_push;
int ft_over_ds;
int ft_psk_generate_local;
+ bool ft_rsnxe_used_only_with_rsnxe;
#endif /* CONFIG_IEEE80211R_AP */
int disable_gtk;
int ap_mlme;
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 01bde71b7..80fabd4af 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -2727,6 +2727,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
snonce = NULL;
}
rsnxe_used = (auth_alg == WLAN_AUTH_FT) &&
+ !(conf->ft_rsnxe_used_only_with_rsnxe && omit_rsnxe) &&
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
conf->sae_pwe == SAE_PWE_BOTH) &&
wpa_ft_rsnxe_used_allowed(sm);
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 9da2e6d20..ee614248e 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -192,6 +192,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_iface *iface,
wconf->pmk_r1_push = conf->pmk_r1_push;
wconf->ft_over_ds = conf->ft_over_ds;
wconf->ft_psk_generate_local = conf->ft_psk_generate_local;
+ wconf->ft_rsnxe_used_only_with_rsnxe =
+ conf->ft_rsnxe_used_only_with_rsnxe;
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_HS20
wconf->disable_gtk = conf->disable_dgaf;
--
2.43.0
More information about the Hostap
mailing list