Merge "Enable scan mac randomization only if driver supports"
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index d269ac7..d4146db 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -551,4 +551,7 @@
 # WPA3-Personal (SAE)
 CONFIG_SAE=y
 
+# WPA3-Enterprise (SuiteB-192)
+CONFIG_SUITEB192=y
+
 include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index dd7f603..a8987a6 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2637,6 +2637,7 @@
 #ifdef CONFIG_MBO
 	os_free(config->non_pref_chan);
 #endif /* CONFIG_MBO */
+	os_free(config->p2p_device_persistent_mac_addr);
 
 	os_free(config);
 }
@@ -4753,6 +4754,9 @@
 	{ INT(gas_rand_addr_lifetime), 0 },
 	{ INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
 	{ INT_RANGE(dpp_config_processing, 0, 2), 0 },
+	{ INT(p2p_device_random_mac_addr), 0 },
+	{ STR(p2p_device_persistent_mac_addr), 0 },
+	{ INT(p2p_interface_random_mac_addr), 0 },
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index ad4dd88..ee20a93 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1469,6 +1469,36 @@
 	 *	profile automatically
 	 */
 	int dpp_config_processing;
+
+	/**
+	 * p2p_device_random_mac_addr - P2P Device MAC address policy default
+	 *
+	 * 0 = use permanent MAC address
+	 * 1 = use random MAC address on creating the interface if there is no persistent groups.
+	 *
+	 * By default, permanent MAC address is used.
+	 */
+	int p2p_device_random_mac_addr;
+
+	/**
+	 * p2p_device_persistent_mac_addr - Record last used MAC address
+	 *
+	 * If there are saved persistent groups, P2P cannot generate another random MAC address,
+	 * and need to restore to last used MAC address.
+	 * format: aa:bb:cc:dd:ee:ff
+	 */
+	char *p2p_device_persistent_mac_addr;
+
+	/**
+	 * p2p_interface_random_mac_addr - P2P Interface MAC address policy default
+	 *
+	 * 0 = use permanent MAC address
+	 * 1 = use random MAC address on creating the interface.
+	 *
+	 * By default, permanent MAC address is used.
+	 */
+	int p2p_interface_random_mac_addr;
+
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index aa73f9d..3a6dae5 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1511,6 +1511,15 @@
 	if (config->dpp_config_processing)
 		fprintf(f, "dpp_config_processing=%d\n",
 			config->dpp_config_processing);
+	if (config->p2p_device_random_mac_addr)
+		fprintf(f, "p2p_device_random_mac_addr=%d\n",
+			config->p2p_device_random_mac_addr);
+	if (config->p2p_device_persistent_mac_addr)
+		fprintf(f, "p2p_device_persistent_mac_addr=%s\n",
+			config->p2p_device_persistent_mac_addr);
+	if (config->p2p_interface_random_mac_addr)
+		fprintf(f, "p2p_interface_random_mac_addr=%d\n",
+			config->p2p_interface_random_mac_addr);
 
 }
 
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index e775422..152e257 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -469,7 +469,7 @@
 		wpa_printf(MSG_INFO,
 			   "DPP: No response received from responder - stopping initiation attempt");
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
-		wpas_notify_dpp_timeout(wpa_s->ifname);
+		wpas_notify_dpp_timeout(wpa_s);
 		offchannel_send_action_done(wpa_s);
 		wpas_dpp_listen_stop(wpa_s);
 		dpp_auth_deinit(auth);
@@ -731,6 +731,7 @@
 			wpa_printf(MSG_INFO,
 				   "DPP: No response received from responder - stopping initiation attempt");
 			wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
+			wpas_notify_dpp_timeout(wpa_s);
 			eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
 					     wpa_s, NULL);
 			offchannel_send_action_done(wpa_s);
@@ -1141,7 +1142,7 @@
 					  peer_bi, own_bi, freq, hdr, buf, len);
 	if (!wpa_s->dpp_auth) {
 		wpa_printf(MSG_DEBUG, "DPP: No response generated");
-		wpas_notify_dpp_auth_failure(wpa_s->ifname);
+		wpas_notify_dpp_auth_failure(wpa_s);
 		return;
 	}
 	wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
@@ -1264,7 +1265,7 @@
 
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
 
-	wpas_notify_dpp_config_received(wpa_s->ifname, ssid);
+	wpas_notify_dpp_config_received(wpa_s, ssid);
 
 	if (wpa_s->conf->dpp_config_processing < 2) {
 		return;
@@ -1389,7 +1390,7 @@
 
 fail:
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
-	wpas_notify_dpp_configuration_failure(wpa_s->ifname);
+	wpas_notify_dpp_configuration_failure(wpa_s);
 	dpp_auth_deinit(wpa_s->dpp_auth);
 	wpa_s->dpp_auth = NULL;
 }
@@ -1467,7 +1468,7 @@
 {
 	wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
-	wpas_notify_dpp_auth_success(wpa_s->ifname);
+	wpas_notify_dpp_auth_success(wpa_s);
 #ifdef CONFIG_TESTING_OPTIONS
 	if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
 		wpa_printf(MSG_INFO,
@@ -1524,13 +1525,13 @@
 		if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
 			wpa_printf(MSG_DEBUG,
 				   "DPP: Start wait for full response");
-			wpas_notify_dpp_resp_pending(wpa_s->ifname);
+			wpas_notify_dpp_resp_pending(wpa_s);
 			offchannel_send_action_done(wpa_s);
 			wpas_dpp_listen_start(wpa_s, auth->curr_freq);
 			return;
 		}
 		wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
-		wpas_notify_dpp_auth_failure(wpa_s->ifname);
+		wpas_notify_dpp_auth_failure(wpa_s);
 		return;
 	}
 	os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
@@ -1568,7 +1569,7 @@
 
 	if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
-		wpas_notify_dpp_auth_failure(wpa_s->ifname);
+		wpas_notify_dpp_auth_failure(wpa_s);
 		return;
 	}
 
