Merge "hostapd: support for 60GHz SoftAP"
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 3590b09..91cdefe 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -69,6 +69,10 @@
 endif
 endif
 
+ifdef CONFIG_TESTING_OPTIONS
+L_CFLAGS += -DCONFIG_TESTING_OPTIONS
+CONFIG_WPS_TESTING=y
+endif
 
 ifndef CONFIG_OS
 ifdef CONFIG_NATIVE_WINDOWS
diff --git a/hostapd/android.config b/hostapd/android.config
index f791daa..fd3c1a1 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -244,3 +244,11 @@
 # This can be used to enable functionality to improve interworking with
 # external networks.
 CONFIG_INTERWORKING=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are useful for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+# Each test case requires a flag set in hostapd.conf or through hostapd_cli
+#CONFIG_TESTING_OPTIONS=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index ce32f3c..efbfd80 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4184,6 +4184,10 @@
 		bss->oci_freq_override_fils_assoc = atoi(pos);
 	} else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) {
 		bss->oci_freq_override_wnm_sleep = atoi(pos);
+	} else if (os_strcmp(buf, "skip_send_eapol") == 0) {
+		conf->skip_send_eapol = atoi(pos);
+	} else if (os_strcmp(buf, "enable_eapol_large_timeout") == 0) {
+		conf->enable_eapol_large_timeout = atoi(pos);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_SAE
 	} else if (os_strcmp(buf, "sae_password") == 0) {
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 30fa47f..02b41fd 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1504,6 +1504,10 @@
 			wpa_auth_set_ocv_override_freq(
 				hapd->wpa_auth,
 				WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value));
+		else if (os_strcasecmp(cmd, "skip_send_eapol") == 0)
+			wpa_auth_set_skip_send_eapol(hapd->wpa_auth, atoi(value));
+		else if (os_strcasecmp(cmd, "enable_eapol_large_timeout") == 0)
+			wpa_auth_set_enable_eapol_large_timeout(hapd->wpa_auth, atoi(value));
 #endif /* CONFIG_TESTING_OPTIONS */
 	}
 
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index 41ac89c..1a342e5 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -588,6 +588,23 @@
 	}
 }
 
+bool forceStaDisconnection(struct hostapd_data* hapd,
+			   const std::array<uint8_t, 6>& client_address,
+			   const uint16_t reason_code) {
+	struct sta_info *sta;
+	for (sta = hapd->sta_list; sta; sta = sta->next) {
+		int res;
+		res = memcmp(sta->addr, client_address.data(), ETH_ALEN);
+		if (res == 0) {
+			wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
+			    MAC2STR(client_address.data()), reason_code);
+			ap_sta_disconnect(hapd, sta, sta->addr, reason_code);
+			return true;
+		}
+	}
+	return false;
+}
+
 // hostapd core functions accept "C" style function pointers, so use global
 // functions to pass to the hostapd core function and store the corresponding
 // std::function methods to be invoked.
