[PATCH 10/20] wpa_supplicant: Store AP Security Profile element

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Jun 10 06:12:03 PDT 2026


From: Ilan Peer <ilan.peer at intel.com>

Track the Security Profile element advertised by the AP
in Beacon, Probe Response, and (Re)Association Response frames in the
WPA state machine.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/rsn_supp/wpa.c              | 46 +++++++++++++++++++++++++++++++++
 src/rsn_supp/wpa.h              | 13 ++++++++++
 src/rsn_supp/wpa_i.h            |  3 +++
 wpa_supplicant/events.c         | 15 +++++++++++
 wpa_supplicant/wpa_supplicant.c |  9 ++++++-
 wpa_supplicant/wpas_glue.c      |  6 +++++
 6 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 068d653f29..929c064038 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -4463,6 +4463,7 @@ struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
 	dl_list_init(&sm->pmksa_candidates);
 	sm->renew_snonce = 1;
 	sm->ctx = ctx;
+	sm->matched_sec_profile = -1;
 
 	sm->dot11RSNAConfigPMKLifetime = 43200;
 	sm->dot11RSNAConfigPMKReauthThreshold = 70;
@@ -4503,6 +4504,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
 	os_free(sm->ap_rsne_override);
 	os_free(sm->ap_rsne_override_2);
 	os_free(sm->ap_rsnxe_override);
+	os_free(sm->ap_security_profile);
 	for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
 		os_free(sm->mlo.links[i].ap_rsne);
 		os_free(sm->mlo.links[i].ap_rsnxe);
@@ -4685,6 +4687,7 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
 	sm->eppke_completed = 0;
 	sm->eap_over_auth_frame_completed = 0;
 #endif /* CONFIG_ENC_ASSOC */
+	sm->matched_sec_profile = -1;
 
 	/* Keys are not needed in the WPA state machine anymore */
 	wpa_sm_drop_sa(sm);
@@ -5317,6 +5320,15 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
 		}
 	}
 
+	if (sm->matched_sec_profile >= 0) {
+		ret = os_snprintf(pos, end - pos,
+				  "matched_sec_profile=%d\n",
+				  sm->matched_sec_profile);
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
 	return pos - buf;
 }
 
@@ -5804,6 +5816,40 @@ int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len)
 }
 
 
+int wpa_sm_set_ap_security_profile(struct wpa_sm *sm, const u8 *ie, size_t len)
+{
+	if (!sm)
+		return -1;
+
+	os_free(sm->ap_security_profile);
+	sm->ap_security_profile_len = 0;
+	if (!ie || !len) {
+		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+			"RSN: Clearing AP Security Profile element");
+		sm->ap_security_profile = NULL;
+		sm->ap_security_profile_len = 0;
+	} else {
+		wpa_hexdump(MSG_DEBUG, "RSN: Set AP Security Profile element",
+			    ie, len);
+		sm->ap_security_profile = os_memdup(ie, len);
+		if (!sm->ap_security_profile)
+			return -1;
+
+		sm->ap_security_profile_len = len;
+	}
+
+	return 0;
+}
+
+
+void wpa_sm_set_matched_security_profile(struct wpa_sm *sm, int profile)
+{
+	if (!sm)
+		return;
+	sm->matched_sec_profile = profile;
+}
+
+
 /**
  * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index d42a7c102a..ce657b5d58 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -225,6 +225,8 @@ int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
 int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len);
 int wpa_sm_set_ap_rsne_override_2(struct wpa_sm *sm, const u8 *ie, size_t len);
 int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len);
+int wpa_sm_set_ap_security_profile(struct wpa_sm *sm, const u8 *ie, size_t len);
+void wpa_sm_set_matched_security_profile(struct wpa_sm *sm, int profile);
 int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
 
 int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
@@ -403,6 +405,17 @@ static inline int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie,
 	return -1;
 }
 
+static inline int wpa_sm_set_ap_security_profile(struct wpa_sm *sm,
+						 const u8 *ie, size_t len)
+{
+	return -1;
+}
+
+static inline void wpa_sm_set_matched_security_profile(struct wpa_sm *sm,
+						       int profile)
+{
+}
+
 static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
 {
 	return 0;
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index fc99d20412..9514a47825 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -130,6 +130,9 @@ struct wpa_sm {
 	u8 *ap_rsne_override, *ap_rsne_override_2, *ap_rsnxe_override;
 	size_t ap_rsne_override_len, ap_rsne_override_2_len,
 		ap_rsnxe_override_len;
+	u8 *ap_security_profile;
+	size_t ap_security_profile_len;
+	int matched_sec_profile;	/* -1 if none */
 
 #ifdef CONFIG_TDLS
 	struct wpa_tdls_peer *tdls;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index c67d19ad87..706e2a439f 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -4071,6 +4071,12 @@ no_pfs:
 		    WPA_GET_BE32(&p[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE)
 			wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, p, len);
 
