[PATCH 2/5] FT: Reconcile RSNXE with RSN Overriding in reassociation
Gopi Raga
ragagopi7 at gmail.com
Thu Jul 16 05:11:12 PDT 2026
In WPA3-Personal Compatibility Mode (RSN Overriding), a STA that
associated via the RSNE Override element computes its FTE MIC over
{RSNE, MDE, FTE} and sets the FTE Element Count accordingly (without
counting an RSNXE), even when the Reassociation Request still carries a
base RSNXE and the RSNXE-Used bit is set (SAE H2E). The STA advertises
which variant it used with the RSN Selection element (WFA vendor type
0x506f9a2c).
The FT reassociation processing did not parse the RSN Selection element
and always counted / included the base RSNXE in the protected IE count
and the FTE MIC. This produced an off-by-one that failed the checks:
FT: Some required IEs not included in the protected IE count
FT: Unexpected IE count in MIC Control
Parse the RSN Selection element in wpa_ft_parse_ies() and, when it
indicates an RSNE Override variant, do not count the base RSNXE in the
protected IE count. Apply the same, RSN-Selection-based rule in
wpa_ft_validate_reassoc() to the MIC Control count check and to the FTE
MIC computation so that the element set matches what the STA protected,
regardless of the local rsn_override_omit_rsnxe configuration. This
keeps the authenticator and supplicant handling symmetric. The FTE MIC
verification remains the ultimate authenticity check.
Signed-off-by: Gopi Raga <ragagopi7 at gmail.com>
---
src/ap/wpa_auth_ft.c | 20 +++++++++++++++++---
src/common/wpa_common.c | 36 +++++++++++++++++++++++++++++++++++-
src/common/wpa_common.h | 2 ++
3 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 6be65d2bc..f6d4effc9 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -3496,6 +3496,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
const u8 *kck;
size_t kck_len;
struct wpa_auth_config *conf;
+ bool ignore_rsnxe = false;
int retval = WLAN_STATUS_UNSPECIFIED_FAILURE;
if (sm == NULL)
@@ -3624,10 +3625,23 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
goto out;
}
+ /* When the STA used an RSNE Override variant (WPA3-Personal
+ * Compatibility Mode), it computes the FTE MIC and Element Count over
+ * the override element set and does not include the base RSNXE that may
+ * still be present in the frame. The STA advertises this choice with
+ * the RSN Selection element, so use that (rather than the local
+ * rsn_override_omit_rsnxe configuration) to decide whether to ignore
+ * the base RSNXE here, keeping the count check and MIC computation in
+ * sync with the STA and symmetric with the supplicant-side handling. */
+ if (parse.rsnxe && parse.rsn_selection && parse.rsn_selection_len >= 1 &&
+ (parse.rsn_selection[0] == RSN_SELECTION_RSNE_OVERRIDE ||
+ parse.rsn_selection[0] == RSN_SELECTION_RSNE_OVERRIDE_2))
+ ignore_rsnxe = true;
+
count = 3;
if (parse.ric)
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
- if (parse.rsnxe)
+ if (parse.rsnxe && !ignore_rsnxe)
count++;
if (parse.fte_elem_count != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
@@ -3649,8 +3663,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
parse.ftie - 2, parse.ftie_len + 2,
parse.rsn - 2, parse.rsn_len + 2,
parse.ric, parse.ric_len,
- parse.rsnxe ? parse.rsnxe - 2 : NULL,
- parse.rsnxe ? parse.rsnxe_len + 2 : 0,
+ (parse.rsnxe && !ignore_rsnxe) ? parse.rsnxe - 2 : NULL,
+ (parse.rsnxe && !ignore_rsnxe) ? parse.rsnxe_len + 2 : 0,
NULL,
mic) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index e759ac4e5..b50c37ee9 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1330,6 +1330,19 @@ static int wpa_ft_parse_fte(int key_mgmt, const u8 *ie, size_t len,
}
+static bool ft_rsn_selection_is_override(const struct wpa_ft_ies *parse)
+{
+ /* The RSN Selection element (WPA3-Personal Compatibility Mode / RSN
+ * Overriding) indicates which RSNE variant the STA used. When it
+ * indicates an RSNE Override variant, the STA's protected element set
+ * (FTE Element Count and MIC) is based on the override view, which does
+ * not include the base RSNXE that may still be present in the frame. */
+ return parse->rsn_selection && parse->rsn_selection_len >= 1 &&
+ (parse->rsn_selection[0] == RSN_SELECTION_RSNE_OVERRIDE ||
+ parse->rsn_selection[0] == RSN_SELECTION_RSNE_OVERRIDE_2);
+}
+
+
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
int key_mgmt, bool reassoc_resp)
{
@@ -1393,6 +1406,21 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
parse->rsnxe = pos;
parse->rsnxe_len = len;
break;
+ case WLAN_EID_VENDOR_SPECIFIC:
+ if (len >= 4 &&
+ WPA_GET_BE32(pos) == RSN_SELECTION_IE_VENDOR_TYPE) {
+ /* RSN Selection element (WFA vendor specific)
+ * indicates which RSNE variant (base / RSNE
+ * Override / RSNE Override 2) the STA used. This
+ * is needed so that the FT reassociation
+ * protected IE count and FTE MIC element set can
+ * match the STA when RSN Overriding is in use. */
+ wpa_hexdump(MSG_DEBUG, "FT: RSN Selection",
+ pos, len);
+ parse->rsn_selection = pos + 4;
+ parse->rsn_selection_len = len - 4;
+ }
+ break;
case WLAN_EID_MOBILITY_DOMAIN:
wpa_hexdump(MSG_DEBUG, "FT: MDE", pos, len);
if (len < sizeof(struct rsn_mdie))
@@ -1487,7 +1515,13 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
} else {
if (parse->rsn)
prot_ie_count--;
- if (parse->rsnxe)
+ /* When the STA used an RSNE Override variant (WPA3-Personal
+ * Compatibility Mode), the base RSNXE that may be present in
+ * the frame is not part of the STA's protected element set and
+ * is not reflected in the FTE Element Count. Do not decrement
+ * for it in that case; the FTE MIC verification remains the
+ * ultimate authenticity check. */
+ if (parse->rsnxe && !ft_rsn_selection_is_override(parse))
prot_ie_count--;
}
if (parse->mdie)
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 98a1c7213..f30977b63 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -607,6 +607,8 @@ struct wpa_ft_ies {
size_t rsn_len;
u16 rsn_capab;
const u8 *rsn_pmkid;
+ const u8 *rsn_selection;
+ size_t rsn_selection_len;
const u8 *tie;
size_t tie_len;
const u8 *igtk;
--
2.43.0
More information about the Hostap
mailing list