Wifi: DPP STA Enrollee-Responder mode
Added below APIs for DPP STA Enrollee-Responder mode
1. API to start DPP in Enrollee-Responder mode
2. API to generate DPP bootstrap URI
3. API to stop DPP in Enrollee-Responder mode
which internally remove the bootstrap and stop listen.
Bug: 162686712
Test: act.py -c <dpp config file> -tc WifiDppTest
Change-Id: I9c7f25362b38ce1acffe35abf8600d33c054614a
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index b11e371..3c0431b 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -533,8 +533,9 @@
# Opportunistic Wireless Encryption (OWE)
CONFIG_OWE=y
-# Easy Connect (Device Provisioning Protocol - DPP R1)
+# Easy Connect (Device Provisioning Protocol - DPP R1 & R2)
CONFIG_DPP=y
+CONFIG_DPP2=y
# WPA3-Personal (SAE)
CONFIG_SAE=y
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 7aa5ebf..731808d 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -40,6 +40,8 @@
using android::hardware::wifi::supplicant::V1_4::ConnectionCapabilities;
using android::hardware::wifi::supplicant::V1_4::LegacyMode;
using android::hardware::wifi::supplicant::V1_4::implementation::HidlManager;
+using android::hardware::wifi::supplicant::V1_4::DppResponderBootstrapInfo;
+using android::hardware::wifi::supplicant::V1_4::DppCurve;
constexpr uint32_t kMaxAnqpElems = 100;
constexpr char kGetMacAddress[] = "MACADDR";
@@ -218,6 +220,65 @@
return mask;
}
+const std::string getDppListenChannel(struct wpa_supplicant *wpa_s, int32_t *listen_channel)
+{
+ struct hostapd_hw_modes *mode;
+ int chan44 = 0, chan149 = 0;
+ *listen_channel = 0;
+
+ /* Check if device support 2.4GHz band*/
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ HOSTAPD_MODE_IEEE80211G, 0);
+ if (mode) {
+ *listen_channel = 6;
+ return "81/6";
+ }
+ /* Check if device support 5GHz band */
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ HOSTAPD_MODE_IEEE80211A, 0);
+ if (mode) {
+ for (int i = 0; i < mode->num_channels; i++) {
+ struct hostapd_channel_data *chan = &mode->channels[i];
+
+ if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_RADAR))
+ continue;
+ if (chan->freq == 5220)
+ chan44 = 1;
+ if (chan->freq == 5745)
+ chan149 = 1;
+ }
+ if (chan149) {
+ *listen_channel = 149;
+ return "124/149";
+ } else if (chan44) {
+ *listen_channel = 44;
+ return "115/44";
+ }
+ }
+
+ return "";
+}
+
+const std::string convertCurveTypeToName(DppCurve curve)
+{
+ switch (curve) {
+ case DppCurve::PRIME256V1:
+ return "prime256v1";
+ case DppCurve::SECP384R1:
+ return "secp384r1";
+ case DppCurve::SECP521R1:
+ return "secp521r1";
+ case DppCurve::BRAINPOOLP256R1:
+ return "brainpoolP256r1";
+ case DppCurve::BRAINPOOLP384R1:
+ return "brainpoolP384r1";
+ case DppCurve::BRAINPOOLP512R1:
+ return "brainpoolP512r1";
+ }
+ WPA_ASSERT(false);
+}
+
} // namespace
namespace android {
@@ -684,6 +745,31 @@
&StaIface::stopDppInitiatorInternal, _hidl_cb);
}
+Return<void> StaIface::generateDppBootstrapInfoForResponder(
+ const hidl_array<uint8_t, 6> &mac_address, const hidl_string& device_info,
+ DppCurve curve, generateDppBootstrapInfoForResponder_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::generateDppBootstrapInfoForResponderInternal, _hidl_cb, mac_address,
+ device_info, curve);
+}
+
+Return<void> StaIface::startDppEnrolleeResponder(
+ uint32_t listen_channel, startDppEnrolleeResponder_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::startDppEnrolleeResponderInternal, _hidl_cb, listen_channel);
+}
+
+Return<void> StaIface::stopDppResponder(uint32_t own_bootstrap_id, stopDppResponder_cb _hidl_cb)
+{
+ return validateAndCall(
+ this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::stopDppResponderInternal, _hidl_cb, own_bootstrap_id);
+}
+
Return<void> StaIface::getWpaDriverCapabilities(
getWpaDriverCapabilities_cb _hidl_cb)
{
@@ -1478,6 +1564,111 @@
#endif
}
+std::pair<V1_4::SupplicantStatus, DppResponderBootstrapInfo>
+StaIface::generateDppBootstrapInfoForResponderInternal(const std::array<uint8_t, 6> &mac_address,
+ const std::string& device_info, DppCurve curve)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string cmd = "type=qrcode";
+ int32_t id;
+ int32_t listen_channel = 0;
+ struct DppResponderBootstrapInfo bootstrap_info;
+ const char *uri;
+ std::string listen_channel_str;
+ std::string mac_addr_str;
+ char buf[3] = {0};
+
+ cmd += (device_info.empty()) ? "" : " info=" + device_info;
+
+ listen_channel_str = getDppListenChannel(wpa_s, &listen_channel);
+ if (listen_channel == 0) {
+ wpa_printf(MSG_ERROR, "StaIface: Failed to derive DPP listen channel");
+ return {{V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""}, bootstrap_info};
+ }
+ cmd += " chan=" + listen_channel_str;
+
+ cmd += " mac=";
+ for (int i = 0;i < 6;i++) {
+ snprintf(buf, sizeof(buf), "%02x", mac_address[i]);
+ mac_addr_str.append(buf);
+ }
+ cmd += mac_addr_str;
+
+ cmd += " curve=" + convertCurveTypeToName(curve);
+
+ id = dpp_bootstrap_gen(wpa_s->dpp, cmd.c_str());
+ wpa_printf(MSG_DEBUG,
+ "DPP generate bootstrap QR code command: %s id: %d", cmd.c_str(), id);
+ if (id > 0) {
+ uri = dpp_bootstrap_get_uri(wpa_s->dpp, id);
+ if (uri) {
+ wpa_printf(MSG_DEBUG, "DPP Bootstrap info: id: %d "
+ "listen_channel: %d uri: %s", id, listen_channel, uri);
+ bootstrap_info.bootstrapId = id;
+ bootstrap_info.listenChannel = listen_channel;
+ bootstrap_info.uri = uri;
+ return {{V1_4::SupplicantStatusCode::SUCCESS, ""}, bootstrap_info};
+ }
+ }
+ return {{V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""}, bootstrap_info};
+#else
+ return {{V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""}, bootstrap_info};
+#endif
+}
+
+V1_4::SupplicantStatus StaIface::startDppEnrolleeResponderInternal(uint32_t listen_channel)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string cmd = "";
+ uint32_t freq = (listen_channel <= 14 ? 2407 : 5000) + listen_channel * 5;
+
+ /* Report received configuration to HIDL and create an internal profile */
+ wpa_s->conf->dpp_config_processing = 1;
+
+ cmd += std::to_string(freq);
+ cmd += " role=enrollee netrole=sta";
+
+ wpa_printf(MSG_DEBUG,
+ "DPP Enrollee Responder command: %s", cmd.c_str());
+
+ if (wpas_dpp_listen(wpa_s, cmd.c_str()) == 0) {
+ return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+ }
+ return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+#else
+ return {V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""};
+#endif
+}
+
+V1_4::SupplicantStatus StaIface::stopDppResponderInternal(uint32_t own_bootstrap_id)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string bootstrap_id_str;
+
+ if (own_bootstrap_id == 0) {
+ bootstrap_id_str = "*";
+ }
+ else {
+ bootstrap_id_str = std::to_string(own_bootstrap_id);
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP Stop DPP Responder id: %d ", own_bootstrap_id);
+ wpas_dpp_stop(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+
+ if (dpp_bootstrap_remove(wpa_s->dpp, bootstrap_id_str.c_str()) < 0) {
+ wpa_printf(MSG_ERROR, "StaIface: dpp_bootstrap_remove failed");
+ }
+
+ return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+#else
+ return {V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""};
+#endif
+}
+
std::pair<SupplicantStatus, android::hardware::wifi::supplicant::V1_3::ConnectionCapabilities>
StaIface::getConnectionCapabilitiesInternal()
{
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
index bb5344b..d49e469 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ b/wpa_supplicant/hidl/1.4/sta_iface.h
@@ -205,6 +205,13 @@
getKeyMgmtCapabilities_1_3_cb _hidl_cb) override;
Return<void> getWpaDriverCapabilities_1_4(
getWpaDriverCapabilities_1_4_cb _hidl_cb) override;
+ Return<void> generateDppBootstrapInfoForResponder(const hidl_array<uint8_t, 6> &mac_address,
+ const hidl_string& device_info, DppCurve curve,
+ generateDppBootstrapInfoForResponder_cb _hidl_cb) override;
+ Return<void> startDppEnrolleeResponder(uint32_t listen_channel,
+ startDppEnrolleeResponder_cb _hidl_cb) override;
+ Return<void> stopDppResponder(uint32_t own_bootstrap_id,
+ stopDppResponder_cb _hidl_cb) override;
private:
// Corresponding worker functions for the HIDL methods.
@@ -303,6 +310,12 @@
SupplicantStatus setMboCellularDataStatusInternal(bool available);
std::pair<SupplicantStatus, uint32_t> getKeyMgmtCapabilitiesInternal_1_3();
std::pair<V1_4::SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal_1_4();
+ std::pair<V1_4::SupplicantStatus, V1_4::DppResponderBootstrapInfo>
+ generateDppBootstrapInfoForResponderInternal(
+ const std::array<uint8_t, 6>& mac_address, const std::string& device_info,
+ DppCurve curve);
+ V1_4::SupplicantStatus startDppEnrolleeResponderInternal(uint32_t listen_channel);
+ V1_4::SupplicantStatus stopDppResponderInternal(uint32_t own_bootstrap_id);
struct wpa_supplicant* retrieveIfacePtr();