+		if (p[0] == WLAN_EID_EXTENSION && p[1] >= 1 &&
+		    p[2] == WLAN_EID_EXT_SECURITY_PROFILE)
+			wpa_sm_set_ap_security_profile(wpa_s->wpa,
+						       p + 3,
+						       p[1] - 1);
+
 		l -= len;
 		p += len;
 	}
@@ -4083,6 +4089,7 @@ no_pfs:
 		wpa_sm_set_ap_rsne_override(wpa_s->wpa, NULL, 0);
 		wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, NULL, 0);
 		wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, NULL, 0);
+		wpa_sm_set_ap_security_profile(wpa_s->wpa, NULL, 0);
 	}
 	if (wpa_found || rsn_found)
 		wpa_s->ap_ies_from_associnfo = 1;
@@ -4183,6 +4190,7 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
 {
 	const u8 *bss_wpa = NULL, *bss_rsn = NULL, *bss_rsnx = NULL;
 	const u8 *rsnoe, *rsno2e, *rsnxoe;
+	const u8 *bss_secp;
 
 	if (!wpa_s->current_bss || !wpa_s->current_ssid)
 		return -1;
@@ -4215,6 +4223,13 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
 					 rsnxoe ? 2 + rsnxoe[1] : 0))
 		return -1;
 
+	bss_secp = wpa_bss_get_ie_ext(wpa_s->current_bss,
+				      WLAN_EID_EXT_SECURITY_PROFILE);
+	if (wpa_sm_set_ap_security_profile(wpa_s->wpa,
+					   bss_secp ? bss_secp + 3 : NULL,
+					   bss_secp ? bss_secp[1] - 1 : 0))
+		return -1;
+
 	return 0;
 }
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 45f6ea8525..2181015453 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -423,6 +423,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
 	wpa_sm_set_ap_rsne_override(wpa_s->wpa, NULL, 0);
 	wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, NULL, 0);
 	wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, NULL, 0);
+	wpa_sm_set_ap_security_profile(wpa_s->wpa, NULL, 0);
 	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
 #ifndef CONFIG_NO_WPA
 	wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
@@ -1961,10 +1962,13 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 
 	if (bss || !wpa_s->ap_ies_from_associnfo) {
 		const u8 *rsnoe = NULL, *rsno2e = NULL, *rsnxoe = NULL;
+		const u8 *bss_secp = NULL;
 
 		if (bss) {
 			bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
 			bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+			bss_secp = wpa_bss_get_ie_ext(
+				bss, WLAN_EID_EXT_SECURITY_PROFILE);
 			rsnoe = wpa_bss_get_vendor_ie(
 				bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
 			rsno2e = wpa_bss_get_vendor_ie(
@@ -1984,7 +1988,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 		    wpa_sm_set_ap_rsne_override_2(wpa_s->wpa, rsno2e,
 						  rsno2e ? 2 + rsno2e[1] : 0) ||
 		    wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, rsnxoe,
-						 rsnxoe ? 2 + rsnxoe[1] : 0))
+						 rsnxoe ? 2 + rsnxoe[1] : 0) ||
+		    wpa_sm_set_ap_security_profile(wpa_s->wpa,
+						   bss_secp ? bss_secp + 3 : NULL,
+						   bss_secp ? bss_secp[1] - 1 : 0))
 			return -1;
 	}
 
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index e571145032..618b5828cd 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -458,6 +458,12 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
 		if (wpa_sm_set_ap_rsnxe_override(wpa_s->wpa, ie,
 						 ie ? 2 + ie[1] : 0))
 			ret = -1;
+
+		ie = wpa_bss_get_ie_ext(curr, WLAN_EID_EXT_SECURITY_PROFILE);
+		if (wpa_sm_set_ap_security_profile(wpa_s->wpa,
+						   ie ? ie + 3 : NULL,
+						   ie ? ie[1] - 1 : 0))
+			ret = -1;
 	} else {
 		ret = -1;
 	}
-- 
2.53.0




More information about the Hostap mailing list