From: Ilan Peer <ilan.peer at intel.com>
Based on Draft P802.11bn (D1.4), the non-AP MLD needs to verify that the
Security Profile element delivered via the protected channel matches
the one advertised by the AP in Beacon or Probe Response frames:
- If the (Re)Association Request frame is encrypted, the verification
is performed against the element (if present) in the (Re)Association
Response frame.
- If the (Re)Association Request frame is not encrypted, the
verification is performed against the element (if present) in
message 3 of the 4-way handshake.
If this verification fails, deauthenticate.
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/rsn_supp/wpa.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 0d8531f823..e0b9241583 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -2215,6 +2215,59 @@ static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
#endif /* CONFIG_IEEE80211R */
+/*
+ * wpa_supplicant_validate_security_profile - Verify Security Profile element
+ * @sm: WPA state machine
+ * @src_addr: Source MAC address (for debug/disconnect)
+ * @payload: Pointer to the Security Profile element payload (after the
+ * Element ID Extension octet), or %NULL if not present
+ * @payload_len: Length of @payload in octets
+ * Returns: 0 on success, -1 on mismatch
+ *
+ * Verify that the Security Profile element advertised by the AP in the Beacon
+ * or Probe Response frame is the same as the one delivered through the
+ * protected channel (encrypted (Re)Association Response or message 3 of the
+ * 4-way handshake).
+ */
+static int wpa_supplicant_validate_security_profile(struct wpa_sm *sm,
+ const u8 *src_addr,
+ const u8 *payload,
+ size_t payload_len)
+{
+ const u8 *ap_payload = NULL;
+ size_t ap_payload_len = 0;
+
+ if (sm->ap_security_profile && sm->ap_security_profile_len) {
+ ap_payload = sm->ap_security_profile;
+ ap_payload_len = sm->ap_security_profile_len;
+ }
+
+ if (!payload && !ap_payload)
+ return 0;
+
+ if (!payload || !ap_payload ||
+ payload_len != ap_payload_len ||
+ os_memcmp(payload, ap_payload, payload_len) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: Security Profile element mismatch between Beacon/ProbeResp and protected delivery");
+
+ wpa_hexdump(MSG_INFO,
+ "Security Profile element in Beacon/ProbeResp",
+ ap_payload, ap_payload_len);
+
+ wpa_hexdump(MSG_INFO,
+ "Security Profile element in protected delivery",
+ payload, payload_len);
+
+ wpa_sm_deauthenticate(sm,
+ WLAN_STATUS_REJECTED_INVALID_SECURITY_PROFILE);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
const unsigned char *src_addr,
struct wpa_eapol_ie_parse *ie)
@@ -2351,6 +2404,20 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
return -1;
#endif /* CONFIG_IEEE80211R */
+ if (sm->proto == WPA_PROTO_RSN) {
+ const u8 *secp = NULL;
+ size_t secp_len = 0;
+
+ if (ie->security_profile) {
+ secp = ie->security_profile;
+ secp_len = ie->security_profile_len;
+ }
+ if (wpa_supplicant_validate_security_profile(sm, src_addr,
+ secp,
+ secp_len) < 0)
+ return -1;
+ }
+
return 0;
}
@@ -7897,6 +7964,12 @@ int process_encrypted_assoc_resp(struct wpa_sm *sm, int valid_links,
return -1;
}
+ if (wpa_supplicant_validate_security_profile(sm, sm->bssid,
+ elems.security_profile,
+ elems.security_profile_len)
+ < 0)
+ return -1;
+
/* TODO: Check for RSNE/RSNXE mismatch for per-STA profile for MLO */
/* Key Delivery element */
--
2.53.0