[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