[DPP] Added support for DPP in hidl

Added support for DPP in hidl, added new APIs for Initiator mode
and callbacks for event reporting. Added hidl notifications in
dpp_supplicant.

Bug: 112197021
Test: act.py -c ../WifiDppConfig.json -tc WifiDppTest
Change-Id: I5029a2ed41b46c4eae06cdd79afca196e46bfb78
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 673800b..9bda274 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1812,7 +1812,8 @@
     libhidlbase \
     libhidltransport \
     libutils \
-    liblog
+    liblog \
+    libssl
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
     $(LOCAL_PATH)/hidl/$(HIDL_INTERFACE_VERSION)
 include $(BUILD_STATIC_LIBRARY)
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 899c4c2..e775422 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -25,6 +25,7 @@
 #include "scan.h"
 #include "notify.h"
 #include "dpp_supplicant.h"
+#include "hidl.h"
 
 
 static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
@@ -468,6 +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);
 		offchannel_send_action_done(wpa_s);
 		wpas_dpp_listen_stop(wpa_s);
 		dpp_auth_deinit(auth);
@@ -1139,6 +1141,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);
 		return;
 	}
 	wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
@@ -1260,8 +1263,12 @@
 		return;
 
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
-	if (wpa_s->conf->dpp_config_processing < 2)
+
+	wpas_notify_dpp_config_received(wpa_s->ifname, ssid);
+
+	if (wpa_s->conf->dpp_config_processing < 2) {
 		return;
+	}
 
 	wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
 	ssid->disabled = 0;
@@ -1382,6 +1389,7 @@
 
 fail:
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+	wpas_notify_dpp_configuration_failure(wpa_s->ifname);
 	dpp_auth_deinit(wpa_s->dpp_auth);
 	wpa_s->dpp_auth = NULL;
 }
@@ -1459,6 +1467,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);
 #ifdef CONFIG_TESTING_OPTIONS
 	if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
 		wpa_printf(MSG_INFO,
@@ -1515,11 +1524,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);
 			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);
 		return;
 	}
 	os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
@@ -1557,6 +1568,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);
 		return;
 	}
 
@@ -2147,8 +2159,10 @@
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
 		MAC2STR(sa));
 	resp = dpp_conf_req_rx(auth, query, query_len);
-	if (!resp)
+	if (!resp) {
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+		wpas_notify_dpp_configuration_failure(wpa_s->ifname);
+	}
 	auth->conf_resp = resp;
 	return resp;
 }
@@ -2178,10 +2192,14 @@
 	eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
 	offchannel_send_action_done(wpa_s);
 	wpas_dpp_listen_stop(wpa_s);
-	if (ok)
+	if (ok) {
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
-	else
+		wpas_notify_dpp_config_sent(wpa_s->ifname);
+	}
+	else {
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+		wpas_notify_dpp_configuration_failure(wpa_s->ifname);
+	}
 	dpp_auth_deinit(wpa_s->dpp_auth);
 	wpa_s->dpp_auth = NULL;
 	wpabuf_free(resp);
diff --git a/wpa_supplicant/hidl/1.2/hidl.cpp b/wpa_supplicant/hidl/1.2/hidl.cpp
index adbeaeb..60ee85f 100644
--- a/wpa_supplicant/hidl/1.2/hidl.cpp
+++ b/wpa_supplicant/hidl/1.2/hidl.cpp
@@ -25,6 +25,11 @@
 using android::hardware::handleTransportPoll;
 using android::hardware::setupTransportPolling;
 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);
 
 void wpas_hidl_sock_handler(
     int sock, void * /* eloop_ctx */, void * /* sock_ctx */)
@@ -642,3 +647,141 @@
 
 	hidl_manager->notifyEapError(wpa_s, error_code);
 }