@@ -2161,7 +2162,7 @@
 	resp = dpp_conf_req_rx(auth, query, query_len);
 	if (!resp) {
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
-		wpas_notify_dpp_configuration_failure(wpa_s->ifname);
+		wpas_notify_dpp_configuration_failure(wpa_s);
 	}
 	auth->conf_resp = resp;
 	return resp;
@@ -2194,11 +2195,11 @@
 	wpas_dpp_listen_stop(wpa_s);
 	if (ok) {
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
-		wpas_notify_dpp_config_sent(wpa_s->ifname);
+		wpas_notify_dpp_config_sent(wpa_s);
 	}
 	else {
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
-		wpas_notify_dpp_configuration_failure(wpa_s->ifname);
+		wpas_notify_dpp_configuration_failure(wpa_s);
 	}
 	dpp_auth_deinit(wpa_s->dpp_auth);
 	wpa_s->dpp_auth = NULL;
diff --git a/wpa_supplicant/hidl/1.2/hidl.cpp b/wpa_supplicant/hidl/1.2/hidl.cpp
index 60ee85f..d8fa82f 100644
--- a/wpa_supplicant/hidl/1.2/hidl.cpp
+++ b/wpa_supplicant/hidl/1.2/hidl.cpp
@@ -27,9 +27,9 @@
 using android::hardware::wifi::supplicant::V1_2::implementation::HidlManager;
 using namespace android::hardware::wifi::supplicant::V1_2;
 
-static void wpas_hidl_notify_dpp_success(const char *ifname, DppSuccessCode code);
-static void wpas_hidl_notify_dpp_failure(const char *ifname, DppFailureCode code);
-static void wpas_hidl_notify_dpp_progress(const char *ifname, DppProgressCode code);
+static void wpas_hidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppSuccessCode code);
+static void wpas_hidl_notify_dpp_failure(struct wpa_supplicant *wpa_s, DppFailureCode code);
+static void wpas_hidl_notify_dpp_progress(struct wpa_supplicant *wpa_s, DppProgressCode code);
 
 void wpas_hidl_sock_handler(
     int sock, void * /* eloop_ctx */, void * /* sock_ctx */)
@@ -648,10 +648,10 @@
 	hidl_manager->notifyEapError(wpa_s, error_code);
 }
 
-void wpas_hidl_notify_dpp_config_received(const char *ifname,
+void wpas_hidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
 	    struct wpa_ssid *ssid)
 {
-	if (!ifname || !ssid)
+	if (!wpa_s || !ssid)
 		return;
 
 	wpa_printf(
@@ -662,85 +662,85 @@
 	if (!hidl_manager)
 		return;
 
-	hidl_manager->notifyDppConfigReceived(ifname, ssid);
+	hidl_manager->notifyDppConfigReceived(wpa_s, ssid);
 }
 
-void wpas_hidl_notify_dpp_config_sent(const char *ifname)
+void wpas_hidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_success(ifname, DppSuccessCode::CONFIGURATION_SENT);
+	wpas_hidl_notify_dpp_success(wpa_s, DppSuccessCode::CONFIGURATION_SENT);
 }
 
 /* DPP Progress notifications */
-void wpas_hidl_notify_dpp_auth_success(const char *ifname)
+void wpas_hidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_progress(ifname, DppProgressCode::AUTHENTICATION_SUCCESS);
+	wpas_hidl_notify_dpp_progress(wpa_s, DppProgressCode::AUTHENTICATION_SUCCESS);
 }
 
-void wpas_hidl_notify_dpp_resp_pending(const char *ifname)
+void wpas_hidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_progress(ifname, DppProgressCode::RESPONSE_PENDING);
+	wpas_hidl_notify_dpp_progress(wpa_s, DppProgressCode::RESPONSE_PENDING);
 }
 
 /* DPP Failure notifications */
-void wpas_hidl_notify_dpp_not_compatible(const char *ifname)
+void wpas_hidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::NOT_COMPATIBLE);
+	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::NOT_COMPATIBLE);
 }
 
-void wpas_hidl_notify_dpp_missing_auth(const char *ifname)
+void wpas_hidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 }
 
-void wpas_hidl_notify_dpp_configuration_failure(const char *ifname)
+void wpas_hidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::CONFIGURATION);
+	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::CONFIGURATION);
 }
 
-void wpas_hidl_notify_dpp_timeout(const char *ifname)
+void wpas_hidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::TIMEOUT);
+	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::TIMEOUT);
 }
 
-void wpas_hidl_notify_dpp_auth_failure(const char *ifname)
+void wpas_hidl_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::AUTHENTICATION);
+	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::AUTHENTICATION);
 }
 
-void wpas_hidl_notify_dpp_fail(const char *ifname)
+void wpas_hidl_notify_dpp_fail(struct wpa_supplicant *wpa_s)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::FAILURE);
+	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::FAILURE);
 }
 
 /* DPP notification helper functions */
-static void wpas_hidl_notify_dpp_success(const char *ifname, DppSuccessCode code)
+static void wpas_hidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppSuccessCode code)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
 	wpa_printf(
@@ -751,12 +751,12 @@
 	if (!hidl_manager)
 		return;
 
-	hidl_manager->notifyDppSuccess(ifname, code);
+	hidl_manager->notifyDppSuccess(wpa_s, code);
 }
 
-static void wpas_hidl_notify_dpp_failure(const char *ifname, DppFailureCode code)
+static void wpas_hidl_notify_dpp_failure(struct wpa_supplicant *wpa_s, DppFailureCode code)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
 	wpa_printf(
@@ -767,12 +767,12 @@
 	if (!hidl_manager)
 		return;
 
-	hidl_manager->notifyDppFailure(ifname, code);
+	hidl_manager->notifyDppFailure(wpa_s, code);
 }
 