@@ -884,7 +901,9 @@
 		   enum wpa_msg_type type, const char *txt,
 		   size_t len) {
 		wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
-		if (os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
+		if (os_strncmp(txt, AP_EVENT_ENABLED,
+			       strlen(AP_EVENT_ENABLED)) == 0 ||
+		    os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
 			       strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
 		    for (const auto &callback : callbacks_) {
 			callback->onApInstanceInfoChanged(
@@ -952,20 +971,29 @@
     const std::array<uint8_t, 6>& client_address, V1_2::Ieee80211ReasonCode reason_code)
 {
 	struct hostapd_data *hapd = hostapd_get_iface(interfaces_, iface_name.c_str());
-	struct sta_info *sta;
+	bool result;
+	if (!hapd) {
+	    for (auto const& iface : br_interfaces_) {
+		if (iface.first == iface_name) {
+		    for (auto const& instance : iface.second) {
+			hapd = hostapd_get_iface(interfaces_, instance.c_str());
+			if (hapd) {
+				result = forceStaDisconnection(hapd, client_address,
+							       (uint16_t) reason_code);
+				if (result) break;
+			}
+		    }
+		}
+	    }
+	} else {
+		result = forceStaDisconnection(hapd, client_address, (uint16_t) reason_code);
+	}
 	if (!hapd) {
 		wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
 		return {V1_2::HostapdStatusCode::FAILURE_IFACE_UNKNOWN, ""};
 	}
-	for (sta = hapd->sta_list; sta; sta = sta->next) {
-		int res;
-		res = memcmp(sta->addr, client_address.data(), ETH_ALEN);
-		if (res == 0) {
-			wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
-			    MAC2STR(client_address.data()), (uint16_t) reason_code);
-			ap_sta_disconnect(hapd, sta, sta->addr, (uint16_t) reason_code);
-			return {V1_2::HostapdStatusCode::SUCCESS, ""};
-		}
+	if (result) {
+		return {V1_2::HostapdStatusCode::SUCCESS, ""};
 	}
 	return {V1_2::HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, ""};
 }
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 04535a1..f0e4236 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -252,6 +252,8 @@
 	conf->ignore_reassoc_probability = 0.0;
 	conf->corrupt_gtk_rekey_mic_probability = 0.0;
 	conf->ecsa_ie_only = 0;
+	conf->skip_send_eapol = 0;
+	conf->enable_eapol_large_timeout = 0;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	conf->acs = 0;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index bada04c..0cb4b52 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1005,6 +1005,8 @@
 	double ignore_reassoc_probability;
 	double corrupt_gtk_rekey_mic_probability;
 	int ecsa_ie_only;
+	unsigned int skip_send_eapol;
+	unsigned int enable_eapol_large_timeout;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_ACS
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 9d74bfc..e48894f 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -188,6 +188,10 @@
 {
 	if (!wpa_auth->cb->send_eapol)
 		return -1;
+#ifdef CONFIG_TESTING_OPTIONS
+	if (wpa_auth->conf.skip_send_eapol)
+		return 0;
+#endif
 	return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
 					encrypt);
 }
@@ -1663,7 +1667,7 @@
 
 	wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
 	wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
-			    sm->pairwise_set);
+			sm->pairwise_set);
 	os_free(hdr);
 }
 
@@ -1698,6 +1702,11 @@
 #ifdef TEST_FUZZ
 	timeout_ms = 1;
 #endif /* TEST_FUZZ */
+#ifdef CONFIG_TESTING_OPTIONS
+	if(wpa_auth->conf.enable_eapol_large_timeout) {
+		timeout_ms = 50 * 1000;
+	}
+#endif
 	wpa_printf(MSG_DEBUG,
 		   "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
 		   timeout_ms, ctr);
@@ -5612,4 +5621,19 @@
 	}
 }
 
+void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
+				     u8 val)
+{
+	if (wpa_auth)
+		wpa_auth->conf.skip_send_eapol = val;
+}
+
+void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
+				     u8 val)
+{
+	if (wpa_auth)
+		wpa_auth->conf.enable_eapol_large_timeout = val;
+}
+
+
 #endif /* CONFIG_TESTING_OPTIONS */
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 5f9df9c..ff90464 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -240,6 +240,8 @@
 	unsigned int gtk_rsc_override_set:1;
 	unsigned int igtk_rsc_override_set:1;
 	int ft_rsnxe_used;
+	unsigned int skip_send_eapol:1;
+	unsigned int enable_eapol_large_timeout:1;
 #endif /* CONFIG_TESTING_OPTIONS */
 	unsigned int oci_freq_override_eapol_m3;
 	unsigned int oci_freq_override_eapol_g1;
@@ -542,5 +544,9 @@
 void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
 				    enum wpa_auth_ocv_override_frame frame,
 				    unsigned int freq);
+void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
+				     u8 val);
+void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
+				     u8 val);
 
 #endif /* WPA_AUTH_H */
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index c01654f..bb44c7a 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -180,6 +180,8 @@
 	wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc;
 	wconf->oci_freq_override_fils_assoc =
 		conf->oci_freq_override_fils_assoc;