+
+void wpas_hidl_notify_dpp_config_received(const char *ifname,
+	    struct wpa_ssid *ssid)
+{
+	if (!ifname || !ssid)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying DPP configuration received for SSID %d", ssid->id);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyDppConfigReceived(ifname, ssid);
+}
+
+void wpas_hidl_notify_dpp_config_sent(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_success(ifname, DppSuccessCode::CONFIGURATION_SENT);
+}
+
+/* DPP Progress notifications */
+void wpas_hidl_notify_dpp_auth_success(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_progress(ifname, DppProgressCode::AUTHENTICATION_SUCCESS);
+}
+
+void wpas_hidl_notify_dpp_resp_pending(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_progress(ifname, DppProgressCode::RESPONSE_PENDING);
+}
+
+/* DPP Failure notifications */
+void wpas_hidl_notify_dpp_not_compatible(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::NOT_COMPATIBLE);
+}
+
+void wpas_hidl_notify_dpp_missing_auth(const char *ifname)
+{
+	if (!ifname)
+		return;
+}
+
+void wpas_hidl_notify_dpp_configuration_failure(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::CONFIGURATION);
+}
+
+void wpas_hidl_notify_dpp_timeout(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::TIMEOUT);
+}
+
+void wpas_hidl_notify_dpp_auth_failure(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::AUTHENTICATION);
+}
+
+void wpas_hidl_notify_dpp_fail(const char *ifname)
+{
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_failure(ifname, DppFailureCode::FAILURE);
+}
+
+/* DPP notification helper functions */
+static void wpas_hidl_notify_dpp_success(const char *ifname, DppSuccessCode code)
+{
+	if (!ifname)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying DPP success event %d", code);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyDppSuccess(ifname, code);
+}
+
+static void wpas_hidl_notify_dpp_failure(const char *ifname, DppFailureCode code)
+{
+	if (!ifname)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying DPP failure event %d", code);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyDppFailure(ifname, code);
+}
+
+static void wpas_hidl_notify_dpp_progress(const char *ifname, DppProgressCode code)
+{
+	if (!ifname)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying DPP progress event %d", code);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyDppProgress(ifname, code);
+}
diff --git a/wpa_supplicant/hidl/1.2/hidl.h b/wpa_supplicant/hidl/1.2/hidl.h
index a457398..914bc7b 100644
--- a/wpa_supplicant/hidl/1.2/hidl.h
+++ b/wpa_supplicant/hidl/1.2/hidl.h
@@ -99,6 +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,
+		    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);
 #else   // CONFIG_CTRL_IFACE_HIDL
 static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
 {
@@ -204,6 +216,29 @@
 static void wpas_hidl_notify_eap_error(
     struct wpa_supplicant *wpa_s, int error_code)
 {}
+static void wpas_hidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+	    struct wpa_ssid *ssid)
+{}
+static void wpas_hidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+	    struct wpa_ssid *ssid);
+static void wpas_hidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_invalid_uri(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_hidl_notify_dpp_failure(struct wpa_supplicant *wpa_s)
+{}
 #endif  // CONFIG_CTRL_IFACE_HIDL
 
 #ifdef _cplusplus
diff --git a/wpa_supplicant/hidl/1.2/hidl_manager.cpp b/wpa_supplicant/hidl/1.2/hidl_manager.cpp
index 3714439..19ea4b1 100644
--- a/wpa_supplicant/hidl/1.2/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.2/hidl_manager.cpp
@@ -318,6 +318,35 @@
 	}
 }
 