-static void wpas_hidl_notify_dpp_progress(const char *ifname, DppProgressCode code)
+static void wpas_hidl_notify_dpp_progress(struct wpa_supplicant *wpa_s, DppProgressCode code)
 {
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
 	wpa_printf(
@@ -783,5 +783,5 @@
 	if (!hidl_manager)
 		return;
 
-	hidl_manager->notifyDppProgress(ifname, code);
+	hidl_manager->notifyDppProgress(wpa_s, code);
 }
diff --git a/wpa_supplicant/hidl/1.2/hidl.h b/wpa_supplicant/hidl/1.2/hidl.h
index 914bc7b..a177f6e 100644
--- a/wpa_supplicant/hidl/1.2/hidl.h
+++ b/wpa_supplicant/hidl/1.2/hidl.h
@@ -99,18 +99,18 @@
 	    const u8 *p2p_dev_addr);
 	void wpas_hidl_notify_eap_error(
 	    struct wpa_supplicant *wpa_s, int error_code);
-	void wpas_hidl_notify_dpp_config_received(const char *ifname,
+	void wpas_hidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
 		    struct wpa_ssid *ssid);
-	void wpas_hidl_notify_dpp_config_sent(const char *ifname);
-	void wpas_hidl_notify_dpp_auth_success(const char *ifname);
-	void wpas_hidl_notify_dpp_resp_pending(const char *ifname);
-	void wpas_hidl_notify_dpp_not_compatible(const char *ifname);
-	void wpas_hidl_notify_dpp_missing_auth(const char *ifname);
-	void wpas_hidl_notify_dpp_configuration_failure(const char *ifname);
-	void wpas_hidl_notify_dpp_invalid_uri(const char *ifname);
-	void wpas_hidl_notify_dpp_timeout(const char *ifname);
-	void wpas_hidl_notify_dpp_auth_failure(const char *ifname);
-	void wpas_hidl_notify_dpp_fail(const char *ifname);
+	void wpas_hidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_invalid_uri(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s);
+	void wpas_hidl_notify_dpp_fail(struct wpa_supplicant *wpa_s);
 #else   // CONFIG_CTRL_IFACE_HIDL
 static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
 {
diff --git a/wpa_supplicant/hidl/1.2/hidl_manager.cpp b/wpa_supplicant/hidl/1.2/hidl_manager.cpp
index 1392159..c6fe92f 100644
--- a/wpa_supplicant/hidl/1.2/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.2/hidl_manager.cpp
@@ -1491,20 +1491,23 @@
  * @param ifname Interface name
  * @param config Configuration object
  */
-void HidlManager::notifyDppConfigReceived(const char *ifname,
+void HidlManager::notifyDppConfigReceived(struct wpa_supplicant *wpa_s,
 		struct wpa_ssid *config)
 {
 	DppAkm securityAkm;
 	char *password;
-	std::string hidl_ifname = ifname;
+	std::string hidl_ifname = wpa_s->ifname;
 
-	if (config->key_mgmt & WPA_KEY_MGMT_SAE) {
+	if ((config->key_mgmt & WPA_KEY_MGMT_SAE) &&
+			(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
 		securityAkm = DppAkm::SAE;
 	} else if (config->key_mgmt & WPA_KEY_MGMT_PSK) {
 			securityAkm = DppAkm::PSK;
 	} else {
 		/* Unsupported AKM */
-		notifyDppFailure(ifname, DppFailureCode::CONFIGURATION);
+		wpa_printf(MSG_ERROR, "DPP: Error: Unsupported AKM 0x%X",
+				config->key_mgmt);
+		notifyDppFailure(wpa_s, DppFailureCode::CONFIGURATION);
 		return;
 	}
 
@@ -1528,9 +1531,9 @@
  * @param ifname Interface name
  * @param code Status code
  */
-void HidlManager::notifyDppSuccess(const char *ifname, DppSuccessCode code)
+void HidlManager::notifyDppSuccess(struct wpa_supplicant *wpa_s, DppSuccessCode code)
 {
-	std::string hidl_ifname = ifname;
+	std::string hidl_ifname = wpa_s->ifname;
 
 	callWithEachStaIfaceCallback_1_2(hidl_ifname,
 			std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppSuccess,
@@ -1543,9 +1546,9 @@
  * @param ifname Interface name
  * @param code Status code
  */
-void HidlManager::notifyDppFailure(const char *ifname, DppFailureCode code)
+void HidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s, DppFailureCode code)
 {
-	std::string hidl_ifname = ifname;
+	std::string hidl_ifname = wpa_s->ifname;
 
 	callWithEachStaIfaceCallback_1_2(hidl_ifname,
 			std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppFailure,
@@ -1558,9 +1561,9 @@
  * @param ifname Interface name
  * @param code Status code
  */
-void HidlManager::notifyDppProgress(const char *ifname, DppProgressCode code)
+void HidlManager::notifyDppProgress(struct wpa_supplicant *wpa_s, DppProgressCode code)
 {
-	std::string hidl_ifname = ifname;
+	std::string hidl_ifname = wpa_s->ifname;
 
 	callWithEachStaIfaceCallback_1_2(hidl_ifname,
 			std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppProgress,
diff --git a/wpa_supplicant/hidl/1.2/hidl_manager.h b/wpa_supplicant/hidl/1.2/hidl_manager.h
index a7e2c86..7291347 100644
--- a/wpa_supplicant/hidl/1.2/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.2/hidl_manager.h
@@ -128,11 +128,11 @@
 	    struct wpa_supplicant *wpa_s, const u8 *sta,
 	    const u8 *p2p_dev_addr);
 	void notifyEapError(struct wpa_supplicant *wpa_s, int error_code);
-	void notifyDppConfigReceived(const char *ifname,
+	void notifyDppConfigReceived(struct wpa_supplicant *wpa_s,
 			struct wpa_ssid *config);
-	void notifyDppSuccess(const char *ifname, DppSuccessCode code);
-	void notifyDppFailure(const char *ifname, DppFailureCode code);
-	void notifyDppProgress(const char *ifname, DppProgressCode code);
+	void notifyDppSuccess(struct wpa_supplicant *wpa_s, DppSuccessCode code);
+	void notifyDppFailure(struct wpa_supplicant *wpa_s, DppFailureCode code);
+	void notifyDppProgress(struct wpa_supplicant *wpa_s, DppProgressCode code);
 
 	// Methods called from hidl objects.
 	void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
@@ -357,6 +357,14 @@
 	WPA_KEY_MGMT_OWE,
     "KeyMgmt value mismatch");
 static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK_SHA256) ==
+	WPA_KEY_MGMT_PSK_SHA256,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP_SHA256) ==
+	WPA_KEY_MGMT_IEEE8021X_SHA256,
+    "KeyMgmt value mismatch");
+static_assert(
     static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::WPA) ==
 	WPA_PROTO_WPA,
     "Proto value mismatch");
diff --git a/wpa_supplicant/hidl/1.2/p2p_iface.cpp b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
index 80c0205..e528cb0 100644
--- a/wpa_supplicant/hidl/1.2/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
@@ -20,8 +20,13 @@
 #include "ap.h"
 #include "wps_supplicant.h"
 #include "wifi_display.h"
+#include "utils/eloop.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
 }
 
+#define P2P_MAX_JOIN_SCAN_ATTEMPTS 10
+
 namespace {
 const char kConfigMethodStrPbc[] = "pbc";
 const char kConfigMethodStrDisplay[] = "display";
@@ -30,6 +35,9 @@
 constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
 constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
 
+std::function<void()> pending_join_scan_callback = NULL;
+std::function<void()> pending_scan_res_join_callback = NULL;
+
 using android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
 using android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
 uint8_t convertHidlMiracastModeToInternal(
@@ -82,6 +90,280 @@
 	}
 	return 1;
 }
+
+void setBandScanFreqsList(
+    struct wpa_supplicant *wpa_s,
+    enum hostapd_hw_mode band,
+    struct wpa_driver_scan_params *params)
+{
+	/* Include only supported channels for the specified band */
+	struct hostapd_hw_modes *mode;
+	int count, i;
+
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band);
+	if (mode == NULL) {
+		/* No channels supported in this band. */
+		return;
+	}
+
+	params->freqs = (int *) os_calloc(mode->num_channels + 1, sizeof(int));
+	if (params->freqs == NULL)
+		return;
+	for (count = 0, i = 0; i < mode->num_channels; i++) {
+		if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+		params->freqs[count++] = mode->channels[i].freq;
+	}
+}
+
+/**
+ * findBssBySsid - Fetch a BSS table entry based on SSID and optional BSSID.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID, zero addr matches any bssid
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss* findBssBySsid(
+    struct wpa_supplicant *wpa_s, const u8 *bssid,
+    const u8 *ssid, size_t ssid_len)
+{
+	struct wpa_bss *bss;
+	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+		if ((is_zero_ether_addr(bssid) ||
+		    os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
+		    bss->ssid_len == ssid_len &&
+		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
+			return bss;
+	}
+	return NULL;
+}
+
+struct wpa_ssid* addGroupClientNetwork(
+    struct wpa_supplicant* wpa_s,
+    uint8_t *group_owner_bssid,
+    const std::vector<uint8_t>& ssid,
+    const std::string& passphrase)
+{
+	struct wpa_ssid* wpa_network = wpa_config_add_network(wpa_s->conf);
+	if (!wpa_network) {
+		return NULL;
+	}
+	// set general network defaults
+	wpa_config_set_network_defaults(wpa_network);
+
+	// set P2p network defaults
+	wpa_network->p2p_group = 1;
+	wpa_network->mode = wpa_ssid::wpas_mode::WPAS_MODE_INFRA;
+
+	wpa_network->auth_alg = WPA_AUTH_ALG_OPEN;
+	wpa_network->key_mgmt = WPA_KEY_MGMT_PSK;
+	wpa_network->proto = WPA_PROTO_RSN;
+	wpa_network->pairwise_cipher = WPA_CIPHER_CCMP;
+	wpa_network->group_cipher = WPA_CIPHER_CCMP;
+	wpa_network->disabled = 2;
+
+	// set necessary fields
+	os_memcpy(wpa_network->bssid, group_owner_bssid, ETH_ALEN);
+	wpa_network->bssid_set = 1;
+
+	wpa_network->ssid = (uint8_t *)os_malloc(ssid.size());
+	if (wpa_network->ssid == NULL) {
+		wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+		return  NULL;
+	}
+	memcpy(wpa_network->ssid, ssid.data(), ssid.size());
+	wpa_network->ssid_len = ssid.size();
+
+	wpa_network->psk_set = 0;
+	wpa_network->passphrase = dup_binstr(passphrase.c_str(), passphrase.length());
+	if (wpa_network->passphrase == NULL) {
+		wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+		return  NULL;
+	}
+	wpa_config_update_psk(wpa_network);
+
+	return wpa_network;
+
+}
+
+void joinScanWrapper(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = (struct wpa_supplicant *) eloop_ctx;
+
+	if (pending_join_scan_callback != NULL) {
+		pending_join_scan_callback();
+	}
+}
+
+void scanResJoinWrapper(
+    struct wpa_supplicant *wpa_s,
+    struct wpa_scan_results *scan_res)
+{
+	if (pending_scan_res_join_callback) {
+		pending_scan_res_join_callback();
+	}
+}
+
+int joinScanReq(
+    struct wpa_supplicant* wpa_s,
+    const std::vector<uint8_t>& ssid,
+    int freq)
+{
+	int ret;
+	struct wpa_driver_scan_params params;
+	struct wpabuf *ies;
+	size_t ielen;
+	unsigned int bands;
+
+	os_memset(&params, 0, sizeof(params));
+	if (ssid.size() > 0) {
+		params.ssids[0].ssid = ssid.data();
+		params.ssids[0].ssid_len = ssid.size();
+	} else {
+		params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
+		params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+	}
+	wpa_printf(MSG_DEBUG, "Scan SSID %s for join with frequency %d (reinvoke)",
+	    wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq);
+
+	if (freq > 0) {
+		if (freq == 2 || freq == 5) {
+			if (wpa_s->hw.modes != NULL) {
+				switch (freq) {
+				case 2:
+					setBandScanFreqsList(wpa_s,
+					    HOSTAPD_MODE_IEEE80211G, &params);
+				break;
+				case 5:
+					setBandScanFreqsList(wpa_s,
+					    HOSTAPD_MODE_IEEE80211A, &params);
+				break;
+				}
+				if (!params.freqs) {
+					wpa_printf(MSG_ERROR,
+					    "P2P: No supported channels in %dG band.", freq);
+					return -1;
+				}
+			} else {
+				wpa_printf(MSG_DEBUG,
+				    "P2P: Unknown what %dG channels the driver supports.", freq);
+			}
+		} else {
+			if (0 == p2p_supported_freq_cli(wpa_s->global->p2p, freq)) {
+				wpa_printf(MSG_ERROR,
+				    "P2P: freq %d is not supported for a client.", freq);
+				return -1;
+			}
+
+			params.freqs = (int *) os_malloc(sizeof(int) * 2);
+			if (params.freqs) {
+				params.freqs[0] = freq;
+			} else {
+				wpa_printf(MSG_ERROR,
+				    "P2P: Cannot allocate memory for scan params.");
+				return -1;
+			}
+		}
+	}
+
+	ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
+	ies = wpabuf_alloc(ielen);
+	if (ies == NULL) {
+		if (params.freqs) {
+			os_free(params.freqs);
+		}
+		return -1;
+	}
+
+	bands = wpas_get_bands(wpa_s, params.freqs);
+	p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
+
+	params.p2p_probe = 1;
+	params.extra_ies = (u8 *) wpabuf_head(ies);
+	params.extra_ies_len = wpabuf_len(ies);
+	if (wpa_s->clear_driver_scan_cache) {
+		wpa_printf(MSG_DEBUG,
+		    "Request driver to clear scan cache due to local BSS flush");
+		params.only_new_results = 1;
+	}
+
+	ret = wpa_drv_scan(wpa_s, &params);
+	if (!ret) {
+		os_get_reltime(&wpa_s->scan_trigger_time);
+		wpa_s->scan_res_handler = scanResJoinWrapper;
+		wpa_s->own_scan_requested = 1;
+		wpa_s->clear_driver_scan_cache = 0;
+	}
+
+	if (params.freqs) {
+		os_free(params.freqs);
+	}
+
+	wpabuf_free(ies);
+
+	return ret;
+}
+
+int joinGroup(
+    struct wpa_supplicant* wpa_s,
+    uint8_t *group_owner_bssid,
+    const std::vector<uint8_t>& ssid,
+    const std::string& passphrase)
+{
+	int ret = 0;
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+
+	// Construct a network for adding group.
+	// Group client follows the persistent attribute of Group Owner.
+	// If joined group is persistent, it adds a persistent network on GroupStarted.
+	struct wpa_ssid *wpa_network = addGroupClientNetwork(
+	    wpa_s, group_owner_bssid, ssid, passphrase);
+	if (wpa_network == NULL) {
+		wpa_printf(MSG_ERROR, "P2P: Cannot construct a network for group join.");
+		return -1;
+	}
+
+	// this is temporary network only for establishing the connection.
+	wpa_network->temporary = 1;
+
+	if (wpas_p2p_group_add_persistent(
+		wpa_s, wpa_network, 0, 0, 0, 0, ht40, vht,
+		VHT_CHANWIDTH_USE_HT, NULL, 0, 1)) {
+		ret = -1;
+	}
+
+	// Always remove this temporary network at the end.
+	wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+	return ret;
+}
+
+void notifyGroupJoinFailure(
+    struct wpa_supplicant* wpa_s)
+{
+	u8 zero_addr[ETH_ALEN] = {0};
+	std::vector<uint8_t> ssid = {'D', 'I', 'R', 'E','C', 'T', '-'};
+	std::string passphrase = "";
+	struct wpa_ssid *wpa_network = addGroupClientNetwork(
+	    wpa_s, zero_addr, ssid, passphrase);
+	if (wpa_network) {
+		wpa_network->temporary = 1;
+		wpas_notify_p2p_group_formation_failure(wpa_s, "Failed to find the group.");
+		wpas_notify_p2p_group_removed(
+		    wpa_s, wpa_network, "client");
+		wpa_config_remove_network(
+		    wpa_s->conf, wpa_network->id);
+	} else {
+		wpa_printf(MSG_ERROR,
+		    "P2P: Cannot construct a network.");
+	}
+}
+
+void scanResJoinIgnore(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res) {
+	wpa_printf(MSG_DEBUG, "P2P: Ignore group join scan results.");
+}
+
 }  // namespace
 
 namespace android {
@@ -706,6 +988,11 @@
 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
 		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
 	}
+	if (wpa_s->scan_res_handler == scanResJoinWrapper) {
+		wpa_printf(MSG_DEBUG, "P2P: Stop pending group scan for stopping find).");
+		pending_scan_res_join_callback = NULL;
+		wpa_s->scan_res_handler = scanResJoinIgnore;
+	}
 	wpas_p2p_stop_find(wpa_s);
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
@@ -769,6 +1056,11 @@
 SupplicantStatus P2pIface::cancelConnectInternal()
 {
 	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->scan_res_handler == scanResJoinWrapper) {
+		wpa_printf(MSG_DEBUG, "P2P: Stop pending group scan for canceling connect");
+		pending_scan_res_join_callback = NULL;
+		wpa_s->scan_res_handler = scanResJoinIgnore;
+	}
 	if (wpas_p2p_cancel(wpa_s)) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
@@ -1324,38 +1616,7 @@
 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, "passphrase is invalid."};
 	}
 
-	if (joinExistingGroup) {
-		struct wpa_bss *bss = findBssBySsid(
-		    wpa_s, peer_address.data(),
-		    ssid.data(), ssid.size());
-		if (bss == NULL) {
-			return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
-			    "No matched BSS found."};
-		}
-
-		// Construct a network for adding group.
-		// Group client follows the persistent attribute of Group Owner.
-		// If joined group is persistent, it adds a persistent network on GroupStarted.
-		struct wpa_ssid *wpa_network = addGroupClientNetwork(
-		    wpa_s, bss->bssid, ssid, passphrase);
-		if (wpa_network == NULL) {
-			return {SupplicantStatusCode::FAILURE_UNKNOWN,
-			    "Cannot construct P2P network."};
-		}
-
-		// this is temporary network only for establishing the connection.
-		wpa_network->temporary = 1;
-
-		if (wpas_p2p_group_add_persistent(
-			wpa_s, wpa_network, 0, 0, 0, 0, ht40, vht,
-			VHT_CHANWIDTH_USE_HT, NULL, 0, 1)) {
-			wpa_config_remove_network(wpa_s->conf, wpa_network->id);
-			return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
-		}
-
-		// Always remove this temporary network at the end.
-		wpa_config_remove_network(wpa_s->conf, wpa_network->id);
-	} else {
+	if (!joinExistingGroup) {
 		if (wpa_s->global->p2p == NULL) {
 			return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
 		}
@@ -1370,10 +1631,94 @@
 		p2p->passphrase_set = 1;
 
 		if (wpas_p2p_group_add(
-			wpa_s, persistent, freq, 0, ht40, vht,
-			VHT_CHANWIDTH_USE_HT)) {
+		    wpa_s, persistent, freq, 0, ht40, vht,
+		    VHT_CHANWIDTH_USE_HT)) {
 			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 		}
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+
+	// The rest is for group join.
+	wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND before group join.");
+	wpas_p2p_stop_find(wpa_s);
+
+	struct wpa_bss *bss = findBssBySsid(
+	    wpa_s, peer_address.data(),
+	    ssid.data(), ssid.size());
+	if (bss != NULL) {
+		wpa_printf(MSG_DEBUG, "P2P: Join group with Group Owner " MACSTR,
+		    MAC2STR(bss->bssid));
+		if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
+			// no need to notify group join failure here,
+			// it will be handled by wpas_p2p_group_add_persistent
+			// called in joinGroup.
+			return {SupplicantStatusCode::FAILURE_UNKNOWN, "Failed to join a group."};
+		}
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+
+	wpa_printf(MSG_INFO, "No matched BSS exists, try to find it by scan");
+
+	if (wpa_s->scan_res_handler) {
+		wpa_printf(MSG_WARNING, "There is on-going scanning, cannot start another scan.");
+		return {SupplicantStatusCode::FAILURE_UNKNOWN,
+		    "Failed to start scan due to device busy."};
+	}
+
+	if (pending_scan_res_join_callback != NULL) {
+		wpa_printf(MSG_WARNING, "There is running group join scan.");
+		return {SupplicantStatusCode::FAILURE_UNKNOWN,
+		    "Failed to start scan due to device busy."};
+	}
+
+	pending_join_scan_callback =
+	    [wpa_s, ssid, freq]() {
+		if (0 != joinScanReq(wpa_s, ssid, freq)) {
+			notifyGroupJoinFailure(wpa_s);
+			pending_scan_res_join_callback = NULL;
+		}
+	};
+
+	pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, this]() {
+		if (wpa_s->global->p2p_disabled) {
+			return;
+		}
+
+		wpa_printf(MSG_DEBUG, "P2P: Scan results received for join (reinvoke).");
+
+		struct wpa_bss *bss = findBssBySsid(
+		    wpa_s, peer_address.data(), ssid.data(), ssid.size());
+		if (bss) {
+			if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
+				wpa_printf(MSG_ERROR, "P2P: Failed to join a group.");
+			}
+			// no need to notify group join failure here,
+			// it will be handled by wpas_p2p_group_add_persistent
+			// called in joinGroup.
+			pending_scan_res_join_callback = NULL;
+			return;
+		}
+
+		wpa_s->p2p_join_scan_count++;
+		wpa_printf(MSG_DEBUG, "P2P: Join scan attempt %d.", wpa_s->p2p_join_scan_count);
+		eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
+		if (wpa_s->p2p_join_scan_count <= P2P_MAX_JOIN_SCAN_ATTEMPTS) {
+			wpa_printf(MSG_DEBUG, "P2P: Try join again later.");
+			eloop_register_timeout(1, 0, joinScanWrapper, wpa_s, this);
+			return;
+		}
+
+		wpa_printf(MSG_ERROR, "P2P: Failed to find the group with "
+		    "network name %s - stop join attempt",
+		    ssid.data());
+		notifyGroupJoinFailure(wpa_s);
+		pending_scan_res_join_callback = NULL;
+	};
+
+	wpa_s->p2p_join_scan_count = 0;
+	if (0 != joinScanReq(wpa_s, ssid, freq)) {
+		pending_scan_res_join_callback = NULL;
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, "Failed to start scan."};
 	}
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
@@ -1398,77 +1743,6 @@
 	return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
 }
 
-struct wpa_ssid* P2pIface::addGroupClientNetwork(
-    struct wpa_supplicant* wpa_s,
-    uint8_t *group_owner_bssid,
-    const std::vector<uint8_t>& ssid,
-    const std::string& passphrase)
-{
-	struct wpa_ssid* wpa_network = wpa_config_add_network(wpa_s->conf);
-	if (!wpa_network) {
-		return NULL;
-	}
-	// set general network defaults
-	wpa_config_set_network_defaults(wpa_network);
-
-	// set P2p network defaults
-	wpa_network->p2p_group = 1;
-	wpa_network->mode = wpa_ssid::wpas_mode::WPAS_MODE_INFRA;
-
-	wpa_network->auth_alg = WPA_AUTH_ALG_OPEN;
-	wpa_network->key_mgmt = WPA_KEY_MGMT_PSK;
-	wpa_network->proto = WPA_PROTO_RSN;
-	wpa_network->pairwise_cipher = WPA_CIPHER_CCMP;
-	wpa_network->group_cipher = WPA_CIPHER_CCMP;
-	wpa_network->disabled = 2;
-
-	// set necessary fields
-	os_memcpy(wpa_network->bssid, group_owner_bssid, ETH_ALEN);
-	wpa_network->bssid_set = 1;
-
-	wpa_network->ssid = (uint8_t *)os_malloc(ssid.size());
-	if (wpa_network->ssid == NULL) {
-		wpa_config_remove_network(wpa_s->conf, wpa_network->id);
-		return  NULL;
-	}
-	memcpy(wpa_network->ssid, ssid.data(), ssid.size());
-	wpa_network->ssid_len = ssid.size();
-
-	wpa_network->psk_set = 0;
-	wpa_network->passphrase = dup_binstr(passphrase.c_str(), passphrase.length());
-	if (wpa_network->passphrase == NULL) {
-		wpa_config_remove_network(wpa_s->conf, wpa_network->id);
-		return  NULL;
-	}
-	wpa_config_update_psk(wpa_network);
-
-	return wpa_network;
-
-}
-
-/**
- * findBssBySsid - Fetch a BSS table entry based on SSID and optional BSSID.
- * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID, zero addr matches any bssid
- * @ssid: SSID
- * @ssid_len: Length of @ssid
- * Returns: Pointer to the BSS entry or %NULL if not found
- */
-struct wpa_bss* P2pIface::findBssBySsid(
-    struct wpa_supplicant *wpa_s, const u8 *bssid,
-    const u8 *ssid, size_t ssid_len)
-{
-	struct wpa_bss *bss;
-	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
-		if ((is_zero_ether_addr(bssid) ||
-		    os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
-		    bss->ssid_len == ssid_len &&
-		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
-			return bss;
-	}
-	return NULL;
-}
-
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace supplicant
diff --git a/wpa_supplicant/hidl/1.2/p2p_iface.h b/wpa_supplicant/hidl/1.2/p2p_iface.h
index a3ccdde..9b9da03 100644
--- a/wpa_supplicant/hidl/1.2/p2p_iface.h
+++ b/wpa_supplicant/hidl/1.2/p2p_iface.h
@@ -303,14 +303,6 @@
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
 	    const std::string& group_ifname);
-	struct wpa_ssid* addGroupClientNetwork(
-	    struct wpa_supplicant* wpa_s,
-	    uint8_t *group_owner_bssid,
-	    const std::vector<uint8_t>& ssid,
-	    const std::string& passphrase);
-	struct wpa_bss* findBssBySsid(
-	    struct wpa_supplicant *wpa_s, const u8 *bssid,
-	    const u8 *ssid, size_t ssid_len);
 
 	// Reference to the global wpa_struct. This is assumed to be valid for
 	// the lifetime of the process.
diff --git a/wpa_supplicant/hidl/1.2/sta_iface.cpp b/wpa_supplicant/hidl/1.2/sta_iface.cpp
index ae5fcbe..8c5178e 100644
--- a/wpa_supplicant/hidl/1.2/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.2/sta_iface.cpp
@@ -1187,6 +1187,14 @@
 	cmd += (own_bootstrap_id > 0) ?
 			" own=" + std::to_string(own_bootstrap_id) : "";
 
+	/* Check for supported AKMs */
+	if (security_akm != DppAkm::PSK && security_akm != DppAkm::SAE &&
+			security_akm != DppAkm::PSK_SAE) {
+		wpa_printf(MSG_ERROR, "DPP: Error: invalid AKM specified: %d",
+				security_akm);
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+
 	/* SAE AKM requires SSID and password to be initialized */
 	if ((security_akm == DppAkm::SAE ||
 			security_akm == DppAkm::PSK_SAE) &&
@@ -1204,9 +1212,6 @@
 			wpa_printf(MSG_ERROR, "DPP: Error: Password or PSK not specified");
 			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 		}
-	} else {
-		wpa_printf(MSG_ERROR, "DPP: Error: invalid AKM specified");
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 
 	cmd += " role=configurator";
diff --git a/wpa_supplicant/hidl/1.2/sta_network.cpp b/wpa_supplicant/hidl/1.2/sta_network.cpp
index 944c4a9..cf15909 100644
--- a/wpa_supplicant/hidl/1.2/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.2/sta_network.cpp
@@ -34,7 +34,9 @@
      static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::OSEN) |
      static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::SAE) |
      static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::SUITE_B_192) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::OWE));
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::OWE) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK_SHA256) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP_SHA256));
 constexpr uint32_t kAllowedProtoMask =
     (static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::WPA) |
      static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::RSN) |
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 37a4595..30bdb6d 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -1033,105 +1033,105 @@
 
 /* DPP Success notifications */
 