+	wconf->skip_send_eapol = iconf->skip_send_eapol;
+	wconf->enable_eapol_large_timeout = iconf->enable_eapol_large_timeout;
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_P2P
 	os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index b11e371..3c0431b 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -533,8 +533,9 @@
 # Opportunistic Wireless Encryption (OWE)
 CONFIG_OWE=y
 
-# Easy Connect (Device Provisioning Protocol - DPP R1)
+# Easy Connect (Device Provisioning Protocol - DPP R1 & R2)
 CONFIG_DPP=y
+CONFIG_DPP2=y
 
 # WPA3-Personal (SAE)
 CONFIG_SAE=y
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index a4892e7..ac88a7d 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -44,6 +44,27 @@
 #endif /* CONFIG_WPS */
 
 
+static bool is_chanwidth160_supported(struct hostapd_hw_modes *mode,
+				      struct hostapd_config *conf)
+{
+#ifdef CONFIG_IEEE80211AX
+	if (conf->ieee80211ax) {
+		struct he_capabilities *he_cap;
+
+		he_cap = &mode->he_capab[IEEE80211_MODE_AP];
+		if (he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+		    (HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G |
+		     HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G))
+			return true;
+	}
+#endif /* CONFIG_IEEE80211AX */
+	if (mode->vht_capab & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+			       VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
+		return true;
+	return false;
+}
+
+
 static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
 			     struct wpa_ssid *ssid,
 			     struct hostapd_config *conf,
@@ -105,7 +126,7 @@
 		 */
 		hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ);
 		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
-		if (center_chan) {
+		if (center_chan && is_chanwidth160_supported(mode, conf)) {
 			wpa_printf(MSG_DEBUG,
 				   "VHT center channel %u for auto-selected 160 MHz bandwidth",
 				   center_chan);
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 7aa5ebf..731808d 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -40,6 +40,8 @@
 using android::hardware::wifi::supplicant::V1_4::ConnectionCapabilities;
 using android::hardware::wifi::supplicant::V1_4::LegacyMode;
 using android::hardware::wifi::supplicant::V1_4::implementation::HidlManager;
+using android::hardware::wifi::supplicant::V1_4::DppResponderBootstrapInfo;
+using android::hardware::wifi::supplicant::V1_4::DppCurve;
 
 constexpr uint32_t kMaxAnqpElems = 100;
 constexpr char kGetMacAddress[] = "MACADDR";
@@ -218,6 +220,65 @@
 	return mask;
 }
 
+const std::string getDppListenChannel(struct wpa_supplicant *wpa_s, int32_t *listen_channel)
+{
+	struct hostapd_hw_modes *mode;
+	int chan44 = 0, chan149 = 0;
+	*listen_channel = 0;
+
+	/* Check if device support 2.4GHz band*/
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+			HOSTAPD_MODE_IEEE80211G, 0);
+	if (mode) {
+		*listen_channel = 6;
+		return "81/6";
+	}
+	/* Check if device support 5GHz band */
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+			HOSTAPD_MODE_IEEE80211A, 0);
+	if (mode) {
+		for (int i = 0; i < mode->num_channels; i++) {
+			struct hostapd_channel_data *chan = &mode->channels[i];
+
+			if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+					  HOSTAPD_CHAN_RADAR))
+				continue;
+			if (chan->freq == 5220)
+				chan44 = 1;
+			if (chan->freq == 5745)
+				chan149 = 1;
+		}
+		if (chan149) {
+			*listen_channel = 149;
+			return "124/149";
+		} else if (chan44) {
+			*listen_channel = 44;
+			return "115/44";
+		}
+	}
+
+	return "";
+}
+
+const std::string convertCurveTypeToName(DppCurve curve)
+{
+	switch (curve) {
+	case DppCurve::PRIME256V1:
+		return "prime256v1";
+	case DppCurve::SECP384R1:
+		return "secp384r1";
+	case DppCurve::SECP521R1:
+		return "secp521r1";
+	case DppCurve::BRAINPOOLP256R1:
+		return "brainpoolP256r1";
+	case DppCurve::BRAINPOOLP384R1:
+		return "brainpoolP384r1";
+	case DppCurve::BRAINPOOLP512R1:
+		return "brainpoolP512r1";
+	}
+	WPA_ASSERT(false);
+}
+
 }  // namespace
 
 namespace android {
@@ -684,6 +745,31 @@
 	    &StaIface::stopDppInitiatorInternal, _hidl_cb);
 }
 
