[wpa_supplicant] Cumulative patch from c4e90da6d

Bug: 124017368
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: DPP functional test.
Test: Regression test passed (Bug: 124052942)

c4e90da6d MBO: Move the WNM-Notification subtype definitions to common location
105b14f54 HS 2.0: Update the T&C Acceptance subtype value
65b487ae5 HS 2.0: Add QUIET=1 support for building hs20-osu-client
73f285dad Add FT-PSK to GET_CAPABILITY key_mgmt
6110753b1 nl80211: Clear PMKID add command message buffer
0fa33e05b nl80211: Clear connect command message buffer
b14e8ea1d nl80211: Request kernel to trim off payload of netlink requests from acks
789b48bb4 EAP peer: Clear temporary message buffers before freeing
8f99a3c26 Clear config item writing buffer before freeing it
a68e9b698 D-Bus: Fix P2P DeleteService dict iteration
0607346f1 D-Bus: Fix a memory leak in DeleteService handler
d05dda61d PEAP: Explicitly clear temporary keys from memory when using CMK
4e1cd3468 EAP-PEAP: Derive EMSK and use 128-octet derivation for MSK
d8c20ec59 DPP: Clear dpp_listen_freq on remain-on-channel failure
59fa20538 P2P: Allow the avoid channels for P2P discovery/negotiation
e34cd9f06 WNM: Fix WNM-Sleep Mode Request bounds checking
159a7fbde crl_reload_interval: Add CRL reloading support
83c860813 AP: Add wpa_psk_file reloading in runtime
ec5c39a55 AP: Allow identifying which passphrase station used with wpa_psk_file
b08c9ad0c AP: Expose PMK outside of wpa_auth module
89896c000 tests: Use python3 compatible print statement
bab493b90 tests: Use python3 compatible "except" statement
0dab47733 Write multi_ap_backhaul_sta to wpa_supplicant config
98251c6f2 dbus: Document more possible BSS/RSA/KeyMgmt values
1e591df06 Check supported types in wpas_mac_addr_rand_scan_set()
c85249aa1 Fix test compilation error related to sme_event_unprot_disconnect()
42d308635 SAE: Advertise Password Identifier use
59c693064 HS 2.0 server: Command line option to fetch the version information
2d1762fa4 HS 2.0 server: Alternative subrem updateNode for certificate credentials
d97cf2a11 HS 2.0 server: Use noMOUpdate in client certificate subrem
13a200a92 FILS: Remove notes about experimental implementation
86d4e0537 dbus: Expose support of SAE key management in BSS properties

Change-Id: I83ffca34ff5349c226db6215ff1ae35c3b7ab335
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index 61d2f65..27c69d3 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -12,6 +12,7 @@
 #include "utils/eloop.h"
 #include "common/ieee802_11_defs.h"
 #include "common/wpa_ctrl.h"
+#include "common/ocv.h"
 #include "ap/hostapd.h"
 #include "ap/sta_info.h"
 #include "ap/ap_config.h"
@@ -54,8 +55,8 @@
 	size_t gtk_elem_len = 0;
 	size_t igtk_elem_len = 0;
 	struct wnm_sleep_element wnmsleep_ie;
-	u8 *wnmtfs_ie;
-	u8 wnmsleep_ie_len;
+	u8 *wnmtfs_ie, *oci_ie;
+	u8 wnmsleep_ie_len, oci_ie_len;
 	u16 wnmtfs_ie_len;
 	u8 *pos;
 	struct sta_info *sta;
@@ -88,10 +89,42 @@
 		wnmtfs_ie = NULL;
 	}
 
