wpa_supplicant(hidl): New EAP phase 2 params and NFC methods

1. Add support for the newly added EAP phase 2 params in HIDL interface.
2. Add the NFC handover related methods in HIDL interface.
3. Add a new utils for wpabuf manipulations and refactor all existing
wpabuf usages.

While there,
Change the input arg type for |setWfdDeviceInfoInternal| from hidl_array
to std::array.

Bug: 35270422
Bug: 35311730
Test: Compiles
Change-Id: I277b1bb128965f95f794a2cbae8c2aa8a79ddcf1
diff --git a/wpa_supplicant/hidl/hidl_manager.cpp b/wpa_supplicant/hidl/hidl_manager.cpp
index ed91dbf..1d77caa 100644
--- a/wpa_supplicant/hidl/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -11,6 +11,7 @@
 #include <regex>
 
 #include "hidl_manager.h"
+#include "misc_utils.h"
 
 extern "C" {
 #include "src/eap_common/eap_sim_common.h"
@@ -313,16 +314,6 @@
 	}
 }
 
-std::vector<uint8_t> convertWpaBufToVector(const struct wpabuf *buf)
-{
-	if (buf) {
-		return std::vector<uint8_t>(
-		    wpabuf_head_u8(buf), wpabuf_head_u8(buf) + wpabuf_len(buf));
-	} else {
-		return std::vector<uint8_t>();
-	}
-}
-
 int parseGsmAuthNetworkRequest(
     const std::string &params_str,
     std::vector<hidl_array<uint8_t, kGsmRandLenBytes>> *out_rands)