-void wpas_notify_dpp_config_received(const char *ifname,
+void wpas_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
 	    struct wpa_ssid *ssid)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_config_received(ifname, ssid);
+	wpas_hidl_notify_dpp_config_received(wpa_s, ssid);
 #endif /* CONFIG_DPP */
 }
 
-void wpas_notify_dpp_config_sent(const char *ifname)
+void wpas_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_config_sent(ifname);
+	wpas_hidl_notify_dpp_config_sent(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
 /* DPP Progress notifications */
-void wpas_notify_dpp_auth_success(const char *ifname)
+void wpas_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_auth_success(ifname);
+	wpas_hidl_notify_dpp_auth_success(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
-void wpas_notify_dpp_resp_pending(const char *ifname)
+void wpas_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_resp_pending(ifname);
+	wpas_hidl_notify_dpp_resp_pending(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
 /* DPP Failure notifications */
-void wpas_notify_dpp_not_compatible(const char *ifname)
+void wpas_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_not_compatible(ifname);
+	wpas_hidl_notify_dpp_not_compatible(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
-void wpas_notify_dpp_missing_auth(const char *ifname)
+void wpas_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_missing_auth(ifname);
+	wpas_hidl_notify_dpp_missing_auth(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
-void wpas_notify_dpp_configuration_failure(const char *ifname)
+void wpas_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_configuration_failure(ifname);
+	wpas_hidl_notify_dpp_configuration_failure(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
-void wpas_notify_dpp_timeout(const char *ifname)
+void wpas_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_timeout(ifname);
+	wpas_hidl_notify_dpp_timeout(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
-void wpas_notify_dpp_auth_failure(const char *ifname)
+void wpas_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_auth_failure(ifname);
+	wpas_hidl_notify_dpp_auth_failure(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
-void wpas_notify_dpp_failure(const char *ifname)
+void wpas_notify_dpp_failure(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP
-	if (!ifname)
+	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_fail(ifname);
+	wpas_hidl_notify_dpp_fail(wpa_s);
 #endif /* CONFIG_DPP */
 }
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index b4cb476..703ef8f 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -167,16 +167,16 @@
 void wpas_notify_hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s,
 						u8 code, u16 reauth_delay,
 						const char *url);
-void wpas_notify_dpp_config_received(const char *ifname,
+void wpas_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
 	    struct wpa_ssid *ssid);
-void wpas_notify_dpp_config_sent(const char *ifname);
-void wpas_notify_dpp_auth_success(const char *ifname);
-void wpas_notify_dpp_resp_pending(const char *ifname);
-void wpas_notify_dpp_not_compatible(const char *ifname);
-void wpas_notify_dpp_missing_auth(const char *ifname);
-void wpas_notify_dpp_configuration_failure(const char *ifname);
-void wpas_notify_dpp_timeout(const char *ifname);
-void wpas_notify_dpp_auth_failure(const char *ifname);
-void wpas_notify_dpp_failure(const char *ifname);
+void wpas_notify_dpp_config_sent(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_auth_success(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_timeout(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s);
+void wpas_notify_dpp_failure(struct wpa_supplicant *wpa_s);
 
 #endif /* NOTIFY_H */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index b9b0bea..3d3296f 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -2075,6 +2075,17 @@
 		return -1;
 	}
 
+	if (wpa_s->conf->p2p_interface_random_mac_addr) {
+		if (random_mac_addr(wpa_s->pending_interface_addr) < 0) {
+			wpa_printf(MSG_ERROR, "P2P: Failed to generate random MAC address "
+					      "for the group interface");
+			return -1;
+		}
+		wpa_printf(MSG_DEBUG, "P2P: Generate random MAC address " MACSTR " for the group",
+			MAC2STR(wpa_s->pending_interface_addr));
+	}
+
+
 	if (force_ifname[0]) {
 		wpa_printf(MSG_DEBUG, "P2P: Driver forced interface name %s",
 			   force_ifname);
@@ -2153,6 +2164,25 @@
 
 	wpas_p2p_clone_config(group_wpa_s, wpa_s);
 
+	if (wpa_s->conf->p2p_interface_random_mac_addr) {
+		if (wpa_drv_set_mac_addr(group_wpa_s, wpa_s->pending_interface_addr) < 0) {
+			wpa_msg(group_wpa_s, MSG_INFO,
+				"Failed to set random MAC address");
+			wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s, 0);
+			return NULL;
+		}
+
+		if (wpa_supplicant_update_mac_addr(group_wpa_s) < 0) {
+			wpa_msg(group_wpa_s, MSG_INFO,
+				"Could not update MAC address information");
+			wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s, 0);
+			return NULL;
+		}
+
+		wpa_printf(MSG_DEBUG, "P2P: Using random MAC address " MACSTR " for the group",
+			MAC2STR(wpa_s->pending_interface_addr));
+	}
+
 	return group_wpa_s;
 }
 
@@ -4314,6 +4344,57 @@
 					  WPA_IF_P2P_CLIENT, len, freq_list);
 }
 
+int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
+{
+	u8 addr[ETH_ALEN] = {0};
+
+	if (wpa_s->conf->p2p_device_random_mac_addr == 0)
+		return 0;
+
+	if (wpa_s->conf->ssid == NULL) {
+		if (random_mac_addr(addr) < 0) {
+			wpa_msg(wpa_s, MSG_INFO,
+				"Failed to generate random MAC address");
+			return -EINVAL;
+		}
+
+		// store generated MAC address.
+		if (wpa_s->conf->p2p_device_persistent_mac_addr)
+			os_free(wpa_s->conf->p2p_device_persistent_mac_addr);
+		size_t mac_addr_str_len = sizeof("00:00:00:00:00:00");
+		wpa_s->conf->p2p_device_persistent_mac_addr =
+			os_zalloc(mac_addr_str_len + 1);
+		os_snprintf(wpa_s->conf->p2p_device_persistent_mac_addr,
+			mac_addr_str_len, MACSTR, MAC2STR(addr));
+	} else {
+		// If there are existing saved groups, restore last MAC address.
+		// if there is no last used MAC address, the last one is factory MAC.
+		if (!wpa_s->conf->p2p_device_persistent_mac_addr)
+			return 0;
+
+		if (hwaddr_aton(wpa_s->conf->p2p_device_persistent_mac_addr, addr) < 0)
+			return -EINVAL;
+		wpa_msg(wpa_s, MSG_DEBUG, "Restore last used MAC address.");
+	}
+
+	if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Failed to set random MAC address");
+		return -EINVAL;
+	}
+
+	if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Could not update MAC address information");
+		return -EINVAL;
+	}
+
+	wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
+		MAC2STR(addr));
+
+	return 0;
+}
+
 
 /**
  * wpas_p2p_init - Initialize P2P module for %wpa_supplicant
@@ -4335,6 +4416,12 @@
 	if (global->p2p)
 		return 0;
 
+	if (wpas_p2p_mac_setup(wpa_s) < 0) {
+		wpa_msg(wpa_s, MSG_ERROR,
+			"Failed to initialize P2P random MAC address.");
+		return -1;
+	}
+
 	os_memset(&p2p, 0, sizeof(p2p));
 	p2p.cb_ctx = wpa_s;
 	p2p.debug_print = wpas_p2p_debug_print;
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 63910d1..0a08a88 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -211,6 +211,7 @@
 		      unsigned int period, unsigned int interval,
 		      unsigned int count);
 int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s);
+int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s);
 
 #else /* CONFIG_P2P */