+template <class CallbackTypeV1_0, class CallbackTypeV1_2>
+void callWithEachIfaceCallback_1_2(
+    const std::string &ifname,
+    const std::function<
+	android::hardware::Return<void>(android::sp<CallbackTypeV1_2>)> &method,
+    const std::map<
+	const std::string, std::vector<android::sp<CallbackTypeV1_0>>>
+	&callbacks_map)
+{
+	if (ifname.empty())
+		return;
+
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == callbacks_map.end())
+		return;
+	const auto &iface_callback_list = iface_callback_map_iter->second;
+	for (const auto &callback : iface_callback_list) {
+		android::sp<CallbackTypeV1_2> callback_1_2 =
+		    CallbackTypeV1_2::castFrom(callback);
+		if (callback_1_2 == nullptr)
+			continue;
+
+		if (!method(callback_1_2).isOk()) {
+			wpa_printf(
+			    MSG_ERROR, "Failed to invoke HIDL iface callback");
+		}
+	}
+}
+
 template <class CallbackType>
 void callWithEachNetworkCallback(
     const std::string &ifname, int network_id,
@@ -1455,6 +1484,88 @@
 }
 
 /**
+ * Notify listener about a new DPP configuration success event
+ *
+ * @param ifname Interface name
+ * @param config Configuration object
+ */
+void HidlManager::notifyDppConfigReceived(const char *ifname,
+		struct wpa_ssid *config)
+{
+	DppAkm securityAkm;
+	char *password;
+	std::string hidl_ifname = ifname;
+
+	if (config->key_mgmt & WPA_KEY_MGMT_SAE) {
+		securityAkm = DppAkm::SAE;
+	} else if (config->key_mgmt & WPA_KEY_MGMT_PSK) {
+			securityAkm = DppAkm::PSK;
+	} else {
+		/* Unsupported AKM */
+		notifyDppFailure(ifname, DppFailureCode::CONFIGURATION);
+		return;
+	}
+
+	password = config->passphrase;
+	std::vector < uint8_t > hidl_ssid;
+	hidl_ssid.assign(config->ssid, config->ssid + config->ssid_len);
+
+	/* At this point, the network is already registered, notify about new
+	 * received configuration
+	 */
+	callWithEachStaIfaceCallback_1_2(hidl_ifname,
+			std::bind(
+					&V1_2::ISupplicantStaIfaceCallback::onDppSuccessConfigReceived,
+					std::placeholders::_1, hidl_ssid, password, config->psk,
+					securityAkm));
+}
+
+/**
+ * Notify listener about a DPP success event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void HidlManager::notifyDppSuccess(const char *ifname, DppSuccessCode code)
+{
+	std::string hidl_ifname = ifname;
+
+	callWithEachStaIfaceCallback_1_2(hidl_ifname,
+			std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppSuccess,
+					std::placeholders::_1, code));
+}
+
+/**
+ * Notify listener about a DPP failure event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void HidlManager::notifyDppFailure(const char *ifname, DppFailureCode code)
+{
+	std::string hidl_ifname = ifname;
+
+	callWithEachStaIfaceCallback_1_2(hidl_ifname,
+			std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppFailure,
+					std::placeholders::_1, code));
+}
+
+/**
+ * Notify listener about a DPP progress event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void HidlManager::notifyDppProgress(const char *ifname, DppProgressCode code)
+{
+	std::string hidl_ifname = ifname;
+
+	callWithEachStaIfaceCallback_1_2(hidl_ifname,
+			std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppProgress,
+					std::placeholders::_1, code));
+}
+
+/**
  * Retrieve the |ISupplicantP2pIface| hidl object reference using the provided
  * ifname.
  *
@@ -1783,8 +1894,8 @@
 }
 
 /**
- * Helper fucntion to invoke the provided callback method on all the
- * registered V1.1 iface callback hidl objects for the specified
+ * Helper function to invoke the provided callback method on all the
+ * registered V1.1 interface callback hidl objects for the specified
  * |ifname|.
  *
  * @param ifname Name of the corresponding interface.
@@ -1800,8 +1911,25 @@
 }
 
 /**
- * Helper fucntion to invoke the provided callback method on all the
- * registered iface callback hidl objects for the specified
+ * Helper function to invoke the provided callback method on all the
+ * registered V1.2 interface callback hidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required hidl method from
+ * |V1_2::ISupplicantIfaceCallback|.
+ */
+void HidlManager::callWithEachStaIfaceCallback_1_2(
+    const std::string &ifname,
+    const std::function<
+	Return<void>(android::sp<V1_2::ISupplicantStaIfaceCallback>)> &method)
+{
+	callWithEachIfaceCallback_1_2(ifname, method, sta_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered interface callback hidl objects for the specified
  * |ifname|.
  *
  * @param ifname Name of the corresponding interface.
diff --git a/wpa_supplicant/hidl/1.2/hidl_manager.h b/wpa_supplicant/hidl/1.2/hidl_manager.h
index 47b6e7d..a7e2c86 100644
--- a/wpa_supplicant/hidl/1.2/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.2/hidl_manager.h
@@ -16,7 +16,7 @@
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
-#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
 
 #include "p2p_iface.h"
@@ -128,6 +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,
+			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);
 
 	// Methods called from hidl objects.
 	void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
@@ -197,6 +202,10 @@
 	    const std::string &ifname,
 	    const std::function<android::hardware::Return<void>(
 		android::sp<V1_1::ISupplicantStaIfaceCallback>)> &method);
+	void callWithEachStaIfaceCallback_1_2(
+	    const std::string &ifname,
+	    const std::function<android::hardware::Return<void>(
+	    android::sp<V1_2::ISupplicantStaIfaceCallback>)> &method);
 	void callWithEachP2pNetworkCallback(
 	    const std::string &ifname, int network_id,
 	    const std::function<android::hardware::Return<void>(
diff --git a/wpa_supplicant/hidl/1.2/sta_iface.cpp b/wpa_supplicant/hidl/1.2/sta_iface.cpp
index 1b8e350..974b0c9 100644
--- a/wpa_supplicant/hidl/1.2/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.2/sta_iface.cpp
@@ -20,6 +20,8 @@
 #include "interworking.h"
 #include "hs20_supplicant.h"
 #include "wps_supplicant.h"
+#include "dpp_supplicant.h"
+#include "dpp.h"
 }
 
 namespace {
@@ -237,6 +239,16 @@
 	    &StaIface::registerCallbackInternal, _hidl_cb, callback_1_0);
 }
 
+Return<void> StaIface::registerCallback_1_2(
+    const sp<V1_2::ISupplicantStaIfaceCallback> &callback,
+    registerCallback_cb _hidl_cb)
+{
+	sp<V1_1::ISupplicantStaIfaceCallback> callback_1_1 = callback;
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::registerCallbackInternal, _hidl_cb, callback_1_1);
+}
+
 Return<void> StaIface::reassociate(reassociate_cb _hidl_cb)
 {
 	return validateAndCall(
@@ -519,6 +531,50 @@
 	    &StaIface::getKeyMgmtCapabilitiesInternal, _hidl_cb);
 }
 
+Return<void> StaIface::addDppPeerUri(const hidl_string& uri,
+		addDppPeerUri_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaIface::addDppPeerUriInternal, _hidl_cb, uri);
+}
+
+Return<void> StaIface::removeDppUri(uint32_t bootstrap_id,
+		removeDppUri_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaIface::removeDppUriInternal, _hidl_cb, bootstrap_id);
+}
+
+Return<void> StaIface::startDppConfiguratorInitiator(uint32_t peer_bootstrap_id,
+		uint32_t own_bootstrap_id, const hidl_string& ssid,
+		const hidl_string& password, const hidl_string& psk,
+		DppNetRole net_role, DppAkm security_akm,
+		startDppConfiguratorInitiator_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaIface::startDppConfiguratorInitiatorInternal, _hidl_cb, peer_bootstrap_id,
+		own_bootstrap_id, ssid, password, psk, net_role, security_akm);
+}
+
+Return<void> StaIface::startDppEnrolleeInitiator(uint32_t peer_bootstrap_id,
+		uint32_t own_bootstrap_id, startDppConfiguratorInitiator_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaIface::startDppEnrolleeInitiatorInternal, _hidl_cb, peer_bootstrap_id,
+		own_bootstrap_id);
+}
+
+Return<void> StaIface::stopDppInitiator(stopDppInitiator_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaIface::stopDppInitiatorInternal, _hidl_cb);
+}
+
 std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -1071,6 +1127,169 @@
 	return {{SupplicantStatusCode::SUCCESS, ""}, mask};
 }
 