@@ -707,26 +698,30 @@
 	ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data;
 	if (std::string(result) == "SUCCESS") {
 		hidl_anqp_data.venueName =
-		    convertWpaBufToVector(anqp->venue_name);
+		    misc_utils::convertWpaBufToVector(anqp->venue_name);
 		hidl_anqp_data.roamingConsortium =
-		    convertWpaBufToVector(anqp->roaming_consortium);
+		    misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
 		hidl_anqp_data.ipAddrTypeAvailability =
-		    convertWpaBufToVector(anqp->ip_addr_type_availability);
+		    misc_utils::convertWpaBufToVector(
+			anqp->ip_addr_type_availability);
 		hidl_anqp_data.naiRealm =
-		    convertWpaBufToVector(anqp->nai_realm);
+		    misc_utils::convertWpaBufToVector(anqp->nai_realm);
 		hidl_anqp_data.anqp3gppCellularNetwork =
-		    convertWpaBufToVector(anqp->anqp_3gpp);
+		    misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
 		hidl_anqp_data.domainName =
-		    convertWpaBufToVector(anqp->domain_name);
+		    misc_utils::convertWpaBufToVector(anqp->domain_name);
 
 		hidl_hs20_anqp_data.operatorFriendlyName =
-		    convertWpaBufToVector(anqp->hs20_operator_friendly_name);
+		    misc_utils::convertWpaBufToVector(
+			anqp->hs20_operator_friendly_name);
 		hidl_hs20_anqp_data.wanMetrics =
-		    convertWpaBufToVector(anqp->hs20_wan_metrics);
+		    misc_utils::convertWpaBufToVector(anqp->hs20_wan_metrics);
 		hidl_hs20_anqp_data.connectionCapability =
-		    convertWpaBufToVector(anqp->hs20_connection_capability);
+		    misc_utils::convertWpaBufToVector(
+			anqp->hs20_connection_capability);
 		hidl_hs20_anqp_data.osuProvidersList =
-		    convertWpaBufToVector(anqp->hs20_osu_providers_list);
+		    misc_utils::convertWpaBufToVector(
+			anqp->hs20_osu_providers_list);
 	}
 
 	callWithEachStaIfaceCallback(
diff --git a/wpa_supplicant/hidl/misc_utils.h b/wpa_supplicant/hidl/misc_utils.h
new file mode 100644
index 0000000..fb8b86f
--- /dev/null
+++ b/wpa_supplicant/hidl/misc_utils.h
@@ -0,0 +1,63 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef MISC_UTILS_H_
+#define MISC_UTILS_H_
+
+extern "C" {
+#include "wpabuf.h"
+}
+
+namespace {
+// Custom deleter for wpabuf.
+void freeWpaBuf(wpabuf *ptr) { wpabuf_free(ptr); }
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_0 {
+namespace implementation {
+namespace misc_utils {
+using wpabuf_unique_ptr = std::unique_ptr<wpabuf, void (*)(wpabuf *)>;
+
+// Creates a unique_ptr for wpabuf ptr with a custom deleter.
+inline wpabuf_unique_ptr createWpaBufUniquePtr(struct wpabuf *raw_ptr)
+{
+	return {raw_ptr, freeWpaBuf};
+}
+
+// Creates a wpabuf ptr with a custom deleter copying the data from the provided
+// vector.
+inline wpabuf_unique_ptr convertVectorToWpaBuf(const std::vector<uint8_t> &data)
+{
+	return createWpaBufUniquePtr(
+	    wpabuf_alloc_copy(data.data(), data.size()));
+}
+
+// Copies the provided wpabuf contents to a std::vector.
+inline std::vector<uint8_t> convertWpaBufToVector(const struct wpabuf *buf)
+{
+	if (buf) {
+		return std::vector<uint8_t>(
+		    wpabuf_head_u8(buf), wpabuf_head_u8(buf) + wpabuf_len(buf));
+	} else {
+		return std::vector<uint8_t>();
+	}
+}
+
+}  // namespace misc_utils
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+#endif  // MISC_UTILS_H_
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
index 4ddb34a..d71bc71 100644
--- a/wpa_supplicant/hidl/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -10,6 +10,7 @@
 #include "hidl_manager.h"
 #include "hidl_return_util.h"
 #include "iface_config_utils.h"
+#include "misc_utils.h"
 #include "p2p_iface.h"
 
 extern "C" {
@@ -462,6 +463,38 @@
 	    &P2pIface::setWfdDeviceInfoInternal, _hidl_cb, info);
 }
 
+Return<void> P2pIface::createNfcHandoverRequestMessage(
+    createNfcHandoverRequestMessage_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::createNfcHandoverRequestMessageInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::createNfcHandoverSelectMessage(
+    createNfcHandoverSelectMessage_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::createNfcHandoverSelectMessageInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::reportNfcHandoverResponse(
+    const hidl_vec<uint8_t>& request, reportNfcHandoverResponse_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::reportNfcHandoverResponseInternal, _hidl_cb, request);
+}
+
+Return<void> P2pIface::reportNfcHandoverInitiation(
+    const hidl_vec<uint8_t>& select, reportNfcHandoverInitiation_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::reportNfcHandoverInitiationInternal, _hidl_cb, select);
+}
+
 std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -878,24 +911,19 @@
     const std::vector<uint8_t>& query, const std::vector<uint8_t>& response)
 {
 	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	struct wpabuf* query_buf = wpabuf_alloc(query.size());
-	if (!query_buf) {
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+	auto response_buf = misc_utils::convertVectorToWpaBuf(response);
+	if (!query_buf || !response_buf) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
-	wpabuf_put_data(query_buf, query.data(), query.size());
-
-	struct wpabuf* response_buf = wpabuf_alloc(response.size());
-	if (!query_buf) {
-		wpabuf_free(query_buf);
+	if (wpas_p2p_service_add_bonjour(
+		wpa_s, query_buf.get(), response_buf.get())) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
-	wpabuf_put_data(response_buf, response.data(), response.size());
-
-	if (wpas_p2p_service_add_bonjour(wpa_s, query_buf, response_buf)) {
-		wpabuf_free(query_buf);
-		wpabuf_free(response_buf);
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
+	// If successful, the wpabuf is referenced internally and hence should
+	// not be freed.
+	query_buf.release();
+	response_buf.release();
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
@@ -903,15 +931,11 @@
     const std::vector<uint8_t>& query)
 {
 	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	struct wpabuf* query_buf = wpabuf_alloc(query.size());
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
 	if (!query_buf) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
-	wpabuf_put_data(query_buf, query.data(), query.size());
-
-	int ret = wpas_p2p_service_del_bonjour(wpa_s, query_buf);
-	wpabuf_free(query_buf);
-	if (ret) {
+	if (wpas_p2p_service_del_bonjour(wpa_s, query_buf.get())) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	return {SupplicantStatusCode::SUCCESS, ""};
@@ -949,14 +973,12 @@
     const std::vector<uint8_t>& query)
 {
 	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	struct wpabuf* query_buf = wpabuf_alloc(query.size());
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
 	if (!query_buf) {
 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
 	}
-	wpabuf_put_data(query_buf, query.data(), query.size());
 	uint64_t identifier =
-	    wpas_p2p_sd_request(wpa_s, peer_address.data(), query_buf);
-	wpabuf_free(query_buf);
+	    wpas_p2p_sd_request(wpa_s, peer_address.data(), query_buf.get());
 	if (identifier == 0) {
 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
 	}
@@ -1108,7 +1130,7 @@
 }
 
 SupplicantStatus P2pIface::setWfdDeviceInfoInternal(
-    const hidl_array<uint8_t, 8>& info)
+    const std::array<uint8_t, 8>& info)
 {
 	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
 	uint32_t wfd_device_info_hex_len = info.size() * 2 + 1;
@@ -1130,6 +1152,64 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+P2pIface::createNfcHandoverRequestMessageInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto buf = misc_utils::createWpaBufUniquePtr(
+	    wpas_p2p_nfc_handover_req(wpa_s, 1));
+	if (!buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpaBufToVector(buf.get())};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+P2pIface::createNfcHandoverSelectMessageInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto buf = misc_utils::createWpaBufUniquePtr(
+	    wpas_p2p_nfc_handover_sel(wpa_s, 1, 0));
+	if (!buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpaBufToVector(buf.get())};
+}
+
+SupplicantStatus P2pIface::reportNfcHandoverResponseInternal(
+    const std::vector<uint8_t>& request)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto req = misc_utils::convertVectorToWpaBuf(request);
+	auto sel = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
+	if (!req || !sel) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+
+	if (wpas_p2p_nfc_report_handover(wpa_s, 0, req.get(), sel.get(), 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::reportNfcHandoverInitiationInternal(
+    const std::vector<uint8_t>& select)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto req = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
+	auto sel = misc_utils::convertVectorToWpaBuf(select);
+	if (!req || !sel) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+
+	if (wpas_p2p_nfc_report_handover(wpa_s, 1, req.get(), sel.get(), 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
index 07551bd..e8770c6 100644
--- a/wpa_supplicant/hidl/p2p_iface.h
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -174,6 +174,16 @@
 	Return<void> setWfdDeviceInfo(
 	    const hidl_array<uint8_t, 8>& info,
 	    setWfdDeviceInfo_cb _hidl_cb) override;
+	Return<void> createNfcHandoverRequestMessage(
+	    createNfcHandoverRequestMessage_cb _hidl_cb) override;
+	Return<void> createNfcHandoverSelectMessage(
+	    createNfcHandoverSelectMessage_cb _hidl_cb) override;
+	Return<void> reportNfcHandoverResponse(
+	    const hidl_vec<uint8_t>& request,
+	    reportNfcHandoverResponse_cb _hidl_cb) override;
+	Return<void> reportNfcHandoverInitiation(
+	    const hidl_vec<uint8_t>& select,
+	    reportNfcHandoverInitiation_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -268,7 +278,15 @@
 	SupplicantStatus setWpsConfigMethodsInternal(uint16_t config_methods);
 	SupplicantStatus enableWfdInternal(bool enable);
 	SupplicantStatus setWfdDeviceInfoInternal(
-	    const hidl_array<uint8_t, 8>& info);
+	    const std::array<uint8_t, 8>& info);
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	createNfcHandoverRequestMessageInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	createNfcHandoverSelectMessageInternal();
+	SupplicantStatus reportNfcHandoverResponseInternal(
+	    const std::vector<uint8_t>& request);
+	SupplicantStatus reportNfcHandoverInitiationInternal(
+	    const std::vector<uint8_t>& select);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
diff --git a/wpa_supplicant/hidl/sta_network.cpp b/wpa_supplicant/hidl/sta_network.cpp
index cae61e6..3d92973 100644
--- a/wpa_supplicant/hidl/sta_network.cpp
+++ b/wpa_supplicant/hidl/sta_network.cpp
@@ -9,8 +9,13 @@
 
 #include "hidl_manager.h"
 #include "hidl_return_util.h"
+#include "misc_utils.h"
 #include "sta_network.h"
 
+extern "C" {
+#include "wps_supplicant.h"
+}
+
 namespace {
 using android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
 using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
@@ -50,9 +55,10 @@
 constexpr char const *kEapMethodStrings[kEapMethodMax] = {
     "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS"};
 constexpr uint32_t kEapPhase2MethodMax =
-    static_cast<uint32_t>(ISupplicantStaNetwork::EapPhase2Method::GTC) + 1;
+    static_cast<uint32_t>(ISupplicantStaNetwork::EapPhase2Method::AKA_PRIME) +
+    1;
 constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
-    "NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC"};
+    "NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC", "SIM", "AKA", "AKA'"};
 constexpr char kEapPhase2AuthPrefix[] = "auth=";
 constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
 constexpr char kNetworkEapSimGsmAuthResponse[] = "GSM-AUTH";
@@ -538,6 +544,14 @@
 	    &StaNetwork::getIdStrInternal, _hidl_cb);
 }
 
+Return<void> StaNetwork::getWpsNfcConfigurationToken(
+    getWpsNfcConfigurationToken_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getWpsNfcConfigurationTokenInternal, _hidl_cb);
+}
+
 Return<void> StaNetwork::enable(bool no_connect, enable_cb _hidl_cb)
 {
 	return validateAndCall(
@@ -1379,6 +1393,20 @@
 	return {{SupplicantStatusCode::SUCCESS, ""}, {wpa_ssid->id_str}};
 }
 
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getWpsNfcConfigurationTokenInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	auto token_buf = misc_utils::createWpaBufUniquePtr(
+	    wpas_wps_network_config_token(wpa_s, 0, wpa_ssid));
+	if (!token_buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpaBufToVector(token_buf.get())};
+}
+
 SupplicantStatus StaNetwork::enableInternal(bool no_connect)
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
diff --git a/wpa_supplicant/hidl/sta_network.h b/wpa_supplicant/hidl/sta_network.h
index 063fa61..c0df028 100644
--- a/wpa_supplicant/hidl/sta_network.h
+++ b/wpa_supplicant/hidl/sta_network.h
@@ -157,6 +157,8 @@
 	Return<void> getEapDomainSuffixMatch(
 	    getEapDomainSuffixMatch_cb _hidl_cb) override;
 	Return<void> getIdStr(getIdStr_cb _hidl_cb) override;
+	Return<void> getWpsNfcConfigurationToken(
+	    getWpsNfcConfigurationToken_cb _hidl_cb) override;
 	Return<void> enable(bool no_connect, enable_cb _hidl_cb) override;
 	Return<void> disable(disable_cb _hidl_cb) override;
 	Return<void> select(select_cb _hidl_cb) override;
@@ -260,6 +262,8 @@
 	std::pair<SupplicantStatus, std::string>
 	getEapDomainSuffixMatchInternal();
 	std::pair<SupplicantStatus, std::string> getIdStrInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	getWpsNfcConfigurationTokenInternal();
 	SupplicantStatus enableInternal(bool no_connect);
 	SupplicantStatus disableInternal();
 	SupplicantStatus selectInternal();
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 74a420c..228269e 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -2210,7 +2210,7 @@
 #ifdef CONFIG_WPS_NFC
 
 #ifdef CONFIG_WPS_ER
-static struct wpabuf *
+struct wpabuf *
 wpas_wps_network_config_token(struct wpa_supplicant *wpa_s, int ndef,
 			      struct wpa_ssid *ssid)
 {
diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
index c8fe47e..eb1615a 100644
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -62,6 +62,8 @@
 					     int ndef, const char *uuid);
 int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
 void wpas_wps_update_config(struct wpa_supplicant *wpa_s);
+struct wpabuf * wpas_wps_network_config_token(struct wpa_supplicant *wpa_s,
+					  int ndef, struct wpa_ssid * ssid);
 struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
 					  int ndef, const char *id_str);
 struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef);