new file mode 100644
@@ -0,0 +1,34 @@
+From 6b0ce29d25d662b68dcc599e62d42eab0690b976 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Wed, 11 Oct 2023 12:43:11 +0300
+Subject: [PATCH 01/11] Define WFA vendor specific element types for RSNE/RSNXE
+ overriding
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=6b0ce29d25d662b68dcc599e62d42eab0690b976]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/common/ieee802_11_defs.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 0fe631026..e2c132a40 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -1446,6 +1446,12 @@ struct ieee80211_ampe_ie {
+ #define QM_IE_OUI_TYPE 0x22
+ #define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
+ #define WFA_CAPA_OUI_TYPE 0x23
++#define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29
++#define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a
++#define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b
++#define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29
++#define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a
++#define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
+
+ #define MULTI_AP_SUB_ELEM_TYPE 0x06
+ #define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,58 @@
+From c16ac89be235ddb07247e0143abf245bb7760c40 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Wed, 11 Oct 2023 12:45:09 +0300
+Subject: [PATCH 02/11] Add RSN overriding elements into IE parsing
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=c16ac89be235ddb07247e0143abf245bb7760c40]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/common/ieee802_11_common.c | 8 ++++++++
+ src/common/ieee802_11_common.h | 4 ++++
+ 2 files changed, 12 insertions(+)
+
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index ba1cb5257..40a38955d 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -140,6 +140,14 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
+ elems->sae_pk = pos + 4;
+ elems->sae_pk_len = elen - 4;
+ break;
++ case WFA_RSNE_OVERRIDE_OUI_TYPE:
++ elems->rsne_override = pos;
++ elems->rsne_override_len = elen;
++ break;
++ case WFA_RSNE_OVERRIDE_2_OUI_TYPE:
++ elems->rsne_override_2 = pos;
++ elems->rsne_override_2_len = elen;
++ break;
+ default:
+ wpa_printf(MSG_MSGDUMP, "Unknown WFA "
+ "information element ignored "
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 9e9684c11..46a86096e 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -116,6 +116,8 @@ struct ieee802_11_elems {
+ const u8 *prior_access_mle;
+ const u8 *mbssid_known_bss;
+ const u8 *mbssid;
++ const u8 *rsne_override;
++ const u8 *rsne_override_2;
+
+ u8 ssid_len;
+ u8 supp_rates_len;
+@@ -179,6 +181,8 @@ struct ieee802_11_elems {
+ size_t prior_access_mle_len;
+ u8 mbssid_known_bss_len;
+ u8 mbssid_len;
++ size_t rsne_override_len;
++ size_t rsne_override_2_len;
+
+ struct mb_ies_info mb_ies;
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,36 @@
+From 48ca68f6f8ba6769d031fac0523e666de7020f57 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Wed, 11 Oct 2023 12:46:23 +0300
+Subject: [PATCH 03/11] Allow RSNE Override element to override RSNE contents
+ during parsing
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=48ca68f6f8ba6769d031fac0523e666de7020f57]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/common/wpa_common.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
+index 1cfdd9ad7..8eb4a1dab 100644
+--- a/src/common/wpa_common.c
++++ b/src/common/wpa_common.c
+@@ -1890,6 +1890,14 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
+ data->has_group = 1;
+ data->key_mgmt = WPA_KEY_MGMT_OSEN;
+ data->proto = WPA_PROTO_OSEN;
++ } else if (rsn_ie_len >= 2 + 4 + 2 && rsn_ie[1] >= 4 + 2 &&
++ rsn_ie[1] == rsn_ie_len - 2 &&
++ (WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE ||
++ WPA_GET_BE32(&rsn_ie[2]) ==
++ RSNE_OVERRIDE_2_IE_VENDOR_TYPE) &&
++ WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) {
++ pos = rsn_ie + 2 + 4 + 2;
++ left = rsn_ie_len - 2 - 4 - 2;
+ } else {
+ const struct rsn_ie_hdr *hdr;
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,36 @@
+From b8a2d11ae04ec20aa6370af4d21150a2a1a5fc89 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Wed, 1 Nov 2023 15:27:31 +0200
+Subject: [PATCH 04/11] Allow RSNXE Override element to override RSNXE contents
+ during parsing
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=b8a2d11ae04ec20aa6370af4d21150a2a1a5fc89]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/common/ieee802_11_common.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index 40a38955d..3ca1ffe7e 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -3131,8 +3131,12 @@ bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
+
+ bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
+ {
+- return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
+- rsnxe ? rsnxe[1] : 0, capab);
++ if (!rsnxe)
++ return false;
++ if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1)
++ return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4,
++ capab);
++ return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab);
+ }
+
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,67 @@
+From 6fad7224be2f54ef9db77aa15a5beee441fa6db5 Mon Sep 17 00:00:00 2001
+From: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
+Date: Tue, 28 May 2024 07:45:44 +0530
+Subject: [PATCH 05/11] Add QCA vendor feature flags to indicate RSN override
+ elements support
+
+Add a separate feature flag for STA mode to indicate support for RSN
+override elements.
+
+Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=6fad7224be2f54ef9db77aa15a5beee441fa6db5]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/common/qca-vendor.h | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
+index 5b58ffb39..2971be74b 100644
+--- a/src/common/qca-vendor.h
++++ b/src/common/qca-vendor.h
+@@ -2180,6 +2180,34 @@ enum qca_wlan_vendor_acs_hw_mode {
+ * that the device supports enhanced audio experience over WLAN feature.
+ * @QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER: Flag indicates that the device
+ * in AP mode supports TWT responder mode in HT and VHT modes.
++ *
++ * @QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA: Flag indicates that the device
++ * supports RSNE/RSNXE overriding in STA mode.
++ *
++ * For SME offload to the driver case:
++ * - Supplicant should enable RSNO element use only when the driver
++ * indicates this feature flag.
++ * - The driver should enable RSNO element use with the supplicant selected
++ * BSS only when the supplicant sends an RSNO element with an empty
++ * payload in the connect request elements buffer in NL80211_CMD_CONNECT.
++ *
++ * For BSS selection offload to the driver case:
++ * - Supplicant should enable RSNO element use only when the driver
++ * indicates this feature flag.
++ * - Supplicant should always send RSNO elements in the connect request
++ * elements buffer in NL80211_CMD_CONNECT irrespective of whether RSNO
++ * elements are supported by the BSS that the supplicant selected
++ * - The driver should enable RSNO element use only when the supplicant
++ * sends an RSNO element with an empty payload in connect request
++ * elements in NL80211_CMD_CONNECT.
++ * - The driver should remove RSNO elements from the connect request
++ * elements while preparing the (Re)Association Request frame elements
++ * if the driver selects a different BSS which is not advertising RSNO
++ * elements.
++ *
++ * If both SME and BSS selection offload to the driver, BSS selection
++ * offload to the driver case rules shall be applied.
++ *
+ * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
+ */
+ enum qca_wlan_vendor_features {
+@@ -2208,6 +2236,7 @@ enum qca_wlan_vendor_features {
+ QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST = 22,
+ QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN = 23,
+ QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER = 24,
++ QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA = 25,
+ NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
+ };
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,65 @@
+From 341bcb2b5c7d83acd2f8f0237182d54d883603e7 Mon Sep 17 00:00:00 2001
+From: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
+Date: Thu, 13 Jun 2024 12:13:14 +0530
+Subject: [PATCH 06/11] nl80211: Add a capability flag for RSN overriding
+
+Add a new capability flag based on the nl80211 feature advertisement for
+RSN overriding support.
+
+Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=341bcb2b5c7d83acd2f8f0237182d54d883603e7]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/drivers/driver.h | 2 ++
+ src/drivers/driver_nl80211.c | 3 +++
+ src/drivers/driver_nl80211_capa.c | 6 ++++++
+ 3 files changed, 11 insertions(+)
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 3e7747489..4331782d8 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -2330,6 +2330,8 @@ struct wpa_driver_capa {
+ #define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP 0x0000000000100000ULL
+ /** Driver supports TWT responder in HT and VHT modes */
+ #define WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER 0x0000000000200000ULL
++/** Driver supports RSN override elements */
++#define WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA 0x0000000000400000ULL
+ u64 flags2;
+
+ #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index e6fbad96d..39f58ff83 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -9899,6 +9899,9 @@ static int nl80211_set_param(void *priv, const char *param)
+ WPA_DRIVER_FLAGS2_SEC_LTF_AP;
+ }
+
++ if (os_strstr(param, "rsn_override_in_driver=1"))
++ drv->capa.flags2 |= WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA;
++
+ return 0;
+ }
+
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index dc16bd445..240d01d3d 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1443,6 +1443,12 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
+ drv->qca_ap_allowed_freqs = 1;
+ if (check_feature(QCA_WLAN_VENDOR_FEATURE_HT_VHT_TWT_RESPONDER, &info))
+ drv->capa.flags2 |= WPA_DRIVER_FLAGS2_HT_VHT_TWT_RESPONDER;
++ if (check_feature(QCA_WLAN_VENDOR_FEATURE_RSN_OVERRIDE_STA, &info)) {
++ wpa_printf(MSG_DEBUG,
++ "The driver supports RSN overriding in STA mode");
++ drv->capa.flags2 |= WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA;
++ }
++
+ os_free(info.flags);
+ }
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,448 @@
+From 5488e120d3d47ba602d89b8365a8d8e5e5aa3e4f Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Wed, 11 Oct 2023 12:50:05 +0300
+Subject: [PATCH 07/11] Use helper functions to access RSNE/RSNXE from BSS
+ entries
+
+This is a step towards allowing the contents of RSNE/RSNXE to be
+overridden.
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=5488e120d3d47ba602d89b8365a8d8e5e5aa3e4f]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ wpa_supplicant/bss.c | 16 ++++++++++++++++
+ wpa_supplicant/bss.h | 7 +++++++
+ wpa_supplicant/ctrl_iface.c | 8 ++++----
+ wpa_supplicant/dbus/dbus_new_handlers.c | 2 +-
+ wpa_supplicant/dpp_supplicant.c | 2 +-
+ wpa_supplicant/events.c | 24 ++++++++++++------------
+ wpa_supplicant/hs20_supplicant.c | 2 +-
+ wpa_supplicant/interworking.c | 6 +++---
+ wpa_supplicant/mbo.c | 2 +-
+ wpa_supplicant/pasn_supplicant.c | 10 +++++-----
+ wpa_supplicant/sme.c | 10 +++++-----
+ wpa_supplicant/wpa_supplicant.c | 8 ++++----
+ wpa_supplicant/wpas_glue.c | 4 ++--
+ wpa_supplicant/wps_supplicant.c | 2 +-
+ 14 files changed, 63 insertions(+), 40 deletions(-)
+
+diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
+index e8aaf6fe1..6d702bb2e 100644
+--- a/wpa_supplicant/bss.c
++++ b/wpa_supplicant/bss.c
+@@ -1866,3 +1866,19 @@ out:
+ wpabuf_free(mlbuf);
+ return removed_links;
+ }
++
++
++const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
++ const struct wpa_bss *bss, struct wpa_ssid *ssid,
++ bool mlo)
++{
++ return wpa_bss_get_ie(bss, WLAN_EID_RSN);
++}
++
++
++const u8 * wpa_bss_get_rsnxe(struct wpa_supplicant *wpa_s,
++ const struct wpa_bss *bss, struct wpa_ssid *ssid,
++ bool mlo)
++{
++ return wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++}
+diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
+index 2079606a9..508129c3d 100644
+--- a/wpa_supplicant/bss.h
++++ b/wpa_supplicant/bss.h
+@@ -226,4 +226,11 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
+ u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss);
+
++const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
++ const struct wpa_bss *bss, struct wpa_ssid *ssid,
++ bool mlo);
++const u8 * wpa_bss_get_rsnxe(struct wpa_supplicant *wpa_s,
++ const struct wpa_bss *bss, struct wpa_ssid *ssid,
++ bool mlo);
++
+ #endif /* BSS_H */
+diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
+index bcbcb258f..d245531cd 100644
+--- a/wpa_supplicant/ctrl_iface.c
++++ b/wpa_supplicant/ctrl_iface.c
+@@ -3119,12 +3119,12 @@ static int wpa_supplicant_ctrl_iface_scan_result(
+ ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+ if (ie)
+ pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
+- ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ if (ie2) {
+ pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
+ ie2, 2 + ie2[1]);
+ }
+- rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
+ if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
+ ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
+ if (os_snprintf_error(end - pos, ret))
+@@ -5444,12 +5444,12 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ if (ie)
+ pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie,
+ 2 + ie[1]);
+- ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ ie2 = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ if (ie2)
+ pos = wpa_supplicant_ie_txt(pos, end,
+ mesh ? "RSN" : "WPA2", ie2,
+ 2 + ie2[1]);
+- rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
+ if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
+ ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
+ if (os_snprintf_error(end - pos, ret))
+diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
+index db1213196..960b3069b 100644
+--- a/wpa_supplicant/dbus/dbus_new_handlers.c
++++ b/wpa_supplicant/dbus/dbus_new_handlers.c
+@@ -5635,7 +5635,7 @@ dbus_bool_t wpas_dbus_getter_bss_rsn(
+ return FALSE;
+
+ os_memset(&wpa_data, 0, sizeof(wpa_data));
+- ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
++ ie = wpa_bss_get_rsne(args->wpa_s, res, NULL, false);
+ if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
+ dbus_set_error_const(error, DBUS_ERROR_FAILED,
+ "failed to parse RSN IE");
+diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
+index 4044b47dd..94d7ae990 100644
+--- a/wpa_supplicant/dpp_supplicant.c
++++ b/wpa_supplicant/dpp_supplicant.c
+@@ -4500,7 +4500,7 @@ int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
+ return 0; /* Not using DPP AKM - continue */
+- rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
+ !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
+ return 0; /* AP does not support DPP AKM - continue */
+diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
+index 49917f7aa..4e55470bb 100644
+--- a/wpa_supplicant/events.c
++++ b/wpa_supplicant/events.c
+@@ -670,7 +670,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
+ (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
+ #endif /* CONFIG_WEP */
+
+- rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsn_ie = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ if (is_6ghz_bss && !rsn_ie) {
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+@@ -1143,7 +1143,7 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ u8 ssid_len;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+- if (!owe || !wpa_bss_get_ie(bss, WLAN_EID_RSN))
++ if (!owe || !wpa_bss_get_rsne(wpa_s, bss, NULL, false))
+ return;
+
+ pos = owe + 6;
+@@ -1247,7 +1247,7 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s,
+
+ if (bss == orig_bss)
+ continue;
+- ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ ie = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
+ if (!(ieee802_11_rsnx_capab(ie, WLAN_RSNX_CAPAB_SAE_PK)))
+ continue;
+
+@@ -1286,7 +1286,7 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+
+ ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+ wpa = ie && ie[1];
+- ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ ie = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ wpa |= ie && ie[1];
+ if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 &&
+ (data.key_mgmt & WPA_KEY_MGMT_OSEN))
+@@ -1295,7 +1295,7 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ osen = ie != NULL;
+
+ #ifdef CONFIG_SAE
+- ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ ie = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
+ if (ie && ie[1] >= 1)
+ rsnxe_capa = ie[2];
+ #endif /* CONFIG_SAE */
+@@ -1650,7 +1650,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
+ ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+ wpa_ie_len = ie ? ie[1] : 0;
+
+- ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ ie = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ rsn_ie_len = ie ? ie[1] : 0;
+
+ ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+@@ -2117,7 +2117,7 @@ static void wpa_supplicant_rsn_preauth_scan_results(
+ if (ssid == NULL)
+ continue;
+
+- rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsn = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ if (rsn == NULL)
+ continue;
+
+@@ -3267,7 +3267,7 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
+ if (wpa_s->wpa_proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) {
+ const u8 *bss_rsn;
+
+- bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ bss_rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ if (bss_rsn) {
+ p = bss_rsn;
+ len = 2 + bss_rsn[1];
+@@ -3721,8 +3721,8 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
+
+ bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
+ WPA_IE_VENDOR_TYPE);
+- bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
+- bss_rsnx = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSNX);
++ bss_rsn = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, NULL, false);
++ bss_rsnx = wpa_bss_get_rsnxe(wpa_s, wpa_s->current_bss, NULL, false);
+
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
+ bss_wpa ? 2 + bss_wpa[1] : 0) ||
+@@ -4110,8 +4110,8 @@ static int wpa_sm_set_ml_info(struct wpa_supplicant *wpa_s)
+ return -1;
+ }
+
+- bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+- bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ bss_rsn = wpa_bss_get_rsne(wpa_s, bss, NULL, true);
++ bss_rsnx = wpa_bss_get_rsnxe(wpa_s, bss, NULL, true);
+
+ wpa_mlo.links[i].ap_rsne = bss_rsn ? (u8 *) bss_rsn : NULL;
+ wpa_mlo.links[i].ap_rsne_len = bss_rsn ? 2 + bss_rsn[1] : 0;
+diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
+index 6a584651e..3ed8813f1 100644
+--- a/wpa_supplicant/hs20_supplicant.c
++++ b/wpa_supplicant/hs20_supplicant.c
+@@ -1087,7 +1087,7 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
+ prov_anqp = bss->anqp->hs20_osu_providers_list;
+ if (prov_anqp == NULL)
+ continue;
+- ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ ie = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &data) == 0 &&
+ (data.key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ osu_ssid2 = bss->ssid;
+diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
+index 6773a243c..e3faca69c 100644
+--- a/wpa_supplicant/interworking.c
++++ b/wpa_supplicant/interworking.c
+@@ -1726,7 +1726,7 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ " for connection",
+ MAC2STR(bss->bssid));
+
+- if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
++ if (!wpa_bss_get_rsne(wpa_s, bss, NULL, false)) {
+ /*
+ * We currently support only HS 2.0 networks and those are
+ * required to use WPA2-Enterprise.
+@@ -2459,7 +2459,7 @@ static struct wpa_bss * pick_best_roaming_partner(struct wpa_supplicant *wpa_s,
+ cred2 = interworking_credentials_available(wpa_s, bss, NULL);
+ if (!cred2)
+ continue;
+- if (!wpa_bss_get_ie(bss, WLAN_EID_RSN))
++ if (!wpa_bss_get_rsne(wpa_s, bss, NULL, false))
+ continue;
+ prio = roaming_prio(wpa_s, cred2, bss);
+ wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for BSS "
+@@ -2511,7 +2511,7 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
+ if (!cred)
+ continue;
+
+- if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
++ if (!wpa_bss_get_rsne(wpa_s, bss, NULL, false)) {
+ /*
+ * We currently support only HS 2.0 networks and those
+ * are required to use WPA2-Enterprise.
+diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
+index 59b15daf6..51f8e0212 100644
+--- a/wpa_supplicant/mbo.c
++++ b/wpa_supplicant/mbo.c
+@@ -115,7 +115,7 @@ void wpas_mbo_check_pmf(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ return;
+ if (oce && oce[1] >= 1 && (oce[2] & OCE_IS_STA_CFON))
+ return; /* STA-CFON is not required to enable PMF */
+- rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsne = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ if (!rsne || wpa_parse_wpa_ie(rsne, 2 + rsne[1], &ie) < 0)
+ return; /* AP is not using RSN */
+
+diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
+index 1bb38f73d..89edad49e 100644
+--- a/wpa_supplicant/pasn_supplicant.c
++++ b/wpa_supplicant/pasn_supplicant.c
+@@ -174,7 +174,7 @@ static int wpas_pasn_get_params_from_bss(struct wpa_supplicant *wpa_s,
+ }
+ }
+
+- rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsne = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ if (!rsne) {
+ wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
+ return -1;
+@@ -186,7 +186,7 @@ static int wpas_pasn_get_params_from_bss(struct wpa_supplicant *wpa_s,
+ return -1;
+ }
+
+- rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
+
+ ssid_str_len = bss->ssid_len;
+ ssid_str = bss->ssid;
+@@ -480,7 +480,7 @@ static struct wpa_bss * wpas_pasn_allowed(struct wpa_supplicant *wpa_s,
+ return NULL;
+ }
+
+- rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsne = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ if (!rsne) {
+ wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
+ return NULL;
+@@ -544,13 +544,13 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
+ goto fail;
+ }
+
+- rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsne = wpa_bss_get_rsne(wpa_s, bss, NULL, false);
+ if (!rsne) {
+ wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
+ goto fail;
+ }
+
+- rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, NULL, false);
+
+ derive_kdk = (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA) &&
+ ieee802_11_rsnx_capab(rsnxe,
+diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
+index e6538e871..8df60393a 100644
+--- a/wpa_supplicant/sme.c
++++ b/wpa_supplicant/sme.c
+@@ -190,7 +190,7 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
+ if (bss) {
+ const u8 *rsnxe;
+
+- rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
+ if (rsnxe && rsnxe[1] >= 1)
+ rsnxe_capa = rsnxe[2];
+ }
+@@ -643,7 +643,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
+ const u8 *rsn;
+ struct wpa_ie_data ied;
+
+- rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ if (!rsn) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SAE enabled, but target BSS does not advertise RSN");
+@@ -683,7 +683,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
+ #endif /* CONFIG_WEP */
+
+ if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
+- wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
++ wpa_bss_get_rsne(wpa_s, bss, ssid, false)) &&
+ wpa_key_mgmt_wpa(ssid->key_mgmt)) {
+ int try_opportunistic;
+ const u8 *cache_id = NULL;
+@@ -807,7 +807,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
+ wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
+ md[0], md[1]);
+
+- omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ omit_rsnxe = !wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
+ if (wpa_s->sme.assoc_req_ie_len + 5 <
+ sizeof(wpa_s->sme.assoc_req_ie)) {
+ struct rsn_mdie *mdie;
+@@ -836,7 +836,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
+
+ wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
+ if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
+- const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ const u8 *rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ struct wpa_ie_data _ie;
+ if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
+ _ie.capabilities &
+diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
+index 037bfa378..de8785a3c 100644
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -1700,8 +1700,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
+
+ if (bss) {
+ bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+- bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+- bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
++ bss_rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
++ bss_rsnx = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
+ bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+ } else {
+ bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
+@@ -3456,7 +3456,7 @@ static u8 * wpas_populate_assoc_ies(
+ }
+
+ if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
+- wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
++ wpa_bss_get_rsne(wpa_s, bss, ssid, false)) &&
+ wpa_key_mgmt_wpa(ssid->key_mgmt)) {
+ int try_opportunistic;
+ const u8 *cache_id = NULL;
+@@ -4497,7 +4497,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+
+ params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
+ if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
+- const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ const u8 *rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ struct wpa_ie_data ie;
+ if (!wpas_driver_bss_selection(wpa_s) && rsn &&
+ wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
+diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
+index 5199f950b..9100bee05 100644
+--- a/wpa_supplicant/wpas_glue.c
++++ b/wpa_supplicant/wpas_glue.c
+@@ -425,11 +425,11 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
+ ret = -1;
+
+- ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
++ ie = wpa_bss_get_rsne(wpa_s, curr, ssid, false);
+ if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
+ ret = -1;
+
+- ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
++ ie = wpa_bss_get_rsnxe(wpa_s, curr, ssid, false);
+ if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
+ ret = -1;
+ } else {
+diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
+index 8cd355f6b..7b9cf7f9e 100644
+--- a/wpa_supplicant/wps_supplicant.c
++++ b/wpa_supplicant/wps_supplicant.c
+@@ -226,7 +226,7 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
+
+ wpa_printf(MSG_DEBUG, "WPS: AP found from BSS table");
+
+- ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
++ ie = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
+ if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0) {
+ wpa2 = 1;
+ if (adv.pairwise_cipher & WPA_CIPHER_CCMP)
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,66 @@
+From d0b55eb360d34231b095a14d55592ea682895e27 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Thu, 27 Jun 2024 17:33:44 +0300
+Subject: [PATCH 08/11] Make driver capabilities for AKM suites available
+ within wpa_supplicant
+
+In addition, add some of the previously missed AKM suites from the
+default capabilities.
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=d0b55eb360d34231b095a14d55592ea682895e27]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/drivers/driver_nl80211_capa.c | 2 ++
+ wpa_supplicant/wpa_supplicant.c | 1 +
+ wpa_supplicant/wpa_supplicant_i.h | 1 +
+ 3 files changed, 4 insertions(+)
+
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 240d01d3d..26c1f4140 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1476,6 +1476,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
++ WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256 |
+ WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
+ WPA_DRIVER_CAPA_KEY_MGMT_OWE |
+ WPA_DRIVER_CAPA_KEY_MGMT_DPP;
+@@ -1491,6 +1492,7 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
+ WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
+ WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
+ WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
++ WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY |
+ WPA_DRIVER_CAPA_KEY_MGMT_SAE;
+ else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
+ drv->capa.key_mgmt |=
+diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
+index de8785a3c..c27977560 100644
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -7363,6 +7363,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
+ wpa_s->drv_flags = capa.flags;
+ wpa_s->drv_flags2 = capa.flags2;
+ wpa_s->drv_enc = capa.enc;
++ wpa_s->drv_key_mgmt = capa.key_mgmt;
+ wpa_s->drv_rrm_flags = capa.rrm_flags;
+ wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
+ wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
+diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
+index 110a8648c..e92f6b147 100644
+--- a/wpa_supplicant/wpa_supplicant_i.h
++++ b/wpa_supplicant/wpa_supplicant_i.h
+@@ -920,6 +920,7 @@ struct wpa_supplicant {
+ u64 drv_flags;
+ u64 drv_flags2;
+ unsigned int drv_enc;
++ unsigned int drv_key_mgmt;
+ unsigned int drv_rrm_flags;
+ unsigned int drv_max_acl_mac_addrs;
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,739 @@
+From 765c48d5adcf8996b2568a7b2ec9d3a9c34ec902 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Wed, 11 Oct 2023 12:50:05 +0300
+Subject: [PATCH 09/11] RSNE/RSNXE overriding for STA
+
+Add support for RSNE/RSNXE Override elements. Use these elements to
+determine AP's extended RSN parameters.
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=765c48d5adcf8996b2568a7b2ec9d3a9c34ec902]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/rsn_supp/wpa.c | 92 ++++++++++---
+ src/rsn_supp/wpa_ie.c | 11 +-
+ wpa_supplicant/bss.c | 201 ++++++++++++++++++++++++++++-
+ wpa_supplicant/config.c | 1 +
+ wpa_supplicant/config.h | 13 ++
+ wpa_supplicant/config_file.c | 2 +
+ wpa_supplicant/events.c | 24 +++-
+ wpa_supplicant/sme.c | 27 +++-
+ wpa_supplicant/wpa_supplicant.c | 128 ++++++++++++++++++
+ wpa_supplicant/wpa_supplicant.conf | 9 ++
+ wpa_supplicant/wpa_supplicant_i.h | 5 +
+ 11 files changed, 487 insertions(+), 26 deletions(-)
+
+diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
+index f23979cd9..e48982989 100644
+--- a/src/rsn_supp/wpa.c
++++ b/src/rsn_supp/wpa.c
+@@ -4550,12 +4550,27 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
+ } else {
+ wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE",
+ ie, len);
+- sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
+- if (!sm->mlo.links[i].ap_rsne) {
+- sm->mlo.links[i].ap_rsne_len = 0;
+- return -1;
++ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
++ sm->mlo.links[i].ap_rsne = os_malloc(len - 4);
++ if (!sm->mlo.links[i].ap_rsne)
++ return -1;
++ sm->mlo.links[i].ap_rsne[0] = WLAN_EID_RSN;
++ sm->mlo.links[i].ap_rsne[1] = len - 2 - 4;
++ os_memcpy(&sm->mlo.links[i].ap_rsne[2],
++ ie + 2 + 4, len - 2 - 4);
++ sm->mlo.links[i].ap_rsne_len = len - 4;
++ wpa_hexdump(MSG_DEBUG,
++ "RSN: Converted RSNE override to RSNE",
++ sm->mlo.links[i].ap_rsne,
++ sm->mlo.links[i].ap_rsne_len);
++ } else {
++ sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
++ if (!sm->mlo.links[i].ap_rsne) {
++ sm->mlo.links[i].ap_rsne_len = 0;
++ return -1;
++ }
++ sm->mlo.links[i].ap_rsne_len = len;
+ }
+- sm->mlo.links[i].ap_rsne_len = len;
+ }
+
+ ie = mlo->links[i].ap_rsnxe;
+@@ -4571,12 +4586,27 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
+ } else {
+ wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie,
+ len);
+- sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
+- if (!sm->mlo.links[i].ap_rsnxe) {
+- sm->mlo.links[i].ap_rsnxe_len = 0;
+- return -1;
++ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
++ sm->mlo.links[i].ap_rsnxe = os_malloc(len - 4);
++ if (!sm->mlo.links[i].ap_rsnxe)
++ return -1;
++ sm->mlo.links[i].ap_rsnxe[0] = WLAN_EID_RSNX;
++ sm->mlo.links[i].ap_rsnxe[1] = len - 2 - 4;
++ os_memcpy(&sm->mlo.links[i].ap_rsnxe[2],
++ ie + 2 + 4, len - 2 - 4);
++ sm->mlo.links[i].ap_rsnxe_len = len - 4;
++ wpa_hexdump(MSG_DEBUG,
++ "RSN: Converted RSNXE override to RSNXE",
++ sm->mlo.links[i].ap_rsnxe,
++ sm->mlo.links[i].ap_rsnxe_len);
++ } else {
++ sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
++ if (!sm->mlo.links[i].ap_rsnxe) {
++ sm->mlo.links[i].ap_rsnxe_len = 0;
++ return -1;
++ }
++ sm->mlo.links[i].ap_rsnxe_len = len;
+ }
+- sm->mlo.links[i].ap_rsnxe_len = len;
+ }
+ }
+
+@@ -5077,11 +5107,24 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
+ sm->ap_rsn_ie_len = 0;
+ } else {
+ wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
+- sm->ap_rsn_ie = os_memdup(ie, len);
+- if (sm->ap_rsn_ie == NULL)
+- return -1;
++ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
++ sm->ap_rsn_ie = os_malloc(len - 4);
++ if (!sm->ap_rsn_ie)
++ return -1;
++ sm->ap_rsn_ie[0] = WLAN_EID_RSN;
++ sm->ap_rsn_ie[1] = len - 2 - 4;
++ os_memcpy(&sm->ap_rsn_ie[2], ie + 2 + 4, len - 2 - 4);
++ sm->ap_rsn_ie_len = len - 4;
++ wpa_hexdump(MSG_DEBUG,
++ "RSN: Converted RSNE override to RSNE",
++ sm->ap_rsn_ie, sm->ap_rsn_ie_len);
++ } else {
++ sm->ap_rsn_ie = os_memdup(ie, len);
++ if (sm->ap_rsn_ie == NULL)
++ return -1;
+
+- sm->ap_rsn_ie_len = len;
++ sm->ap_rsn_ie_len = len;
++ }
+ }
+
+ return 0;
+@@ -5110,11 +5153,24 @@ int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
+ sm->ap_rsnxe_len = 0;
+ } else {
+ wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
+- sm->ap_rsnxe = os_memdup(ie, len);
+- if (!sm->ap_rsnxe)
+- return -1;
++ if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) {
++ sm->ap_rsnxe = os_malloc(len - 4);
++ if (!sm->ap_rsnxe)
++ return -1;
++ sm->ap_rsnxe[0] = WLAN_EID_RSNX;
++ sm->ap_rsnxe[1] = len - 2 - 4;
++ os_memcpy(&sm->ap_rsnxe[2], ie + 2 + 4, len - 2 - 4);
++ sm->ap_rsnxe_len = len - 4;
++ wpa_hexdump(MSG_DEBUG,
++ "RSN: Converted RSNXE override to RSNXE",
++ sm->ap_rsnxe, sm->ap_rsnxe_len);
++ } else {
++ sm->ap_rsnxe = os_memdup(ie, len);
++ if (!sm->ap_rsnxe)
++ return -1;
+
+- sm->ap_rsnxe_len = len;
++ sm->ap_rsnxe_len = len;
++ }
+ }
+
+ return 0;
+diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
+index eeedf8ba5..515f1b027 100644
+--- a/src/rsn_supp/wpa_ie.c
++++ b/src/rsn_supp/wpa_ie.c
+@@ -33,8 +33,15 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
+ if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
+ return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
+- else
+- return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
++ if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
++ wpa_ie[1] >= 4 &&
++ WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE)
++ return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
++ if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
++ wpa_ie[1] >= 4 &&
++ WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE)
++ return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
++ return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
+ }
+
+
+diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
+index 6d702bb2e..8dcda7848 100644
+--- a/wpa_supplicant/bss.c
++++ b/wpa_supplicant/bss.c
+@@ -1657,10 +1657,22 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
+
+ if (ssid) {
+ struct wpa_ie_data ie;
+-
+- if (!elems.rsn_ie ||
+- wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
+- &ie)) {
++ const u8 *rsne;
++ size_t rsne_len;
++
++ if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s)) {
++ rsne = elems.rsne_override_2;
++ rsne_len = elems.rsne_override_2_len;
++ } else if (elems.rsne_override &&
++ wpas_rsn_overriding(wpa_s)) {
++ rsne = elems.rsne_override;
++ rsne_len = elems.rsne_override_len;
++ } else {
++ rsne = elems.rsn_ie;
++ rsne_len = elems.rsn_ie_len;
++ }
++ if (!rsne ||
++ wpa_parse_wpa_ie(rsne - 2, 2 + rsne_len, &ie)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
+ goto out;
+ }
+@@ -1868,10 +1880,163 @@ out:
+ }
+
+
++static bool wpa_bss_supported_cipher(struct wpa_supplicant *wpa_s,
++ int pairwise_cipher)
++{
++ if (!wpa_s->drv_enc)
++ return true;
++
++ if ((pairwise_cipher & WPA_CIPHER_CCMP) &&
++ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP))
++ return true;
++
++ if ((pairwise_cipher & WPA_CIPHER_GCMP) &&
++ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP))
++ return true;
++
++ if ((pairwise_cipher & WPA_CIPHER_CCMP_256) &&
++ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256))
++ return true;
++
++ if ((pairwise_cipher & WPA_CIPHER_GCMP_256) &&
++ (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256))
++ return true;
++
++ return false;
++}
++
++
++static bool wpa_bss_supported_key_mgmt(struct wpa_supplicant *wpa_s,
++ int key_mgmt)
++{
++ if (!wpa_s->drv_key_mgmt)
++ return true;
++
++ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_PSK) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FT_PSK) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_PSK_SHA256) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_SAE) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FT_SAE) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_OWE) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_DPP) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA256) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA384) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256))
++ return true;
++ if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) &&
++ (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384))
++ return true;
++
++ return false;
++}
++
++
++static bool wpa_bss_supported_rsne(struct wpa_supplicant *wpa_s,
++ struct wpa_ssid *ssid, const u8 *ie)
++{
++ struct wpa_ie_data data;
++
++ if (wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) < 0)
++ return false;
++
++ /* Check that there is a supported AKM and pairwise cipher based on
++ * overall capabilities */
++ if (!data.pairwise_cipher || !data.key_mgmt)
++ return false;
++
++ if (wpa_s->drv_capa_known) {
++ if (!wpa_bss_supported_cipher(wpa_s, data.pairwise_cipher) ||
++ !wpa_bss_supported_key_mgmt(wpa_s, data.key_mgmt))
++ return false;
++ }
++
++ if (ssid) {
++ /* Check that there is a supported AKM and pairwise cipher
++ * based on the specific network profile. */
++ if ((ssid->pairwise_cipher & data.pairwise_cipher) == 0)
++ return false;
++ if ((ssid->key_mgmt & data.key_mgmt) == 0)
++ return false;
++ }
++
++ return true;
++}
++
++
+ const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
+ const struct wpa_bss *bss, struct wpa_ssid *ssid,
+ bool mlo)
+ {
++ const u8 *ie;
++
++ if (wpas_rsn_overriding(wpa_s)) {
++ if (!ssid)
++ ssid = wpa_s->current_ssid;
++
++ /* MLO cases for RSN overriding are required to use RSNE
++ * Override 2 element and RSNXE Override element together. */
++ ie = wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
++ if (mlo && ie &&
++ !wpa_bss_get_vendor_ie(bss,
++ RSNXE_OVERRIDE_IE_VENDOR_TYPE)) {
++ wpa_printf(MSG_DEBUG, "BSS " MACSTR
++ " advertises RSNE Override 2 element without RSNXE Override element - ignore RSNE Override 2 element for MLO",
++ MAC2STR(bss->bssid));
++ } else if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie)) {
++ return ie;
++ }
++
++ if (!mlo) {
++ ie = wpa_bss_get_vendor_ie(
++ bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
++ if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie))
++ return ie;
++ }
++ }
++
+ return wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ }
+
+@@ -1880,5 +2045,33 @@ const u8 * wpa_bss_get_rsnxe(struct wpa_supplicant *wpa_s,
+ const struct wpa_bss *bss, struct wpa_ssid *ssid,
+ bool mlo)
+ {
++ const u8 *ie;
++
++ if (wpas_rsn_overriding(wpa_s)) {
++ ie = wpa_bss_get_vendor_ie(bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
++ if (ie) {
++ const u8 *tmp;
++
++ tmp = wpa_bss_get_rsne(wpa_s, bss, ssid, mlo);
++ if (!tmp || tmp[0] == WLAN_EID_RSN) {
++ /* An acceptable RSNE override element was not
++ * found, so need to ignore RSNXE overriding. */
++ return NULL;
++ }
++
++ return ie;
++ }
++
++ /* MLO cases for RSN overriding are required to use RSNE
++ * Override 2 element and RSNXE Override element together. */
++ if (mlo && wpa_bss_get_vendor_ie(
++ bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE)) {
++ wpa_printf(MSG_DEBUG, "BSS " MACSTR
++ " advertises RSNXE Override element without RSNE Override 2 element - ignore RSNXE Override element for MLO",
++ MAC2STR(bss->bssid));
++ return NULL;
++ }
++ }
++
+ return wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+ }
+diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
+index 24861c68f..b02b694a3 100644
+--- a/wpa_supplicant/config.c
++++ b/wpa_supplicant/config.c
+@@ -5579,6 +5579,7 @@ static const struct global_parse_data global_fields[] = {
+ { INT_RANGE(extended_key_id, 0, 1), 0 },
+ #endif /* CONFIG_WNM */
+ { INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
++ { INT_RANGE(rsn_overriding, 0, 2), 0},
+ #ifdef CONFIG_PASN
+ #ifdef CONFIG_TESTING_OPTIONS
+ { INT_RANGE(force_kdk_derivation, 0, 1), 0 },
+diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
+index 8981305c2..d74b5c455 100644
+--- a/wpa_supplicant/config.h
++++ b/wpa_supplicant/config.h
+@@ -1774,6 +1774,19 @@ struct wpa_config {
+ */
+ int wowlan_disconnect_on_deinit;
+
++ /**
++ * rsn_overriding - RSN overriding
++ *
++ * 0 = Disabled
++ * 1 = Enabled automatically if the driver indicates support
++ * 2 = Forced to be enabled even without driver capability indication
++ */
++ enum rsn_overriding {
++ RSN_OVERRIDING_DISABLED = 0,
++ RSN_OVERRIDING_AUTO = 1,
++ RSN_OVERRIDING_ENABLED = 2,
++ } rsn_overriding;
++
+ #ifdef CONFIG_PASN
+ #ifdef CONFIG_TESTING_OPTIONS
+ /*
+diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
+index ad37bcf22..fd8eafe2b 100644
+--- a/wpa_supplicant/config_file.c
++++ b/wpa_supplicant/config_file.c
+@@ -1615,6 +1615,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
+ if (config->wowlan_disconnect_on_deinit)
+ fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
+ config->wowlan_disconnect_on_deinit);
++ if (config->rsn_overriding)
++ fprintf(f, "rsn_overriding=%d\n", config->rsn_overriding);
+ #ifdef CONFIG_TESTING_OPTIONS
+ if (config->mld_force_single_link)
+ fprintf(f, "mld_force_single_link=1\n");
+diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
+index 4e55470bb..4393c469c 100644
+--- a/wpa_supplicant/events.c
++++ b/wpa_supplicant/events.c
+@@ -1296,7 +1296,9 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+
+ #ifdef CONFIG_SAE
+ ie = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
+- if (ie && ie[1] >= 1)
++ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4 + 1)
++ rsnxe_capa = ie[4 + 2];
++ else if (ie && ie[1] >= 1)
+ rsnxe_capa = ie[2];
+ #endif /* CONFIG_SAE */
+
+@@ -3665,9 +3667,29 @@ no_pfs:
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
+ }
+
++ if (wpas_rsn_overriding(wpa_s) &&
++ p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
++ WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
++ rsn_found = 1;
++ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
++ }
++
++ if (!rsn_found &&
++ wpas_rsn_overriding(wpa_s) &&
++ p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
++ WPA_GET_BE32(&p[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
++ rsn_found = 1;
++ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
++ }
++
+ if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
+
++ if (wpas_rsn_overriding(wpa_s) &&
++ p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
++ WPA_GET_BE32(&p[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE)
++ wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
++
+ l -= len;
+ p += len;
+ }
+diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
+index 8df60393a..292897edd 100644
+--- a/wpa_supplicant/sme.c
++++ b/wpa_supplicant/sme.c
+@@ -191,7 +191,10 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
+ const u8 *rsnxe;
+
+ rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
+- if (rsnxe && rsnxe[1] >= 1)
++ if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC &&
++ rsnxe[1] >= 1 + 4)
++ rsnxe_capa = rsnxe[2 + 4];
++ else if (rsnxe && rsnxe[1] >= 1)
+ rsnxe_capa = rsnxe[2];
+ }
+
+@@ -2464,6 +2467,28 @@ mscs_fail:
+ wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
+ }
+
++ if (wpas_rsn_overriding(wpa_s) &&
++ wpas_ap_supports_rsn_overriding(wpa_s, wpa_s->current_bss) &&
++ wpa_s->sme.assoc_req_ie_len + 2 + 4 <=
++ sizeof(wpa_s->sme.assoc_req_ie)) {
++ u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
++ u32 type = 0;
++ const u8 *ie;
++
++ ie = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, ssid,
++ wpa_s->valid_links);
++ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
++ type = WPA_GET_BE32(&ie[2]);
++
++ if (type) {
++ /* Indicate support for RSN overriding */
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 4;
++ WPA_PUT_BE32(pos, type);
++ wpa_s->sme.assoc_req_ie_len += 2 + 4;
++ }
++ }
++
+ params.bssid = bssid;
+ params.ssid = wpa_s->sme.ssid;
+ params.ssid_len = wpa_s->sme.ssid_len;
+diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
+index c27977560..3203446f1 100644
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -3943,6 +3943,57 @@ mscs_end:
+ wpa_ie_len += multi_ap_ie_len;
+ }
+
++ if (!wpas_driver_bss_selection(wpa_s) &&
++ wpas_rsn_overriding(wpa_s) &&
++ wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
++ wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
++ u8 *pos = wpa_ie + wpa_ie_len;
++ u32 type = 0;
++ const u8 *ie;
++
++ ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
++ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
++ type = WPA_GET_BE32(&ie[2]);
++
++ if (type) {
++ /* Indicate support for RSN overriding */
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 4;
++ WPA_PUT_BE32(pos, type);
++ pos += 4;
++ wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
++ pos - wpa_ie);
++ wpa_ie_len += 2 + 4;
++ }
++ }
++
++ if (wpas_driver_bss_selection(wpa_s) &&
++ wpas_rsn_overriding(wpa_s)) {
++ if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
++ u8 *pos = wpa_ie + wpa_ie_len;
++
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 4;
++ WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
++ pos += 4;
++ wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
++ pos - wpa_ie);
++ wpa_ie_len += 2 + 4;
++ }
++
++ if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
++ u8 *pos = wpa_ie + wpa_ie_len;
++
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 4;
++ WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
++ pos += 4;
++ wpa_hexdump(MSG_MSGDUMP, "RSNE Override 2",
++ wpa_ie, pos - wpa_ie);
++ wpa_ie_len += 2 + 4;
++ }
++ }
++
+ params->wpa_ie = wpa_ie;
+ params->wpa_ie_len = wpa_ie_len;
+ params->auth_alg = algs;
+@@ -8557,6 +8608,28 @@ int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
+ }
+
+
++static bool wpas_driver_rsn_override(struct wpa_supplicant *wpa_s)
++{
++ return !!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_RSN_OVERRIDE_STA);
++}
++
++
++bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s)
++{
++ if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_DISABLED)
++ return false;
++
++ if (wpa_s->conf->rsn_overriding == RSN_OVERRIDING_ENABLED)
++ return true;
++
++ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
++ wpas_driver_bss_selection(wpa_s))
++ return wpas_driver_rsn_override(wpa_s);
++
++ return true;
++}
++
++
+ #if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
+ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+@@ -9531,3 +9604,58 @@ bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled)
+
+ return false;
+ }
++
++
++bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
++ struct wpa_bss *bss)
++{
++ int i;
++
++ if (!bss)
++ return false;
++ if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
++ wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
++ return true;
++
++ if (!wpa_s->valid_links)
++ return false;
++
++ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
++ if (!(wpa_s->valid_links & BIT(i)))
++ continue;
++ if (wpa_s->links[i].bss &&
++ (wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
++ RSNE_OVERRIDE_IE_VENDOR_TYPE) ||
++ wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
++ RSNE_OVERRIDE_2_IE_VENDOR_TYPE)))
++ return true;
++ }
++
++ return false;
++}
++
++
++bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
++ struct wpa_bss *bss)
++{
++ int i;
++
++ if (!bss)
++ return false;
++ if (wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
++ return true;
++
++ if (!wpa_s->valid_links)
++ return false;
++
++ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
++ if (!(wpa_s->valid_links & BIT(i)))
++ continue;
++ if (wpa_s->links[i].bss &&
++ wpa_bss_get_vendor_ie(wpa_s->links[i].bss,
++ RSNE_OVERRIDE_2_IE_VENDOR_TYPE))
++ return true;
++ }
++
++ return false;
++}
+diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
+index b08f5417a..b721f6504 100644
+--- a/wpa_supplicant/wpa_supplicant.conf
++++ b/wpa_supplicant/wpa_supplicant.conf
+@@ -878,6 +878,15 @@ fast_reauth=1
+ # 1 = auto: Activate Extended Key ID support if the driver supports it
+ #extended_key_id=0
+
++# RSN overriding
++# NOTE: The protocol used for this mechanism is still subject to change and as
++# such, this should not yet be enabled for production uses to avoid issues if
++# something were to change.
++# 0 = Disabled (default)
++# 1 = Enabled automatically if the driver indicates support
++# 2 = Forced to be enabled even without driver capability indication
++#rsn_overriding=0
++
+ # network block
+ #
+ # Each network (usually AP's sharing the same SSID) is configured as a separate
+diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
+index e92f6b147..3043bc654 100644
+--- a/wpa_supplicant/wpa_supplicant_i.h
++++ b/wpa_supplicant/wpa_supplicant_i.h
+@@ -1727,6 +1727,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ void fils_connection_failure(struct wpa_supplicant *wpa_s);
+ void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
+ int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
++bool wpas_rsn_overriding(struct wpa_supplicant *wpa_s);
+ int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
+ void wpas_auth_failed(struct wpa_supplicant *wpa_s, const char *reason,
+ const u8 *bssid);
+@@ -2011,5 +2012,9 @@ bool wpas_is_6ghz_supported(struct wpa_supplicant *wpa_s, bool only_enabled);
+
+ bool wpa_is_non_eht_scs_traffic_desc_supported(struct wpa_bss *bss);
+ bool wpas_ap_link_address(struct wpa_supplicant *wpa_s, const u8 *addr);
++bool wpas_ap_supports_rsn_overriding(struct wpa_supplicant *wpa_s,
++ struct wpa_bss *bss);
++bool wpas_ap_supports_rsn_overriding_2(struct wpa_supplicant *wpa_s,
++ struct wpa_bss *bss);
+
+ #endif /* WPA_SUPPLICANT_I_H */
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,415 @@
+From 62ca121f9625ffe16b2d5764568bf6ccffd7d64e Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Mon, 29 Jul 2024 15:41:59 +0300
+Subject: [PATCH 10/11] RSNO: Use the RSN Selection element to indicate which
+ variant was used
+
+This replaces the use of the RSNE Override and RSNE Override 2 elements
+with empty payload to indicate which RSNE variant was used.
+
+In addition, this adds stricter validation of the RSNE in
+(Re)Association Request frame to allow only the pairwise cipher suites
+and AKMs listed in the indicated RSNE variant to be used.
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=62ca121f9625ffe16b2d5764568bf6ccffd7d64e]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/common/ieee802_11_common.c | 9 +++++++
+ src/common/ieee802_11_common.h | 2 ++
+ src/common/ieee802_11_defs.h | 2 ++
+ src/common/wpa_common.c | 6 +++++
+ src/common/wpa_common.h | 10 +++++++
+ src/rsn_supp/wpa.c | 38 +++++++++++++++++++++++++-
+ src/rsn_supp/wpa.h | 8 ++++++
+ src/rsn_supp/wpa_i.h | 2 ++
+ wpa_supplicant/events.c | 22 ++++++++++++++-
+ wpa_supplicant/sme.c | 36 ++++++++++++++++++-------
+ wpa_supplicant/wpa_supplicant.c | 47 +++++++++++++++++++++++----------
+ 11 files changed, 157 insertions(+), 25 deletions(-)
+
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index 3ca1ffe7e..3e6fba5bd 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -148,6 +148,15 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
+ elems->rsne_override_2 = pos;
+ elems->rsne_override_2_len = elen;
+ break;
++ case WFA_RSN_SELECTION_OUI_TYPE:
++ if (elen < 4 + 1) {
++ wpa_printf(MSG_DEBUG,
++ "Too short RSN Selection element ignored");
++ return -1;
++ }
++ elems->rsn_selection = pos + 4;
++ elems->rsn_selection_len = elen - 4;
++ break;
+ default:
+ wpa_printf(MSG_MSGDUMP, "Unknown WFA "
+ "information element ignored "
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 46a86096e..d4c691e1b 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -118,6 +118,7 @@ struct ieee802_11_elems {
+ const u8 *mbssid;
+ const u8 *rsne_override;
+ const u8 *rsne_override_2;
++ const u8 *rsn_selection;
+
+ u8 ssid_len;
+ u8 supp_rates_len;
+@@ -183,6 +184,7 @@ struct ieee802_11_elems {
+ u8 mbssid_len;
+ size_t rsne_override_len;
+ size_t rsne_override_2_len;
++ size_t rsn_selection_len;
+
+ struct mb_ies_info mb_ies;
+
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index e2c132a40..db9e90355 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -1449,9 +1449,11 @@ struct ieee80211_ampe_ie {
+ #define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29
+ #define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a
+ #define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b
++#define WFA_RSN_SELECTION_OUI_TYPE 0x2c
+ #define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29
+ #define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a
+ #define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
++#define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c
+
+ #define MULTI_AP_SUB_ELEM_TYPE 0x06
+ #define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
+diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
+index 8eb4a1dab..bfaca9128 100644
+--- a/src/common/wpa_common.c
++++ b/src/common/wpa_common.c
+@@ -3629,6 +3629,12 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
+ return 0;
+ }
+
++ if (selector == RSN_SELECTION_IE_VENDOR_TYPE) {
++ ie->rsn_selection = p;
++ ie->rsn_selection_len = left;
++ return 0;
++ }
++
+ return 2;
+ }
+
+diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
+index 1e3136843..c8cdf748d 100644
+--- a/src/common/wpa_common.h
++++ b/src/common/wpa_common.h
+@@ -643,6 +643,14 @@ struct wpa_pasn_params_data {
+ #define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
+ #define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
+
++/* WPA3 specification - RSN Selection element */
++enum rsn_selection_variant {
++ RSN_SELECTION_RSNE = 0,
++ RSN_SELECTION_RSNE_OVERRIDE = 1,
++ RSN_SELECTION_RSNE_OVERRIDE_2 = 2,
++};
++
++
+ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
+ int key_mgmt, bool reassoc_resp);
+ void wpa_ft_parse_ies_free(struct wpa_ft_ies *parse);
+@@ -704,6 +712,8 @@ struct wpa_eapol_ie_parse {
+ u16 aid;
+ const u8 *wmm;
+ size_t wmm_len;
++ const u8 *rsn_selection;
++ size_t rsn_selection_len;
+ u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */
+ const u8 *mlo_gtk[MAX_NUM_MLD_LINKS];
+ size_t mlo_gtk_len[MAX_NUM_MLD_LINKS];
+diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
+index e48982989..9b13b3a84 100644
+--- a/src/rsn_supp/wpa.c
++++ b/src/rsn_supp/wpa.c
+@@ -531,7 +531,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
+ size_t mic_len, hdrlen, rlen, extra_len = 0;
+ struct wpa_eapol_key *reply;
+ u8 *rbuf, *key_mic;
+- u8 *rsn_ie_buf = NULL;
++ u8 *rsn_ie_buf = NULL, *buf2 = NULL;
+ u16 key_info;
+ #ifdef CONFIG_TESTING_OPTIONS
+ size_t pad_len = 0;
+@@ -581,6 +581,37 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
+ }
+ #endif /* CONFIG_IEEE80211R */
+
++ if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) {
++ u8 *pos;
++
++ buf2 = os_malloc(wpa_ie_len + 2 + 4 + 1);
++ if (!buf2) {
++ os_free(rsn_ie_buf);
++ return -1;
++ }
++ os_memcpy(buf2, wpa_ie, wpa_ie_len);
++ pos = buf2 + wpa_ie_len;
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 4 + 1;
++ WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
++ pos += 4;
++ if (sm->rsn_override == RSN_OVERRIDE_RSNE) {
++ *pos++ = RSN_SELECTION_RSNE;
++ } else if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) {
++ *pos++ = RSN_SELECTION_RSNE_OVERRIDE;
++ } else if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE_2) {
++ *pos++ = RSN_SELECTION_RSNE_OVERRIDE_2;
++ } else {
++ os_free(rsn_ie_buf);
++ os_free(buf2);
++ return -1;
++ }
++
++ wpa_ie = buf2;
++ wpa_ie_len += 2 + 4 + 1;
++
++ }
++
+ wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
+
+ #ifdef CONFIG_TESTING_OPTIONS
+@@ -601,6 +632,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
+ &rlen, (void *) &reply);
+ if (rbuf == NULL) {
+ os_free(rsn_ie_buf);
++ os_free(buf2);
+ return -1;
+ }
+
+@@ -633,6 +665,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
+ WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len + extra_len);
+ os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
+ os_free(rsn_ie_buf);
++ os_free(buf2);
+ #ifdef CONFIG_TESTING_OPTIONS
+ if (sm->test_eapol_m2_elems) {
+ os_memcpy(key_mic + mic_len + 2 + wpa_ie_len,
+@@ -4767,6 +4800,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
+ case WPA_PARAM_SSID_PROTECTION:
+ sm->ssid_protection = value;
+ break;
++ case WPA_PARAM_RSN_OVERRIDE:
++ sm->rsn_override = value;
++ break;
+ default:
+ break;
+ }
+diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
+index 2bef093e3..f8346e1ef 100644
+--- a/src/rsn_supp/wpa.h
++++ b/src/rsn_supp/wpa.h
+@@ -137,6 +137,14 @@ enum wpa_sm_conf_params {
+ WPA_PARAM_ENCRYPT_EAPOL_M4,
+ WPA_PARAM_FT_PREPEND_PMKID,
+ WPA_PARAM_SSID_PROTECTION,
++ WPA_PARAM_RSN_OVERRIDE,
++};
++
++enum wpa_rsn_override {
++ RSN_OVERRIDE_NOT_USED,
++ RSN_OVERRIDE_RSNE,
++ RSN_OVERRIDE_RSNE_OVERRIDE,
++ RSN_OVERRIDE_RSNE_OVERRIDE_2,
+ };
+
+ struct rsn_supp_config {
+diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
+index d7e780519..6e4797577 100644
+--- a/src/rsn_supp/wpa_i.h
++++ b/src/rsn_supp/wpa_i.h
+@@ -229,6 +229,8 @@ struct wpa_sm {
+ bool wmm_enabled;
+ bool driver_bss_selection;
+ bool ft_prepend_pmkid;
++
++ enum wpa_rsn_override rsn_override;
+ };
+
+
+diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
+index 4393c469c..93191c7fe 100644
+--- a/wpa_supplicant/events.c
++++ b/wpa_supplicant/events.c
+@@ -3368,9 +3368,10 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+ {
+ int l, len, found = 0, found_x = 0, wpa_found, rsn_found;
+- const u8 *p;
++ const u8 *p, *ie;
+ u8 bssid[ETH_ALEN];
+ bool bssid_known;
++ enum wpa_rsn_override rsn_override;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
+ wpa_s->ssid_verified = false;
+@@ -3482,6 +3483,25 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
+ if (!found_x && data->assoc_info.req_ies)
+ wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
+
++ rsn_override = RSN_OVERRIDE_NOT_USED;
++ ie = get_vendor_ie(data->assoc_info.req_ies,
++ data->assoc_info.req_ies_len,
++ RSN_SELECTION_IE_VENDOR_TYPE);
++ if (ie && ie[1] >= 4 + 1) {
++ switch (ie[2 + 4]) {
++ case RSN_SELECTION_RSNE:
++ rsn_override = RSN_OVERRIDE_RSNE;
++ break;
++ case RSN_SELECTION_RSNE_OVERRIDE:
++ rsn_override = RSN_OVERRIDE_RSNE_OVERRIDE;
++ break;
++ case RSN_SELECTION_RSNE_OVERRIDE_2:
++ rsn_override = RSN_OVERRIDE_RSNE_OVERRIDE_2;
++ break;
++ }
++ }
++ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE, rsn_override);
++
+ #ifdef CONFIG_FILS
+ #ifdef CONFIG_SME
+ if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
+diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
+index 292897edd..443b0b667 100644
+--- a/wpa_supplicant/sme.c
++++ b/wpa_supplicant/sme.c
+@@ -2467,26 +2467,44 @@ mscs_fail:
+ wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
+ }
+
++ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_NOT_USED);
+ if (wpas_rsn_overriding(wpa_s) &&
+ wpas_ap_supports_rsn_overriding(wpa_s, wpa_s->current_bss) &&
+ wpa_s->sme.assoc_req_ie_len + 2 + 4 <=
+ sizeof(wpa_s->sme.assoc_req_ie)) {
+ u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
+- u32 type = 0;
+ const u8 *ie;
++ enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
+
++ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_RSNE);
+ ie = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, ssid,
+ wpa_s->valid_links);
+- if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
+- type = WPA_GET_BE32(&ie[2]);
++ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
++ u32 type;
+
+- if (type) {
+- /* Indicate support for RSN overriding */
+- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+- *pos++ = 4;
+- WPA_PUT_BE32(pos, type);
+- wpa_s->sme.assoc_req_ie_len += 2 + 4;
++ type = WPA_GET_BE32(&ie[2]);
++ if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
++ variant = RSN_SELECTION_RSNE_OVERRIDE;
++ wpa_sm_set_param(wpa_s->wpa,
++ WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_RSNE_OVERRIDE);
++ } else if (type == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
++ variant = RSN_SELECTION_RSNE_OVERRIDE_2;
++ wpa_sm_set_param(wpa_s->wpa,
++ WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_RSNE_OVERRIDE_2);
++ }
+ }
++
++ /* Indicate which RSNE variant was used */
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 4 + 1;
++ WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
++ pos += 4;
++ *pos = variant;
++ wpa_s->sme.assoc_req_ie_len += 2 + 4 + 1;
+ }
+
+ params.bssid = bssid;
+diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
+index 3203446f1..81eadbc9b 100644
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -3943,32 +3943,51 @@ mscs_end:
+ wpa_ie_len += multi_ap_ie_len;
+ }
+
++ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_NOT_USED);
+ if (!wpas_driver_bss_selection(wpa_s) &&
+ wpas_rsn_overriding(wpa_s) &&
+ wpas_ap_supports_rsn_overriding(wpa_s, bss) &&
+- wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
+- u8 *pos = wpa_ie + wpa_ie_len;
+- u32 type = 0;
++ wpa_ie_len + 2 + 4 + 1 <= max_wpa_ie_len) {
++ u8 *pos = wpa_ie + wpa_ie_len, *start = pos;
+ const u8 *ie;
++ enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
+
++ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_RSNE);
+ ie = wpa_bss_get_rsne(wpa_s, bss, ssid, wpa_s->valid_links);
+- if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4)
+- type = WPA_GET_BE32(&ie[2]);
++ if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
++ u32 type;
+
+- if (type) {
+- /* Indicate support for RSN overriding */
+- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+- *pos++ = 4;
+- WPA_PUT_BE32(pos, type);
+- pos += 4;
+- wpa_hexdump(MSG_MSGDUMP, "RSNE Override", wpa_ie,
+- pos - wpa_ie);
+- wpa_ie_len += 2 + 4;
++ type = WPA_GET_BE32(&ie[2]);
++ if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
++ variant = RSN_SELECTION_RSNE_OVERRIDE;
++ wpa_sm_set_param(wpa_s->wpa,
++ WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_RSNE_OVERRIDE);
++ } else if (type == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
++ variant = RSN_SELECTION_RSNE_OVERRIDE_2;
++ wpa_sm_set_param(wpa_s->wpa,
++ WPA_PARAM_RSN_OVERRIDE,
++ RSN_OVERRIDE_RSNE_OVERRIDE_2);
++ }
+ }
++
++ /* Indicate which RSNE variant was used */
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 4 + 1;
++ WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
++ pos += 4;
++ *pos++ = variant;
++ wpa_hexdump(MSG_MSGDUMP, "RSN Selection", start, pos - start);
++ wpa_ie_len += pos - start;
+ }
+
+ if (wpas_driver_bss_selection(wpa_s) &&
+ wpas_rsn_overriding(wpa_s)) {
++ /* TODO: Replace this indication of support for RSN overriding
++ * to the driver in driver-based BSS selection cases with
++ * something cleaner. */
+ if (wpa_ie_len + 2 + 4 <= max_wpa_ie_len) {
+ u8 *pos = wpa_ie + wpa_ie_len;
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,84 @@
+From 6f522baa1b445536b3aa7ea0d3a28475fa91e644 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <quic_jouni@quicinc.com>
+Date: Mon, 29 Jul 2024 16:43:50 +0300
+Subject: [PATCH 11/11] RSNO: Use SNonce cookie to indicate support for RSN
+ overriding
+
+This provides an implicitly protected (SNonce is used as an input to PTK
+derivation) mechanism for a STA to indicate support for RSN overriding
+in a manner that does not cause interopability issues with deployed APs.
+
+In addition, update sm->SNonce on the Authenticator only based on
+message 2/4 since that is the only EAPOL-Key message that is defined to
+provide the actual SNonce value. While clearing of this internal buffer
+on message 4/4 might not cause issues, it is better to keep the actual
+SNonce value here since the SNonce cookie can be used at a later point
+in the sequence.
+
+Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
+
+Upstream-Status: Backport [https://git.w1.fi/cgit/hostap/commit/?h=hostap_2_11&id=6f522baa1b445536b3aa7ea0d3a28475fa91e644]
+Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com>
+---
+ src/common/wpa_common.c | 21 +++++++++++++++++++++
+ src/common/wpa_common.h | 3 +++
+ src/rsn_supp/wpa.c | 2 ++
+ 3 files changed, 26 insertions(+)
+
+diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
+index bfaca9128..4f58f0737 100644
+--- a/src/common/wpa_common.c
++++ b/src/common/wpa_common.c
+@@ -4274,3 +4274,24 @@ int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len)
+ }
+
+ #endif /* CONFIG_PASN */
++
++
++void rsn_set_snonce_cookie(u8 *snonce)
++{
++ u8 *pos;
++
++ pos = snonce + WPA_NONCE_LEN - 6;
++ WPA_PUT_BE24(pos, OUI_WFA);
++ pos += 3;
++ WPA_PUT_BE24(pos, 0x000029);
++}
++
++
++bool rsn_is_snonce_cookie(const u8 *snonce)
++{
++ const u8 *pos;
++
++ pos = snonce + WPA_NONCE_LEN - 6;
++ return WPA_GET_BE24(pos) == OUI_WFA &&
++ WPA_GET_BE24(pos + 3) == 0x000029;
++}
+diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
+index c8cdf748d..4cb5b8c60 100644
+--- a/src/common/wpa_common.h
++++ b/src/common/wpa_common.h
+@@ -797,4 +797,7 @@ int wpa_pasn_parse_parameter_ie(const u8 *data, u8 len, bool from_ap,
+ void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab);
+ int wpa_pasn_add_extra_ies(struct wpabuf *buf, const u8 *extra_ies, size_t len);
+
++void rsn_set_snonce_cookie(u8 *snonce);
++bool rsn_is_snonce_cookie(const u8 *snonce);
++
+ #endif /* WPA_COMMON_H */
+diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
+index 9b13b3a84..0a1d4d07f 100644
+--- a/src/rsn_supp/wpa.c
++++ b/src/rsn_supp/wpa.c
+@@ -1023,6 +1023,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
+ "WPA: Failed to get random data for SNonce");
+ goto failed;
+ }
++ if (sm->rsn_override != RSN_OVERRIDE_NOT_USED)
++ rsn_set_snonce_cookie(sm->snonce);
+ sm->renew_snonce = 0;
+ wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
+ sm->snonce, WPA_NONCE_LEN);
+--
+2.34.1
+
@@ -19,6 +19,17 @@ SRC_URI = "http://w1.fi/releases/wpa_supplicant-${PV}.tar.gz \
file://0002-defconfig-Update-Opportunistic-Wireless-Encryption-O.patch \
file://0003-defconfig-Document-IEEE-802.11be-as-a-published-amen.patch \
file://0004-defconfig-Uncomment-CONFIG_IEEE80211BE-y.patch \
+ file://0005-Define-WFA-vendor-specific-element-types-for-RSNE-RS.patch \
+ file://0006-Add-RSN-overriding-elements-into-IE-parsing.patch \
+ file://0007-Allow-RSNE-Override-element-to-override-RSNE-content.patch \
+ file://0008-Allow-RSNXE-Override-element-to-override-RSNXE-conte.patch \
+ file://0009-Add-QCA-vendor-feature-flags-to-indicate-RSN-overrid.patch \
+ file://0010-nl80211-Add-a-capability-flag-for-RSN-overriding.patch \
+ file://0011-Use-helper-functions-to-access-RSNE-RSNXE-from-BSS-e.patch \
+ file://0012-Make-driver-capabilities-for-AKM-suites-available-wi.patch \
+ file://0013-RSNE-RSNXE-overriding-for-STA.patch \
+ file://0014-RSNO-Use-the-RSN-Selection-element-to-indicate-which.patch \
+ file://0015-RSNO-Use-SNonce-cookie-to-indicate-support-for-RSN-o.patch \
file://CVE-2025-24912-01.patch \
file://CVE-2025-24912-02.patch \
"
Fix WFA test case 5.2.3.3 "STAUT forward compatibility to an AP with various AKMs in RSN IE" failure caused by missing SNonce_Cookie handling. During the 2EAPMSG exchange, the STA did not apply the SNonce_Cookie provided by the AP as required by the test specification, resulting in sniffer validation failure. To address this, add full support for RSN/RSNX overriding for STA mode and explicitly signal SNonce_Cookie–based override capability. Change-Id: I443bdc00b1983db1a8a97ffa3f1f4998cd826a86 Signed-off-by: Jiacheng Shi <jiacheng.shi@oss.qualcomm.com> --- ...r-specific-element-types-for-RSNE-RS.patch | 34 + ...-overriding-elements-into-IE-parsing.patch | 58 ++ ...ide-element-to-override-RSNE-content.patch | 36 + ...ride-element-to-override-RSNXE-conte.patch | 36 + ...eature-flags-to-indicate-RSN-overrid.patch | 67 ++ ...a-capability-flag-for-RSN-overriding.patch | 65 ++ ...ions-to-access-RSNE-RSNXE-from-BSS-e.patch | 448 +++++++++++ ...bilities-for-AKM-suites-available-wi.patch | 66 ++ .../0013-RSNE-RSNXE-overriding-for-STA.patch | 739 ++++++++++++++++++ ...-Selection-element-to-indicate-which.patch | 415 ++++++++++ ...cookie-to-indicate-support-for-RSN-o.patch | 84 ++ .../wpa-supplicant/wpa-supplicant_2.11.bb | 11 + 12 files changed, 2059 insertions(+) create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0005-Define-WFA-vendor-specific-element-types-for-RSNE-RS.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0006-Add-RSN-overriding-elements-into-IE-parsing.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0007-Allow-RSNE-Override-element-to-override-RSNE-content.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0008-Allow-RSNXE-Override-element-to-override-RSNXE-conte.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0009-Add-QCA-vendor-feature-flags-to-indicate-RSN-overrid.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0010-nl80211-Add-a-capability-flag-for-RSN-overriding.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0011-Use-helper-functions-to-access-RSNE-RSNXE-from-BSS-e.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0012-Make-driver-capabilities-for-AKM-suites-available-wi.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0013-RSNE-RSNXE-overriding-for-STA.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0014-RSNO-Use-the-RSN-Selection-element-to-indicate-which.patch create mode 100644 meta/recipes-connectivity/wpa-supplicant/wpa-supplicant/0015-RSNO-Use-SNonce-cookie-to-indicate-support-for-RSN-o.patch