+Return<void> StaIface::generateDppBootstrapInfoForResponder(
+		const hidl_array<uint8_t, 6> &mac_address, const hidl_string& device_info,
+		DppCurve curve, generateDppBootstrapInfoForResponder_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::generateDppBootstrapInfoForResponderInternal, _hidl_cb, mac_address,
+	    device_info, curve);
+}
+
+Return<void> StaIface::startDppEnrolleeResponder(
+		uint32_t listen_channel, startDppEnrolleeResponder_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startDppEnrolleeResponderInternal, _hidl_cb, listen_channel);
+}
+
+Return<void> StaIface::stopDppResponder(uint32_t own_bootstrap_id, stopDppResponder_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::stopDppResponderInternal, _hidl_cb, own_bootstrap_id);
+}
+
 Return<void> StaIface::getWpaDriverCapabilities(
 		getWpaDriverCapabilities_cb _hidl_cb)
 {
@@ -1478,6 +1564,111 @@
 #endif
 }
 
+std::pair<V1_4::SupplicantStatus, DppResponderBootstrapInfo>
+StaIface::generateDppBootstrapInfoForResponderInternal(const std::array<uint8_t, 6> &mac_address,
+		const std::string& device_info, DppCurve curve)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string cmd = "type=qrcode";
+	int32_t id;
+	int32_t listen_channel = 0;
+	struct DppResponderBootstrapInfo bootstrap_info;
+	const char *uri;
+	std::string listen_channel_str;
+	std::string mac_addr_str;
+	char buf[3] = {0};
+
+	cmd += (device_info.empty()) ? "" : " info=" + device_info;
+
+	listen_channel_str = getDppListenChannel(wpa_s, &listen_channel);
+	if (listen_channel == 0) {
+		wpa_printf(MSG_ERROR, "StaIface: Failed to derive DPP listen channel");
+		return {{V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""}, bootstrap_info};
+	}
+	cmd += " chan=" + listen_channel_str;
+
+	cmd += " mac=";
+	for (int i = 0;i < 6;i++) {
+		snprintf(buf, sizeof(buf), "%02x", mac_address[i]);
+		mac_addr_str.append(buf);
+	}
+	cmd += mac_addr_str;
+
+	cmd += " curve=" + convertCurveTypeToName(curve);
+
+	id = dpp_bootstrap_gen(wpa_s->dpp, cmd.c_str());
+	wpa_printf(MSG_DEBUG,
+		   "DPP generate bootstrap QR code command: %s id: %d", cmd.c_str(), id);
+	if (id > 0) {
+		uri = dpp_bootstrap_get_uri(wpa_s->dpp, id);
+		if (uri) {
+			wpa_printf(MSG_DEBUG, "DPP Bootstrap info: id: %d "
+				   "listen_channel: %d uri: %s", id, listen_channel, uri);
+			bootstrap_info.bootstrapId = id;
+			bootstrap_info.listenChannel = listen_channel;
+			bootstrap_info.uri = uri;
+			return {{V1_4::SupplicantStatusCode::SUCCESS, ""}, bootstrap_info};
+		}
+	}
+	return {{V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""}, bootstrap_info};
+#else
+	return {{V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""}, bootstrap_info};
+#endif
+}
+
+V1_4::SupplicantStatus StaIface::startDppEnrolleeResponderInternal(uint32_t listen_channel)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string cmd = "";
+	uint32_t freq = (listen_channel <= 14 ? 2407 : 5000) + listen_channel * 5;
+
+	/* Report received configuration to HIDL and create an internal profile */
+	wpa_s->conf->dpp_config_processing = 1;
+
+	cmd += std::to_string(freq);
+	cmd += " role=enrollee netrole=sta";
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP Enrollee Responder command: %s", cmd.c_str());
+
+	if (wpas_dpp_listen(wpa_s, cmd.c_str()) == 0) {
+		return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+	}
+	return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+#else
+	return {V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""};
+#endif
+}
+
+V1_4::SupplicantStatus StaIface::stopDppResponderInternal(uint32_t own_bootstrap_id)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string bootstrap_id_str;
+
+	if (own_bootstrap_id == 0) {
+		bootstrap_id_str = "*";
+	}
+	else {
+		bootstrap_id_str = std::to_string(own_bootstrap_id);
+	}
+
+	wpa_printf(MSG_DEBUG, "DPP Stop DPP Responder id: %d ", own_bootstrap_id);
+	wpas_dpp_stop(wpa_s);
+	wpas_dpp_listen_stop(wpa_s);
+
+	if (dpp_bootstrap_remove(wpa_s->dpp, bootstrap_id_str.c_str()) < 0) {
+		wpa_printf(MSG_ERROR, "StaIface: dpp_bootstrap_remove failed");
+	}
+
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+#else
+	return {V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""};
+#endif
+}
+
 std::pair<SupplicantStatus, android::hardware::wifi::supplicant::V1_3::ConnectionCapabilities>
 StaIface::getConnectionCapabilitiesInternal()
 {
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
index bb5344b..d49e469 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ b/wpa_supplicant/hidl/1.4/sta_iface.h
@@ -205,6 +205,13 @@
 	    getKeyMgmtCapabilities_1_3_cb _hidl_cb) override;
 	Return<void> getWpaDriverCapabilities_1_4(
 	    getWpaDriverCapabilities_1_4_cb _hidl_cb) override;