+std::pair<SupplicantStatus, uint32_t>
+StaIface::addDppPeerUriInternal(const std::string& uri)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	int32_t id;
+
+	id = wpas_dpp_qr_code(wpa_s, uri.c_str());
+
+	if (id > 0) {
+		return {{SupplicantStatusCode::SUCCESS, ""}, id};
+	}
+#endif
+	return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, -1};
+}
+
+SupplicantStatus StaIface::removeDppUriInternal(uint32_t bootstrap_id)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string bootstrap_id_str;
+
+	if (bootstrap_id == 0) {
+		bootstrap_id_str = "*";
+	}
+	else {
+		bootstrap_id_str = std::to_string(bootstrap_id);
+	}
+
+	if (wpas_dpp_bootstrap_remove(wpa_s, bootstrap_id_str.c_str()) >= 0) {
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+#endif
+	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+}
+
+SupplicantStatus StaIface::startDppConfiguratorInitiatorInternal(
+		uint32_t peer_bootstrap_id,	uint32_t own_bootstrap_id,
+		const std::string& ssid, const std::string& password,
+		const std::string& psk, DppNetRole net_role, DppAkm security_akm)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string cmd = "";
+
+	if (net_role != DppNetRole::AP &&
+			net_role != DppNetRole::STA) {
+		wpa_printf(MSG_ERROR,
+			   "DPP: Error: Invalid network role specified: %d", net_role);
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+
+	cmd += " peer=" + std::to_string(peer_bootstrap_id);
+	cmd += (own_bootstrap_id > 0) ?
+			" own=" + std::to_string(own_bootstrap_id) : "";
+
+	/* SAE AKM requires SSID and password to be initialized */
+	if ((security_akm == DppAkm::SAE ||
+			security_akm == DppAkm::PSK_SAE) &&
+			(ssid.empty() || password.empty())) {
+		wpa_printf(MSG_ERROR, "DPP: Error: Password or SSID not specified");
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	} else if (security_akm == DppAkm::PSK ||
+			security_akm == DppAkm::PSK_SAE) {
+		/* PSK AKM requires SSID and password/psk to be initialized */
+		if (ssid.empty()) {
+			wpa_printf(MSG_ERROR, "DPP: Error: SSID not specified");
+			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+		}
+		if (password.empty() && psk.empty()) {
+			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";
+	cmd += (ssid.empty()) ? "" : " ssid=" + ssid;
+
+	if (!psk.empty()) {
+		cmd += " psk=" + psk;
+	} else {
+		cmd += (password.empty()) ? "" : " pass=" + password;
+	}
+
+	std::string role = "";
+	if (net_role == DppNetRole::AP) {
+		role = "ap-";
+	}
+	else {
+		role = "sta-";
+	}
+
+	switch (security_akm) {
+	case DppAkm::PSK:
+		role += "psk";
+		break;
+
+	case DppAkm::SAE:
+		role += "sae";
+		break;
+
+	case DppAkm::PSK_SAE:
+		role += "psk-sae";
+		break;
+
+	default:
+		wpa_printf(MSG_ERROR,
+			   "DPP: Invalid or unsupported security AKM specified: %d", security_akm);
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+
+	cmd += " conf=";
+	cmd += role;
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP initiator command: %s", cmd.c_str());
+
+	if (wpas_dpp_auth_init(wpa_s, cmd.c_str()) == 0) {
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+#endif
+	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+}
+
+SupplicantStatus StaIface::startDppEnrolleeInitiatorInternal(uint32_t peer_bootstrap_id,
+			uint32_t own_bootstrap_id) {
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string cmd = "";
+
+	/* Report received configuration to HIDL and create an internal profile */
+	wpa_s->conf->dpp_config_processing = 1;
+
+	cmd += " peer=" + std::to_string(peer_bootstrap_id);
+	cmd += (own_bootstrap_id > 0) ?
+			" own=" + std::to_string(own_bootstrap_id) : "";
+
+	cmd += " role=enrollee";
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP initiator command: %s", cmd.c_str());
+
+	if (wpas_dpp_auth_init(wpa_s, cmd.c_str()) == 0) {
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+#endif
+	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+}
+SupplicantStatus StaIface::stopDppInitiatorInternal()
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+
+	wpas_dpp_stop(wpa_s);
+	return {SupplicantStatusCode::SUCCESS, ""};
+#else
+	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+#endif
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/1.2/sta_iface.h b/wpa_supplicant/hidl/1.2/sta_iface.h
index bda9d93..5a04ee3 100644
--- a/wpa_supplicant/hidl/1.2/sta_iface.h
+++ b/wpa_supplicant/hidl/1.2/sta_iface.h
@@ -16,7 +16,7 @@
 #include <android-base/macros.h>
 
 #include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIface.h>
-#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.2/ISupplicantStaNetwork.h>
 
 extern "C"
@@ -77,6 +77,9 @@
 	Return<void> registerCallback_1_1(
 	    const sp<V1_1::ISupplicantStaIfaceCallback>& callback,
 	    registerCallback_cb _hidl_cb) override;
+	Return<void> registerCallback_1_2(
+	    const sp<V1_2::ISupplicantStaIfaceCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
 	Return<void> reassociate(reassociate_cb _hidl_cb) override;
 	Return<void> reconnect(reconnect_cb _hidl_cb) override;
 	Return<void> disconnect(disconnect_cb _hidl_cb) override;
@@ -161,6 +164,19 @@
 	    bool enable, enableAutoReconnect_cb _hidl_cb) override;
 	Return<void> getKeyMgmtCapabilities(
 	    getKeyMgmtCapabilities_cb _hidl_cb) override;
+	Return<void> addDppPeerUri(const hidl_string& uri,
+			addDppPeerUri_cb _hidl_cb) override;
+	Return<void> removeDppUri(uint32_t bootstrap_id,
+			removeDppUri_cb _hidl_cb) override;
+	Return<void> startDppConfiguratorInitiator(uint32_t peer_bootstrap_id,
+			uint32_t own_bootstrap_id, const hidl_string& ssid,
+			const hidl_string& password, const hidl_string& psk,
+			DppNetRole net_role, DppAkm security_akm,
+			startDppConfiguratorInitiator_cb _hidl_cb) override;
+	Return<void> startDppEnrolleeInitiator(uint32_t peer_bootstrap_id,
+			uint32_t own_bootstrap_id,
+			startDppConfiguratorInitiator_cb _hidl_cb) override;
+	Return<void> stopDppInitiator(stopDppInitiator_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -235,6 +251,16 @@
 	SupplicantStatus removeExtRadioWorkInternal(uint32_t id);
 	SupplicantStatus enableAutoReconnectInternal(bool enable);
 	std::pair<SupplicantStatus, uint32_t> getKeyMgmtCapabilitiesInternal();
+	std::pair<SupplicantStatus, uint32_t> addDppPeerUriInternal(const std::string& uri);
+	SupplicantStatus removeDppUriInternal(uint32_t bootstrap_id);
+	SupplicantStatus startDppConfiguratorInitiatorInternal(uint32_t peer_bootstrap_id,
+			uint32_t own_bootstrap_id,
+		    const std::string& ssid, const std::string& password,
+			const std::string& psk, DppNetRole net_role, DppAkm security_akm);
+	SupplicantStatus startDppEnrolleeInitiatorInternal(uint32_t peer_bootstrap_id,
+			uint32_t own_bootstrap_id);
+	SupplicantStatus stopDppInitiatorInternal();
+
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 95da23f..37a4595 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -1026,3 +1026,112 @@
 }
 
 #endif /* CONFIG_MESH */
+
+/*
+ * DPP Notifications
+ */
+
+/* DPP Success notifications */
+
+void wpas_notify_dpp_config_received(const char *ifname,
+	    struct wpa_ssid *ssid)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_config_received(ifname, ssid);
+#endif /* CONFIG_DPP */
+}
+
+void wpas_notify_dpp_config_sent(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_config_sent(ifname);
+#endif /* CONFIG_DPP */
+}
+
+/* DPP Progress notifications */
+void wpas_notify_dpp_auth_success(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_auth_success(ifname);
+#endif /* CONFIG_DPP */
+}
+
+void wpas_notify_dpp_resp_pending(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_resp_pending(ifname);
+#endif /* CONFIG_DPP */
+}
+
+/* DPP Failure notifications */
+void wpas_notify_dpp_not_compatible(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_not_compatible(ifname);
+#endif /* CONFIG_DPP */
+}
+
+void wpas_notify_dpp_missing_auth(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_missing_auth(ifname);
+#endif /* CONFIG_DPP */
+}
+
+void wpas_notify_dpp_configuration_failure(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_configuration_failure(ifname);
+#endif /* CONFIG_DPP */
+}
+
+void wpas_notify_dpp_timeout(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_timeout(ifname);
+#endif /* CONFIG_DPP */
+}
+
+void wpas_notify_dpp_auth_failure(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_auth_failure(ifname);
+#endif /* CONFIG_DPP */
+}
+
+void wpas_notify_dpp_failure(const char *ifname)
+{
+#ifdef CONFIG_DPP
+	if (!ifname)
+		return;
+
+	wpas_hidl_notify_dpp_fail(ifname);
+#endif /* CONFIG_DPP */
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index c3ac3d1..b4cb476 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -167,4 +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,
+	    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);
+
 #endif /* NOTIFY_H */