+	oci_ie = NULL;
+	oci_ie_len = 0;
+#ifdef CONFIG_OCV
+	if (action_type == WNM_SLEEP_MODE_EXIT &&
+	    wpa_auth_uses_ocv(sta->wpa_sm)) {
+		struct wpa_channel_info ci;
+
+		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to get channel info for OCI element in WNM-Sleep Mode frame");
+			os_free(wnmtfs_ie);
+			return -1;
+		}
+
+		oci_ie_len = OCV_OCI_EXTENDED_LEN;
+		oci_ie = os_zalloc(oci_ie_len);
+		if (!oci_ie) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to allocate buffer for OCI element in WNM-Sleep Mode frame");
+			os_free(wnmtfs_ie);
+			return -1;
+		}
+
+		if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
+			os_free(wnmtfs_ie);
+			os_free(oci_ie);
+			return -1;
+		}
+	}
+#endif /* CONFIG_OCV */
+
 #define MAX_GTK_SUBELEM_LEN 45
 #define MAX_IGTK_SUBELEM_LEN 26
 	mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len +
-			 MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN);
+			 MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN +
+			 oci_ie_len);
 	if (mgmt == NULL) {
 		wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
 			   "WNM-Sleep Response action frame");
@@ -134,11 +167,18 @@
 	os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len);
 	/* copy TFS IE here */
 	pos += wnmsleep_ie_len;
-	if (wnmtfs_ie)
+	if (wnmtfs_ie) {
 		os_memcpy(pos, wnmtfs_ie, wnmtfs_ie_len);
+		pos += wnmtfs_ie_len;
+	}
+#ifdef CONFIG_OCV
+	/* copy OCV OCI here */
+	if (oci_ie_len > 0)
+		os_memcpy(pos, oci_ie, oci_ie_len);
+#endif /* CONFIG_OCV */
 
 	len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len +
-		igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len;
+		igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len;
 
 	/* In driver, response frame should be forced to sent when STA is in
 	 * PS mode */
@@ -185,6 +225,7 @@
 #undef MAX_IGTK_SUBELEM_LEN
 fail:
 	os_free(wnmtfs_ie);
+	os_free(oci_ie);
 	os_free(mgmt);
 	return res;
 }
@@ -201,6 +242,11 @@
 	u8 *tfsreq_ie_start = NULL;
 	u8 *tfsreq_ie_end = NULL;
 	u16 tfsreq_ie_len = 0;
+#ifdef CONFIG_OCV
+	struct sta_info *sta;
+	const u8 *oci_ie = NULL;
+	u8 oci_ie_len = 0;
+#endif /* CONFIG_OCV */
 
 	if (!hapd->conf->wnm_sleep_mode) {
 		wpa_printf(MSG_DEBUG, "Ignore WNM-Sleep Mode Request from "
@@ -228,6 +274,12 @@
 			if (!tfsreq_ie_start)
 				tfsreq_ie_start = (u8 *) pos;
 			tfsreq_ie_end = (u8 *) pos;
+#ifdef CONFIG_OCV
+		} else if (*pos == WLAN_EID_EXTENSION && ie_len >= 1 &&
+			   pos[2] == WLAN_EID_EXT_OCV_OCI) {
+			oci_ie = pos + 3;
+			oci_ie_len = ie_len - 1;
+#endif /* CONFIG_OCV */
 		} else
 			wpa_printf(MSG_DEBUG, "WNM: EID %d not recognized",
 				   *pos);
@@ -239,6 +291,27 @@
 		return;
 	}
 
+#ifdef CONFIG_OCV
+	sta = ap_get_sta(hapd, addr);
+	if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT &&
+	    sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
+		struct wpa_channel_info ci;
+
+		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to get channel info to validate received OCI in WNM-Sleep Mode frame");
+			return;
+		}
+
+		if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci,
+					 channel_width_to_int(ci.chanwidth),
+					 ci.seg1_idx) != 0) {
+			wpa_msg(hapd, MSG_WARNING, "WNM: %s", ocv_errorstr);
+			return;
+		}
+	}
+#endif /* CONFIG_OCV */
+
 	if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_ENTER &&
 	    tfsreq_ie_start && tfsreq_ie_end &&
 	    tfsreq_ie_end - tfsreq_ie_start >= 0) {