+	Return<void> generateDppBootstrapInfoForResponder(const hidl_array<uint8_t, 6> &mac_address,
+			const hidl_string& device_info, DppCurve curve,
+			generateDppBootstrapInfoForResponder_cb _hidl_cb) override;
+	Return<void> startDppEnrolleeResponder(uint32_t listen_channel,
+			startDppEnrolleeResponder_cb _hidl_cb) override;
+	Return<void> stopDppResponder(uint32_t own_bootstrap_id,
+			stopDppResponder_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -303,6 +310,12 @@
 	SupplicantStatus setMboCellularDataStatusInternal(bool available);
 	std::pair<SupplicantStatus, uint32_t> getKeyMgmtCapabilitiesInternal_1_3();
 	std::pair<V1_4::SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal_1_4();
+	std::pair<V1_4::SupplicantStatus, V1_4::DppResponderBootstrapInfo>
+			generateDppBootstrapInfoForResponderInternal(
+			const std::array<uint8_t, 6>& mac_address, const std::string& device_info,
+			DppCurve curve);
+	V1_4::SupplicantStatus startDppEnrolleeResponderInternal(uint32_t listen_channel);
+	V1_4::SupplicantStatus stopDppResponderInternal(uint32_t own_bootstrap_id);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/hidl/1.4/sta_network.cpp b/wpa_supplicant/hidl/1.4/sta_network.cpp
index 6d53282..3e773de 100644
--- a/wpa_supplicant/hidl/1.4/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_network.cpp
@@ -2273,6 +2273,11 @@
 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
 	}
 	setFastTransitionKeyMgmt(key_mgmt_mask);
+
+	if (key_mgmt_mask & WPA_KEY_MGMT_OWE) {
+		// Do not allow to connect to Open network when OWE is selected
+		wpa_ssid->owe_only = 1;
+	}
 	wpa_ssid->key_mgmt = key_mgmt_mask;
 	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", wpa_ssid->key_mgmt);
 	resetInternalStateAfterParamsUpdate();