[PATCH 12/20] wpa_supplicant: Include Security profile element in auth/assoc
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Wed Jun 10 06:12:05 PDT 2026
From: Ilan Peer <ilan.peer at intel.com>
When connecting to an AP that advertises a security profile element,
and the WPA SM was configured with a matching security profile ID,
build a local Security Profile element advertising the chosen profile
ID and include it in:
- The first Authentication frame, when that frame carries an RSNE
(i.e., EPPKE Authentication frame 1);
- The (Re)Association Request frame.
For PASN, since the Security Profile Element is expected only in the
1st authentication frame, extend pasn_set_extra_ies() to also clear
the content of the PASN extra elements.
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/pasn/pasn_common.c | 6 ++-
src/rsn_supp/wpa.c | 66 +++++++++++++++++++++++++++++++++
src/rsn_supp/wpa.h | 7 ++++
wpa_supplicant/sme.c | 41 ++++++++++++++++++++
wpa_supplicant/wpa_supplicant.c | 11 ++++++
5 files changed, 130 insertions(+), 1 deletion(-)
diff --git a/src/pasn/pasn_common.c b/src/pasn/pasn_common.c
index ab9e551bb8..d7359e66f0 100644
--- a/src/pasn/pasn_common.c
+++ b/src/pasn/pasn_common.c
@@ -214,14 +214,18 @@ void pasn_set_custom_pmkid(struct pasn_data *pasn, const u8 *pmkid)
int pasn_set_extra_ies(struct pasn_data *pasn, const u8 *extra_ies,
size_t extra_ies_len)
{
- if (!pasn || !extra_ies_len || !extra_ies)
+ if (!pasn)
return -1;
if (pasn->extra_ies) {
os_free((u8 *) pasn->extra_ies);
+ pasn->extra_ies = NULL;
pasn->extra_ies_len = 0;
}
+ if (!extra_ies_len || !extra_ies)
+ return 0;
+
pasn->extra_ies = os_memdup(extra_ies, extra_ies_len);
if (!pasn->extra_ies) {
wpa_printf(MSG_ERROR,
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 929c064038..0d8531f823 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -5850,6 +5850,72 @@ void wpa_sm_set_matched_security_profile(struct wpa_sm *sm, int profile)
}
+/*
+ * wpa_sm_build_security_profile - Build Security Profile element
+ *
+ * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @buf: Buffer for building the Security Profile element
+ * @len: Length of the buf buffer
+ * Returns: Number of bytes written to buf, or 0 if no Security Profile
+ * element should be sent
+ *
+ * Build a Security Profile element advertising the single profile from
+ * the current WPA SM configuration and is also advertised by the AP.
+ */
+int wpa_sm_build_security_profile(struct wpa_sm *sm, u8 *buf, size_t len)
+{
+ int match, out_octets;
+ size_t elen;
+ u8 reduced_rsn_capab = 0;
+ u8 *pos;
+
+ if (!sm || !buf)
+ return 0;
+
+ if (!sm->ap_security_profile || sm->ap_security_profile_len < 2)
+ return 0;
+
+ match = sm->matched_sec_profile;
+ if (match < 0)
+ return 0;
+
+ if (sm->ext_key_id)
+ reduced_rsn_capab |=
+ SECURITY_PROFILE_REDUCED_RSN_CAPAB_EXT_KEY_ID;
+#ifdef CONFIG_OCV
+ if (sm->ocv)
+ reduced_rsn_capab |= SECURITY_PROFILE_REDUCED_RSN_CAPAB_OCVC;
+#endif /* CONFIG_OCV */
+
+ out_octets = (match / 8) + 1;
+
+ /*
+ * Element ID + Length + Element ID Extension +
+ * Reduced RSN Capabilities + Security Profile Indication +
+ * Security Profile Bitmap.
+ */
+ elen = 1 + 1 + 1 + 1 + 1 + out_octets;
+ if (len < elen)
+ return 0;
+
+ pos = buf;
+ *pos++ = WLAN_EID_EXTENSION;
+ *pos++ = elen - 2;
+ *pos++ = WLAN_EID_EXT_SECURITY_PROFILE;
+ *pos++ = reduced_rsn_capab;
+ *pos++ = (out_octets << SECURITY_PROFILE_IND_OCTETS_BITMAP_SHIFT) &
+ SECURITY_PROFILE_IND_OCTETS_BITMAP_MASK;
+
+ os_memset(pos, 0, out_octets);
+ pos[match / 8] |= BIT(match % 8);
+ pos += out_octets;
+
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Built local Security Profile element", buf, elen);
+ return elen;
+}
+
+
/**
* 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 ce657b5d58..3adfb2b79d 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -226,6 +226,7 @@ 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);
+int wpa_sm_build_security_profile(struct wpa_sm *sm, u8 *buf, 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);
@@ -411,6 +412,12 @@ static inline int wpa_sm_set_ap_security_profile(struct wpa_sm *sm,
return -1;
}
+static inline int wpa_sm_build_security_profile(struct wpa_sm *sm, u8 *buf,
+ size_t len)
+{
+ return 0;
+}
+
static inline void wpa_sm_set_matched_security_profile(struct wpa_sm *sm,
int profile)
{
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 0ab66e760c..e3be8c3c15 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -972,6 +972,8 @@ static int wpas_eppke_initialize(struct wpa_supplicant *wpa_s,
u8 rsne[80];
size_t rsne_len = sizeof(rsne);
int len;
+ u8 secp[20];
+ size_t secp_len;
pasn = &wpa_s->pasn;
@@ -1166,6 +1168,24 @@ static int wpas_eppke_initialize(struct wpa_supplicant *wpa_s,
pasn_set_rsne(pasn, rsne);
wpa_hexdump(MSG_DEBUG, "EPPKE: Set own RSNE default",
pasn->rsn_ie, pasn->rsn_ie_len);
+
+ /*
+ * Include the matching Security Profile element in the first EPPKE
+ * Authentication frame. Pass it via PASN extra_ies so that it is part
+ * of the stored auth1 frame used for the auth-3 MIC computation.
+ * The extra_ies are cleared after building auth1 to avoid including
+ * this element in auth frame 3.
+ */
+ secp_len = wpa_sm_build_security_profile(wpa_s->wpa, secp,
+ sizeof(secp));
+ if (secp_len) {
+ if (pasn_set_extra_ies(pasn, secp, secp_len) < 0) {
+ wpa_printf(MSG_INFO,
+ "EPPKE: Failed to set Security Profile element");
+ goto fail;
+ }
+ }
+
pasn->akmp = wpa_s->key_mgmt;
pasn->cipher = wpa_s->pairwise_cipher;
pasn->group = group;
@@ -1221,6 +1241,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_MBO */
int omit_rsnxe = 0;
unsigned int keys_to_clear = 0;
+ u8 secp[20];
+ size_t secp_len;
if (bss == NULL) {
wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
@@ -1640,6 +1662,18 @@ skip_setup:
wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
}
+ secp_len = wpa_sm_build_security_profile(wpa_s->wpa, secp,
+ sizeof(secp));
+ if (secp_len &&
+ secp_len <= sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RSN: Add Security Profile element to (Re)Association Request frame");
+ os_memcpy(wpa_s->sme.assoc_req_ie +
+ wpa_s->sme.assoc_req_ie_len, secp, secp_len);
+ wpa_s->sme.assoc_req_ie_len += secp_len;
+ }
+
if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION &&
wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_KNOWN_STA_IDENTIFICATION)) {
struct wpabuf *e;
@@ -1723,6 +1757,13 @@ skip_setup:
resp = wpas_pasn_build_auth_1(&wpa_s->pasn, NULL,
false, 0);
+
+ /*
+ * Clear extra_ies after auth1 is built so that
+ * the Security Profile element is not included
+ * in auth frame 3.
+ */
+ pasn_set_extra_ies(&wpa_s->pasn, NULL, 0);
} else {
resp = wpas_pasn_build_auth_3(&wpa_s->pasn, 0);
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 2181015453..043411707c 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3815,6 +3815,8 @@ static u8 * wpas_populate_assoc_ies(
size_t max_wpa_ie_len = 500;
size_t wpa_ie_len;
int algs = WPA_AUTH_ALG_OPEN;
+ u8 secp[20];
+ size_t secp_len;
#ifdef CONFIG_MBO
const u8 *mbo_ie;
#endif
@@ -4269,6 +4271,15 @@ pfs_fail:
wpa_ie_len += wpa_s->rsnxe_len;
}
+ secp_len = wpa_sm_build_security_profile(wpa_s->wpa, secp,
+ sizeof(secp));
+ if (secp_len && secp_len <= max_wpa_ie_len - wpa_ie_len) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RSN: Add Security Profile element to (Re)Association Request frame");
+ os_memcpy(wpa_ie + wpa_ie_len, secp, secp_len);
+ wpa_ie_len += secp_len;
+ }
+
#ifndef CONFIG_NO_ROBUST_AV
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->disable_mscs_support)
--
2.53.0
More information about the Hostap
mailing list