Merge "DO NOT MERGE - Merge Android 13"
diff --git a/CONTRIBUTIONS b/CONTRIBUTIONS
index c81ad64..d342264 100644
--- a/CONTRIBUTIONS
+++ b/CONTRIBUTIONS
@@ -37,7 +37,7 @@
 http://lists.infradead.org/mailman/listinfo/hostap
 
 The message should contain an inlined patch against the current
-development branch (i.e., the master branch of
+development branch (i.e., the main branch of
 git://w1.fi/hostap.git). Please make sure the software you use for
 sending the patch does not corrupt whitespace. If that cannot be fixed
 for some reason, it is better to include an attached version of the
@@ -140,7 +140,7 @@
 
 Modified BSD license (no advertisement clause):
 
-Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
 All Rights Reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/COPYING b/COPYING
index 5d0115c..7ca3030 100644
--- a/COPYING
+++ b/COPYING
@@ -1,7 +1,7 @@
 wpa_supplicant and hostapd
 --------------------------
 
-Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
 All Rights Reserved.
 
 
diff --git a/README b/README
index a9f8069..1470c4f 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
 wpa_supplicant and hostapd
 --------------------------
 
-Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
 All Rights Reserved.
 
 These programs are licensed under the BSD license (the one with
diff --git a/hostapd/Android.bp b/hostapd/Android.bp
index e5d54f3..d7cc39b 100644
--- a/hostapd/Android.bp
+++ b/hostapd/Android.bp
@@ -45,13 +45,10 @@
     defaults: ["hostapd_cflags_defaults"],
     srcs: [":hostapd_srcs"],
     shared_libs: [
-        "android.hardware.wifi.hostapd@1.0",
-        "android.hardware.wifi.hostapd@1.1",
-        "android.hardware.wifi.hostapd@1.2",
-        "android.hardware.wifi.hostapd@1.3",
+        "android.hardware.wifi.hostapd-V1-ndk",
         "libbase",
-        "libhidlbase",
         "libutils",
+        "libbinder_ndk",
         "libc",
         "libcutils",
         "liblog",
@@ -63,11 +60,11 @@
     relative_install_path: "hw",
     soc_specific: true,
     static_libs: [
-        "libhostapd_hidl_bp",
+        "libhostapd_aidl_bp",
     ],
     header_libs: [
         "hostapd_headers",
-        "libhostapd_hidl_headers",
+        "libhostapd_aidl_headers",
     ],
 }
 
@@ -165,7 +162,7 @@
         "-DCONFIG_PROXYARP",
         "-DCONFIG_ACS",
         "-DCONFIG_ANDROID_LOG",
-        "-DCONFIG_CTRL_IFACE_HIDL",
+        "-DCONFIG_CTRL_IFACE_AIDL",
         "-Wall",
         "-Werror",
         "-Wno-unused-parameter",
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 9cce32b..4c37b77 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -42,6 +42,14 @@
 L_CFLAGS += -DANDROID_LIB_STUB
 endif
 
+ifeq ($(BOARD_HOSTAPD_CONFIG_80211W_MFP_OPTIONAL),true)
+L_CFLAGS += -DENABLE_HOSTAPD_CONFIG_80211W_MFP_OPTIONAL
+endif
+
+ifneq ($(BOARD_HOSTAPD_PRIVATE_LIB_EVENT),)
+L_CFLAGS += -DANDROID_LIB_EVENT
+endif
+
 # Use Android specific directory for control interface sockets
 L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/hostapd/sockets\"
 L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/hostapd/ctrl\"
@@ -579,6 +587,9 @@
 ifdef CONFIG_DPP2
 L_CFLAGS += -DCONFIG_DPP2
 endif
+ifdef CONFIG_DPP3
+L_CFLAGS += -DCONFIG_DPP3
+endif
 endif
 
 ifdef CONFIG_PASN
@@ -1125,9 +1136,9 @@
 endif
 
 ifeq ($(filter gce_x86 gce_x86_64 calypso, $(TARGET_DEVICE)),)
-ifdef CONFIG_CTRL_IFACE_HIDL
-HOSTAPD_USE_HIDL=y
-L_CFLAGS += -DCONFIG_CTRL_IFACE_HIDL
+ifdef CONFIG_CTRL_IFACE_AIDL
+HOSTAPD_USE_AIDL=y
+L_CFLAGS += -DCONFIG_CTRL_IFACE_AIDL
 L_CPPFLAGS = -Wall -Werror
 endif
 endif
@@ -1170,13 +1181,11 @@
 LOCAL_STATIC_LIBRARIES += libnl_2
 endif
 endif
-ifeq ($(HOSTAPD_USE_HIDL), y)
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.0
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.1
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.2
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.3
-LOCAL_SHARED_LIBRARIES += libbase libhidlbase libutils
-LOCAL_STATIC_LIBRARIES += libhostapd_hidl
+ifeq ($(HOSTAPD_USE_AIDL), y)
+LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd-V1-ndk
+LOCAL_SHARED_LIBRARIES += libbase libutils
+LOCAL_SHARED_LIBRARIES += libbinder_ndk
+LOCAL_STATIC_LIBRARIES += libhostapd_aidl
 endif
 LOCAL_CFLAGS := $(L_CFLAGS)
 LOCAL_SRC_FILES := $(OBJS)
@@ -1186,7 +1195,7 @@
 
 ########################
 include $(CLEAR_VARS)
-LOCAL_MODULE := hostapd_nohidl
+LOCAL_MODULE := hostapd_noaidl
 LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-BSD-3-Clause SPDX-license-identifier-ISC legacy_unencumbered
 LOCAL_LICENSE_CONDITIONS := notice unencumbered
 LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../LICENSE
@@ -1206,16 +1215,16 @@
 LOCAL_STATIC_LIBRARIES += libnl_2
 endif
 endif
-LOCAL_CFLAGS := $(patsubst -DCONFIG_CTRL_IFACE_HIDL,,$(L_CFLAGS))
+LOCAL_CFLAGS := $(patsubst -DCONFIG_CTRL_IFACE_AIDL,,$(L_CFLAGS))
 LOCAL_SRC_FILES := $(OBJS)
 LOCAL_C_INCLUDES := $(INCLUDES)
 include $(BUILD_EXECUTABLE)
 
-ifeq ($(HOSTAPD_USE_HIDL), y)
-### Hidl service library ###
+ifeq ($(HOSTAPD_USE_AIDL), y)
+### Aidl service library ###
 ########################
 include $(CLEAR_VARS)
-LOCAL_MODULE := libhostapd_hidl
+LOCAL_MODULE := libhostapd_aidl
 LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-BSD-3-Clause SPDX-license-identifier-ISC legacy_unencumbered
 LOCAL_LICENSE_CONDITIONS := notice unencumbered
 LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../COPYING $(LOCAL_PATH)/../NOTICE
@@ -1223,21 +1232,17 @@
 LOCAL_CPPFLAGS := $(L_CPPFLAGS)
 LOCAL_CFLAGS := $(L_CFLAGS)
 LOCAL_C_INCLUDES := $(INCLUDES)
-HIDL_INTERFACE_VERSION = 1.3
 LOCAL_SRC_FILES := \
-    hidl/$(HIDL_INTERFACE_VERSION)/hidl.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/hostapd.cpp
+    aidl/aidl.cpp \
+    aidl/hostapd.cpp
 LOCAL_SHARED_LIBRARIES := \
-    android.hardware.wifi.hostapd@1.0 \
-    android.hardware.wifi.hostapd@1.1 \
-    android.hardware.wifi.hostapd@1.2 \
-    android.hardware.wifi.hostapd@1.3 \
+    android.hardware.wifi.hostapd-V1-ndk \
+    libbinder_ndk \
     libbase \
-    libhidlbase \
     libutils \
     liblog
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/hidl/$(HIDL_INTERFACE_VERSION)
+    $(LOCAL_PATH)/aidl
 include $(BUILD_STATIC_LIBRARY)
-endif # HOSTAPD_USE_HIDL == y
+endif # HOSTAPD_USE_AIDL == y
 endif # ifeq ($(WPA_BUILD_HOSTAPD),true)
diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog
index 34a8a08..279298e 100644
--- a/hostapd/ChangeLog
+++ b/hostapd/ChangeLog
@@ -1,5 +1,48 @@
 ChangeLog for hostapd
 
+2022-01-16 - v2.10
+	* SAE changes
+	  - improved protection against side channel attacks
+	    [https://w1.fi/security/2022-1/]
+	  - added option send SAE Confirm immediately (sae_config_immediate=1)
+	    after SAE Commit
+	  - added support for the hash-to-element mechanism (sae_pwe=1 or
+	    sae_pwe=2)
+	  - fixed PMKSA caching with OKC
+	  - added support for SAE-PK
+	* EAP-pwd changes
+	  - improved protection against side channel attacks
+	    [https://w1.fi/security/2022-1/]
+	* fixed WPS UPnP SUBSCRIBE handling of invalid operations
+	  [https://w1.fi/security/2020-1/]
+	* fixed PMF disconnection protection bypass
+	  [https://w1.fi/security/2019-7/]
+	* added support for using OpenSSL 3.0
+	* fixed various issues in experimental support for EAP-TEAP server
+	* added configuration (max_auth_rounds, max_auth_rounds_short) to
+	  increase the maximum number of EAP message exchanges (mainly to
+	  support cases with very large certificates) for the EAP server
+	* added support for DPP release 2 (Wi-Fi Device Provisioning Protocol)
+	* extended HE (IEEE 802.11ax) support, including 6 GHz support
+	* removed obsolete IAPP functionality
+	* fixed EAP-FAST server with TLS GCM/CCM ciphers
+	* dropped support for libnl 1.1
+	* added support for nl80211 control port for EAPOL frame TX/RX
+	* fixed OWE key derivation with groups 20 and 21; this breaks backwards
+	  compatibility for these groups while the default group 19 remains
+	  backwards compatible; owe_ptk_workaround=1 can be used to enabled a
+	  a workaround for the group 20/21 backwards compatibility
+	* added support for Beacon protection
+	* added support for Extended Key ID for pairwise keys
+	* removed WEP support from the default build (CONFIG_WEP=y can be used
+	  to enable it, if really needed)
+	* added a build option to remove TKIP support (CONFIG_NO_TKIP=y)
+	* added support for Transition Disable mechanism to allow the AP to
+	  automatically disable transition mode to improve security
+	* added support for PASN
+	* added EAP-TLS server support for TLS 1.3 (disabled by default for now)
+	* a large number of other fixes, cleanup, and extensions
+
 2019-08-07 - v2.9
 	* SAE changes
 	  - disable use of groups using Brainpool curves
diff --git a/hostapd/Makefile b/hostapd/Makefile
index ce7d215..98a0102 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -597,6 +597,9 @@
 ifdef CONFIG_DPP2
 CFLAGS += -DCONFIG_DPP2
 endif
+ifdef CONFIG_DPP3
+CFLAGS += -DCONFIG_DPP3
+endif
 endif
 
 ifdef CONFIG_PASN
diff --git a/hostapd/README b/hostapd/README
index 1f30d7e..739c964 100644
--- a/hostapd/README
+++ b/hostapd/README
@@ -2,7 +2,7 @@
 	  Authenticator and RADIUS authentication server
 ================================================================
 
-Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
 All Rights Reserved.
 
 This program is licensed under the BSD license (the one with
diff --git a/hostapd/hidl/.clang-format b/hostapd/aidl/.clang-format
similarity index 100%
rename from hostapd/hidl/.clang-format
rename to hostapd/aidl/.clang-format
diff --git a/hostapd/hidl/1.3/Android.bp b/hostapd/aidl/Android.bp
similarity index 78%
rename from hostapd/hidl/1.3/Android.bp
rename to hostapd/aidl/Android.bp
index 4568ef9..3cbccee 100644
--- a/hostapd/hidl/1.3/Android.bp
+++ b/hostapd/aidl/Android.bp
@@ -20,23 +20,20 @@
 }
 
 cc_library_headers {
-    name: "libhostapd_hidl_headers",
+    name: "libhostapd_aidl_headers",
     export_include_dirs: ["."],
     soc_specific: true,
 }
 
 cc_library_static {
-    name: "libhostapd_hidl_bp",
+    name: "libhostapd_aidl_bp",
     srcs: ["*.cpp"],
     defaults: ["hostapd_cflags_defaults"],
     soc_specific: true,
     shared_libs: [
-        "android.hardware.wifi.hostapd@1.0",
-        "android.hardware.wifi.hostapd@1.1",
-        "android.hardware.wifi.hostapd@1.2",
-        "android.hardware.wifi.hostapd@1.3",
+        "android.hardware.wifi.hostapd-V1-ndk",
+        "libbinder_ndk",
         "libbase",
-        "libhidlbase",
         "libutils",
         "liblog",
     ],
@@ -46,6 +43,6 @@
     ],
     header_libs: [
         "hostapd_headers",
-        "libhostapd_hidl_headers",
+        "libhostapd_aidl_headers",
     ],
 }
diff --git a/hostapd/aidl/aidl.cpp b/hostapd/aidl/aidl.cpp
new file mode 100644
index 0000000..e02708c
--- /dev/null
+++ b/hostapd/aidl/aidl.cpp
@@ -0,0 +1,73 @@
+/*
+ * aidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hostapd.h"
+#include <android/binder_process.h>
+#include <android/binder_manager.h>
+
+extern "C"
+{
+#include "aidl.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+}
+
+using aidl::android::hardware::wifi::hostapd::Hostapd;
+
+// This file is a bridge between the hostapd code written in 'C' and the aidl
+// interface in C++. So, using "C" style static globals here!
+static int aidl_fd = -1;
+static std::shared_ptr<Hostapd> service;
+
+void hostapd_aidl_sock_handler(
+    int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
+{
+	ABinderProcess_handlePolledCommands();
+}
+
+int hostapd_aidl_init(struct hapd_interfaces *interfaces)
+{
+	wpa_printf(MSG_DEBUG, "Initializing aidl control");
+	std::string instance;   // declared here to allow use of goto
+
+	ABinderProcess_setupPolling(&aidl_fd);
+	if (aidl_fd < 0)
+		goto err;
+
+	wpa_printf(MSG_INFO, "Processing aidl events on FD %d", aidl_fd);
+	// Look for read events from the aidl socket in the eloop.
+	if (eloop_register_read_sock(
+		aidl_fd, hostapd_aidl_sock_handler, interfaces, NULL) < 0)
+		goto err;
+
+	wpa_printf(MSG_DEBUG, "Make service");
+	service = ndk::SharedRefBase::make<Hostapd>(interfaces);
+	if (!service)
+		goto err;
+	wpa_printf(MSG_DEBUG, "Add service");
+	instance = std::string() + Hostapd::descriptor + "/default";
+	if (AServiceManager_addService(service->asBinder().get(), instance.c_str()) != STATUS_OK)
+		goto err;
+	return 0;
+err:
+	hostapd_aidl_deinit(interfaces);
+	return -1;
+}
+
+void hostapd_aidl_deinit(struct hapd_interfaces *interfaces)
+{
+	wpa_printf(MSG_INFO, "Deiniting aidl control");
+	// Before aidl deinit, make sure call terminate to clear callback_
+	if (service) {
+		service->terminate();
+	}
+	eloop_unregister_read_sock(aidl_fd);
+	aidl_fd = -1;
+}
diff --git a/hostapd/aidl/aidl.h b/hostapd/aidl/aidl.h
new file mode 100644
index 0000000..f82013d
--- /dev/null
+++ b/hostapd/aidl/aidl.h
@@ -0,0 +1,27 @@
+/*
+ * aidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif  // _cplusplus
+#include "ap/hostapd.h"
+
+/**
+ * This is the aidl RPC interface entry point to the hostapd core.
+ * This initializes the aidl driver & IHostapd instance.
+ */
+int hostapd_aidl_init(struct hapd_interfaces *interfaces);
+void hostapd_aidl_deinit(struct hapd_interfaces *interfaces);
+
+#ifdef __cplusplus
+}
+#endif  // _cplusplus
diff --git a/hostapd/aidl/hostapd.cpp b/hostapd/aidl/hostapd.cpp
new file mode 100644
index 0000000..11d1290
--- /dev/null
+++ b/hostapd/aidl/hostapd.cpp
@@ -0,0 +1,1128 @@
+/*
+ * aidl interface for wpa_hostapd daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <linux/if_bridge.h>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+
+#include "hostapd.h"
+#include <aidl/android/hardware/wifi/hostapd/ApInfo.h>
+#include <aidl/android/hardware/wifi/hostapd/BandMask.h>
+#include <aidl/android/hardware/wifi/hostapd/ChannelParams.h>
+#include <aidl/android/hardware/wifi/hostapd/ClientInfo.h>
+#include <aidl/android/hardware/wifi/hostapd/EncryptionType.h>
+#include <aidl/android/hardware/wifi/hostapd/HostapdStatusCode.h>
+#include <aidl/android/hardware/wifi/hostapd/IfaceParams.h>
+#include <aidl/android/hardware/wifi/hostapd/NetworkParams.h>
+#include <aidl/android/hardware/wifi/hostapd/ParamSizeLimits.h>
+
+extern "C"
+{
+#include "common/wpa_ctrl.h"
+#include "drivers/linux_ioctl.h"
+}
+
+// The AIDL implementation for hostapd creates a hostapd.conf dynamically for
+// each interface. This file can then be used to hook onto the normal config
+// file parsing logic in hostapd code.  Helps us to avoid duplication of code
+// in the AIDL interface.
+// TOOD(b/71872409): Add unit tests for this.
+namespace {
+constexpr char kConfFileNameFmt[] = "/data/vendor/wifi/hostapd/hostapd_%s.conf";
+
+using android::base::RemoveFileIfExists;
+using android::base::StringPrintf;
+using android::base::WriteStringToFile;
+using aidl::android::hardware::wifi::hostapd::BandMask;
+using aidl::android::hardware::wifi::hostapd::ChannelBandwidth;
+using aidl::android::hardware::wifi::hostapd::ChannelParams;
+using aidl::android::hardware::wifi::hostapd::EncryptionType;
+using aidl::android::hardware::wifi::hostapd::Generation;
+using aidl::android::hardware::wifi::hostapd::HostapdStatusCode;
+using aidl::android::hardware::wifi::hostapd::IfaceParams;
+using aidl::android::hardware::wifi::hostapd::NetworkParams;
+using aidl::android::hardware::wifi::hostapd::ParamSizeLimits;
+
+int band2Ghz = (int)BandMask::BAND_2_GHZ;
+int band5Ghz = (int)BandMask::BAND_5_GHZ;
+int band6Ghz = (int)BandMask::BAND_6_GHZ;
+int band60Ghz = (int)BandMask::BAND_60_GHZ;
+
+#define MAX_PORTS 1024
+bool GetInterfacesInBridge(std::string br_name,
+                           std::vector<std::string>* interfaces) {
+	android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+	if (sock.get() < 0) {
+		wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
+			strerror(errno), __FUNCTION__);
+		return false;
+	}
+
+	struct ifreq request;
+	int i, ifindices[MAX_PORTS];
+	char if_name[IFNAMSIZ];
+	unsigned long args[3];
+
+	memset(ifindices, 0, MAX_PORTS * sizeof(int));
+
+	args[0] = BRCTL_GET_PORT_LIST;
+	args[1] = (unsigned long) ifindices;
+	args[2] = MAX_PORTS;
+
+	strlcpy(request.ifr_name, br_name.c_str(), IFNAMSIZ);
+	request.ifr_data = (char *)args;
+
+	if (ioctl(sock.get(), SIOCDEVPRIVATE, &request) < 0) {
+		wpa_printf(MSG_ERROR, "Failed to ioctl SIOCDEVPRIVATE in %s",
+			__FUNCTION__);
+		return false;
+	}
+
+	for (i = 0; i < MAX_PORTS; i ++) {
+		memset(if_name, 0, IFNAMSIZ);
+		if (ifindices[i] == 0 || !if_indextoname(ifindices[i], if_name)) {
+			continue;
+		}
+		interfaces->push_back(if_name);
+	}
+	return true;
+}
+
+std::string WriteHostapdConfig(
+    const std::string& interface_name, const std::string& config)
+{
+	const std::string file_path =
+	    StringPrintf(kConfFileNameFmt, interface_name.c_str());
+	if (WriteStringToFile(
+		config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+		getuid(), getgid())) {
+		return file_path;
+	}
+	// Diagnose failure
+	int error = errno;
+	wpa_printf(
+		MSG_ERROR, "Cannot write hostapd config to %s, error: %s",
+		file_path.c_str(), strerror(error));
+	struct stat st;
+	int result = stat(file_path.c_str(), &st);
+	if (result == 0) {
+		wpa_printf(
+			MSG_ERROR, "hostapd config file uid: %d, gid: %d, mode: %d",
+			st.st_uid, st.st_gid, st.st_mode);
+	} else {
+		wpa_printf(
+			MSG_ERROR,
+			"Error calling stat() on hostapd config file: %s",
+			strerror(errno));
+	}
+	return "";
+}
+
+/*
+ * Get the op_class for a channel/band
+ * The logic here is based on Table E-4 in the 802.11 Specification
+ */
+int getOpClassForChannel(int channel, int band, bool support11n, bool support11ac) {
+	// 2GHz Band
+	if ((band & band2Ghz) != 0) {
+		if (channel == 14) {
+			return 82;
+		}
+		if (channel >= 1 && channel <= 13) {
+			if (!support11n) {
+				//20MHz channel
+				return 81;
+			}
+			if (channel <= 9) {
+				// HT40 with secondary channel above primary
+				return 83;
+			}
+			// HT40 with secondary channel below primary
+			return 84;
+		}
+		// Error
+		return 0;
+	}
+
+	// 5GHz Band
+	if ((band & band5Ghz) != 0) {
+		if (support11ac) {
+			switch (channel) {
+				case 42:
+				case 58:
+				case 106:
+				case 122:
+				case 138:
+				case 155:
+					// 80MHz channel
+					return 128;
+				case 50:
+				case 114:
+					// 160MHz channel
+					return 129;
+			}
+		}
+
+		if (!support11n) {
+			if (channel >= 36 && channel <= 48) {
+				return 115;
+			}
+			if (channel >= 52 && channel <= 64) {
+				return 118;
+			}
+			if (channel >= 100 && channel <= 144) {
+				return 121;
+			}
+			if (channel >= 149 && channel <= 161) {
+				return 124;
+			}
+			if (channel >= 165 && channel <= 169) {
+				return 125;
+			}
+		} else {
+			switch (channel) {
+				case 36:
+				case 44:
+					// HT40 with secondary channel above primary
+					return 116;
+				case 40:
+				case 48:
+					// HT40 with secondary channel below primary
+					return 117;
+				case 52:
+				case 60:
+					// HT40 with secondary channel above primary
+					return  119;
+				case 56:
+				case 64:
+					// HT40 with secondary channel below primary
+					return 120;
+				case 100:
+				case 108:
+				case 116:
+				case 124:
+				case 132:
+				case 140:
+					// HT40 with secondary channel above primary
+					return 122;
+				case 104:
+				case 112:
+				case 120:
+				case 128:
+				case 136:
+				case 144:
+					// HT40 with secondary channel below primary
+					return 123;
+				case 149:
+				case 157:
+					// HT40 with secondary channel above primary
+					return 126;
+				case 153:
+				case 161:
+					// HT40 with secondary channel below primary
+					return 127;
+			}
+		}
+		// Error
+		return 0;
+	}
+
+	// 6GHz Band
+	if ((band & band6Ghz) != 0) {
+		// Channels 1, 5. 9, 13, ...
+		if ((channel & 0x03) == 0x01) {
+			// 20MHz channel
+			return 131;
+		}
+		// Channels 3, 11, 19, 27, ...
+		if ((channel & 0x07) == 0x03) {
+			// 40MHz channel
+			return 132;
+		}
+		// Channels 7, 23, 39, 55, ...
+		if ((channel & 0x0F) == 0x07) {
+			// 80MHz channel
+			return 133;
+		}
+		// Channels 15, 47, 69, ...
+		if ((channel & 0x1F) == 0x0F) {
+			// 160MHz channel
+			return 134;
+		}
+		if (channel == 2) {
+			// 20MHz channel
+			return 136;
+		}
+		// Error
+		return 0;
+	}
+
+	if ((band & band60Ghz) != 0) {
+		if (1 <= channel && channel <= 8) {
+			return 180;
+		} else if (9 <= channel && channel <= 15) {
+			return 181;
+		} else if (17 <= channel && channel <= 22) {
+			return 182;
+		} else if (25 <= channel && channel <= 29) {
+			return 183;
+		}
+		// Error
+		return 0;
+	}
+
+	return 0;
+}
+
+bool validatePassphrase(int passphrase_len, int min_len, int max_len)
+{
+	if (min_len != -1 && passphrase_len < min_len) return false;
+	if (max_len != -1 && passphrase_len > max_len) return false;
+	return true;
+}
+
+std::string CreateHostapdConfig(
+	const IfaceParams& iface_params,
+	const ChannelParams& channelParams,
+	const NetworkParams& nw_params,
+	const std::string br_name,
+	const std::string owe_transition_ifname)
+{
+	if (nw_params.ssid.size() >
+		static_cast<uint32_t>(
+		ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
+		wpa_printf(
+			MSG_ERROR, "Invalid SSID size: %zu", nw_params.ssid.size());
+		return "";
+	}
+
+	// SSID string
+	std::stringstream ss;
+	ss << std::hex;
+	ss << std::setfill('0');
+	for (uint8_t b : nw_params.ssid) {
+		ss << std::setw(2) << static_cast<unsigned int>(b);
+	}
+	const std::string ssid_as_string = ss.str();
+
+	// Encryption config string
+	uint32_t band = 0;
+	band |= static_cast<uint32_t>(channelParams.bandMask);
+	bool is_2Ghz_band_only = band == static_cast<uint32_t>(band2Ghz);
+	bool is_6Ghz_band_only = band == static_cast<uint32_t>(band6Ghz);
+	bool is_60Ghz_band_only = band == static_cast<uint32_t>(band60Ghz);
+	std::string encryption_config_as_string;
+	switch (nw_params.encryptionType) {
+	case EncryptionType::NONE:
+		// no security params
+		break;
+	case EncryptionType::WPA:
+		if (!validatePassphrase(
+			nw_params.passphrase.size(),
+			static_cast<uint32_t>(ParamSizeLimits::
+				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
+			static_cast<uint32_t>(ParamSizeLimits::
+				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
+			return "";
+		}
+		encryption_config_as_string = StringPrintf(
+			"wpa=3\n"
+			"wpa_pairwise=%s\n"
+			"wpa_passphrase=%s",
+			is_60Ghz_band_only ? "GCMP" : "TKIP CCMP",
+			nw_params.passphrase.c_str());
+		break;
+	case EncryptionType::WPA2:
+		if (!validatePassphrase(
+			nw_params.passphrase.size(),
+			static_cast<uint32_t>(ParamSizeLimits::
+				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
+			static_cast<uint32_t>(ParamSizeLimits::
+				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
+			return "";
+		}
+		encryption_config_as_string = StringPrintf(
+			"wpa=2\n"
+			"rsn_pairwise=%s\n"
+#ifdef ENABLE_HOSTAPD_CONFIG_80211W_MFP_OPTIONAL
+			"ieee80211w=1\n"
+#endif
+			"wpa_passphrase=%s",
+			is_60Ghz_band_only ? "GCMP" : "CCMP",
+			nw_params.passphrase.c_str());
+		break;
+	case EncryptionType::WPA3_SAE_TRANSITION:
+		if (!validatePassphrase(
+			nw_params.passphrase.size(),
+			static_cast<uint32_t>(ParamSizeLimits::
+				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
+			static_cast<uint32_t>(ParamSizeLimits::
+				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
+			return "";
+		}
+		encryption_config_as_string = StringPrintf(
+			"wpa=2\n"
+			"rsn_pairwise=%s\n"
+			"wpa_key_mgmt=WPA-PSK SAE\n"
+			"ieee80211w=1\n"
+			"sae_require_mfp=1\n"
+			"wpa_passphrase=%s\n"
+			"sae_password=%s",
+			is_60Ghz_band_only ? "GCMP" : "CCMP",
+			nw_params.passphrase.c_str(),
+			nw_params.passphrase.c_str());
+		break;
+	case EncryptionType::WPA3_SAE:
+		if (!validatePassphrase(nw_params.passphrase.size(), 1, -1)) {
+			return "";
+		}
+		encryption_config_as_string = StringPrintf(
+			"wpa=2\n"
+			"rsn_pairwise=%s\n"
+			"wpa_key_mgmt=SAE\n"
+			"ieee80211w=2\n"
+			"sae_require_mfp=2\n"
+			"sae_pwe=%d\n"
+			"sae_password=%s",
+			is_60Ghz_band_only ? "GCMP" : "CCMP",
+			is_6Ghz_band_only ? 1 : 2,
+			nw_params.passphrase.c_str());
+		break;
+	case EncryptionType::WPA3_OWE_TRANSITION:
+		encryption_config_as_string = StringPrintf(
+			"wpa=2\n"
+			"rsn_pairwise=%s\n"
+			"wpa_key_mgmt=OWE\n"
+			"ieee80211w=2",
+			is_60Ghz_band_only ? "GCMP" : "CCMP");
+		break;
+	case EncryptionType::WPA3_OWE:
+		encryption_config_as_string = StringPrintf(
+			"wpa=2\n"
+			"rsn_pairwise=%s\n"
+			"wpa_key_mgmt=OWE\n"
+			"ieee80211w=2",
+			is_60Ghz_band_only ? "GCMP" : "CCMP");
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "Unknown encryption type");
+		return "";
+	}
+
+	std::string channel_config_as_string;
+	bool isFirst = true;
+	if (channelParams.enableAcs) {
+		std::string freqList_as_string;
+		for (const auto &range :
+			channelParams.acsChannelFreqRangesMhz) {
+			if (!isFirst) {
+				freqList_as_string += ",";
+			}
+			isFirst = false;
+
+			if (range.startMhz != range.endMhz) {
+				freqList_as_string +=
+					StringPrintf("%d-%d", range.startMhz, range.endMhz);
+			} else {
+				freqList_as_string += StringPrintf("%d", range.startMhz);
+			}
+		}
+		channel_config_as_string = StringPrintf(
+			"channel=0\n"
+			"acs_exclude_dfs=%d\n"
+			"freqlist=%s",
+			channelParams.acsShouldExcludeDfs,
+			freqList_as_string.c_str());
+	} else {
+		int op_class = getOpClassForChannel(
+			channelParams.channel,
+			band,
+			iface_params.hwModeParams.enable80211N,
+			iface_params.hwModeParams.enable80211AC);
+		channel_config_as_string = StringPrintf(
+			"channel=%d\n"
+			"op_class=%d",
+			channelParams.channel, op_class);
+	}
+
+	std::string hw_mode_as_string;
+	std::string enable_edmg_as_string;
+	std::string edmg_channel_as_string;
+	bool is_60Ghz_used = false;
+
+	if (((band & band60Ghz) != 0)) {
+		hw_mode_as_string = "hw_mode=ad";
+		if (iface_params.hwModeParams.enableEdmg) {
+			enable_edmg_as_string = "enable_edmg=1";
+			edmg_channel_as_string = StringPrintf(
+				"edmg_channel=%d",
+				channelParams.channel);
+		}
+		is_60Ghz_used = true;
+	} else if ((band & band2Ghz) != 0) {
+		if (((band & band5Ghz) != 0)
+		    || ((band & band6Ghz) != 0)) {
+			hw_mode_as_string = "hw_mode=any";
+		} else {
+			hw_mode_as_string = "hw_mode=g";
+		}
+	} else if (((band & band5Ghz) != 0)
+		    || ((band & band6Ghz) != 0)) {
+			hw_mode_as_string = "hw_mode=a";
+	} else {
+		wpa_printf(MSG_ERROR, "Invalid band");
+		return "";
+	}
+
+	std::string he_params_as_string;
+#ifdef CONFIG_IEEE80211AX
+	if (iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) {
+		he_params_as_string = StringPrintf(
+			"ieee80211ax=1\n"
+			"he_su_beamformer=%d\n"
+			"he_su_beamformee=%d\n"
+			"he_mu_beamformer=%d\n"
+			"he_twt_required=%d\n",
+			iface_params.hwModeParams.enableHeSingleUserBeamformer ? 1 : 0,
+			iface_params.hwModeParams.enableHeSingleUserBeamformee ? 1 : 0,
+			iface_params.hwModeParams.enableHeMultiUserBeamformer ? 1 : 0,
+			iface_params.hwModeParams.enableHeTargetWakeTime ? 1 : 0);
+	} else {
+		he_params_as_string = "ieee80211ax=0";
+	}
+#endif /* CONFIG_IEEE80211AX */
+
+	std::string ht_cap_vht_oper_he_oper_chwidth_as_string;
+	switch (iface_params.hwModeParams.maximumChannelBandwidth) {
+	case ChannelBandwidth::BANDWIDTH_20:
+		ht_cap_vht_oper_he_oper_chwidth_as_string = StringPrintf(
+#ifdef CONFIG_IEEE80211AX
+			"he_oper_chwidth=0\n"
+#endif
+			"vht_oper_chwidth=0");
+		break;
+	case ChannelBandwidth::BANDWIDTH_40:
+		ht_cap_vht_oper_he_oper_chwidth_as_string = StringPrintf(
+			"ht_capab=[HT40+]\n"
+#ifdef CONFIG_IEEE80211AX
+			"he_oper_chwidth=0\n"
+#endif
+			"vht_oper_chwidth=0");
+		break;
+	case ChannelBandwidth::BANDWIDTH_80:
+		ht_cap_vht_oper_he_oper_chwidth_as_string = StringPrintf(
+			"ht_capab=[HT40+]\n"
+#ifdef CONFIG_IEEE80211AX
+			"he_oper_chwidth=%d\n"
+#endif
+			"vht_oper_chwidth=%d",
+#ifdef CONFIG_IEEE80211AX
+			(iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) ? 1 : 0,
+#endif
+			iface_params.hwModeParams.enable80211AC ? 1 : 0);
+		break;
+	case ChannelBandwidth::BANDWIDTH_160:
+		ht_cap_vht_oper_he_oper_chwidth_as_string = StringPrintf(
+			"ht_capab=[HT40+]\n"
+#ifdef CONFIG_IEEE80211AX
+			"he_oper_chwidth=%d\n"
+#endif
+			"vht_oper_chwidth=%d",
+#ifdef CONFIG_IEEE80211AX
+			(iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) ? 2 : 0,
+#endif
+			iface_params.hwModeParams.enable80211AC ? 2 : 0);
+		break;
+	default:
+		if (!is_2Ghz_band_only && !is_60Ghz_used
+		    && iface_params.hwModeParams.enable80211AC) {
+			ht_cap_vht_oper_he_oper_chwidth_as_string =
+					"ht_capab=[HT40+]\n"
+					"vht_oper_chwidth=1\n";
+		}
+#ifdef CONFIG_IEEE80211AX
+		if (iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) {
+			ht_cap_vht_oper_he_oper_chwidth_as_string += "he_oper_chwidth=1";
+		}
+#endif
+		break;
+	}
+
+#ifdef CONFIG_INTERWORKING
+	std::string access_network_params_as_string;
+	if (nw_params.isMetered) {
+		access_network_params_as_string = StringPrintf(
+			"interworking=1\n"
+			"access_network_type=2\n"); // CHARGEABLE_PUBLIC_NETWORK
+	} else {
+	    access_network_params_as_string = StringPrintf(
+			"interworking=0\n");
+	}
+#endif /* CONFIG_INTERWORKING */
+
+	std::string bridge_as_string;
+	if (!br_name.empty()) {
+		bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
+	}
+
+	// vendor_elements string
+	std::string vendor_elements_as_string;
+	if (nw_params.vendorElements.size() > 0) {
+		std::stringstream ss;
+		ss << std::hex;
+		ss << std::setfill('0');
+		for (uint8_t b : nw_params.vendorElements) {
+			ss << std::setw(2) << static_cast<unsigned int>(b);
+		}
+		vendor_elements_as_string = StringPrintf("vendor_elements=%s", ss.str().c_str());
+	}
+
+	std::string owe_transition_ifname_as_string;
+	if (!owe_transition_ifname.empty()) {
+		owe_transition_ifname_as_string = StringPrintf(
+			"owe_transition_ifname=%s", owe_transition_ifname.c_str());
+	}
+
+	return StringPrintf(
+		"interface=%s\n"
+		"driver=nl80211\n"
+		"ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
+		// ssid2 signals to hostapd that the value is not a literal value
+		// for use as a SSID.  In this case, we're giving it a hex
+		// std::string and hostapd needs to expect that.
+		"ssid2=%s\n"
+		"%s\n"
+		"ieee80211n=%d\n"
+		"ieee80211ac=%d\n"
+		"%s\n"
+		"%s\n"
+		"%s\n"
+		"ignore_broadcast_ssid=%d\n"
+		"wowlan_triggers=any\n"
+#ifdef CONFIG_INTERWORKING
+		"%s\n"
+#endif /* CONFIG_INTERWORKING */
+		"%s\n"
+		"%s\n"
+		"%s\n"
+		"%s\n"
+		"%s\n"
+		"%s\n",
+		iface_params.name.c_str(), ssid_as_string.c_str(),
+		channel_config_as_string.c_str(),
+		iface_params.hwModeParams.enable80211N ? 1 : 0,
+		iface_params.hwModeParams.enable80211AC ? 1 : 0,
+		he_params_as_string.c_str(),
+		hw_mode_as_string.c_str(), ht_cap_vht_oper_he_oper_chwidth_as_string.c_str(),
+		nw_params.isHidden ? 1 : 0,
+#ifdef CONFIG_INTERWORKING
+		access_network_params_as_string.c_str(),
+#endif /* CONFIG_INTERWORKING */
+		encryption_config_as_string.c_str(),
+		bridge_as_string.c_str(),
+		owe_transition_ifname_as_string.c_str(),
+		enable_edmg_as_string.c_str(),
+		edmg_channel_as_string.c_str(),
+		vendor_elements_as_string.c_str());
+}
+
+Generation getGeneration(hostapd_hw_modes *current_mode)
+{
+	wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d,"
+		   " vht_enabled=%d, he_supported=%d",
+		   current_mode->mode, current_mode->ht_capab != 0,
+		   current_mode->vht_capab != 0, current_mode->he_capab->he_supported);
+	switch (current_mode->mode) {
+	case HOSTAPD_MODE_IEEE80211B:
+		return Generation::WIFI_STANDARD_LEGACY;
+	case HOSTAPD_MODE_IEEE80211G:
+		return current_mode->ht_capab == 0 ?
+				Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
+	case HOSTAPD_MODE_IEEE80211A:
+		if (current_mode->he_capab->he_supported) {
+			return Generation::WIFI_STANDARD_11AX;
+		}
+		return current_mode->vht_capab == 0 ?
+		       Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
+	case HOSTAPD_MODE_IEEE80211AD:
+		return Generation::WIFI_STANDARD_11AD;
+	default:
+		return Generation::WIFI_STANDARD_UNKNOWN;
+	}
+}
+
+ChannelBandwidth getChannelBandwidth(struct hostapd_config *iconf)
+{
+	wpa_printf(MSG_DEBUG, "getChannelBandwidth %d, isHT=%d, isHT40=%d",
+		   iconf->vht_oper_chwidth, iconf->ieee80211n,
+		   iconf->secondary_channel);
+	switch (iconf->vht_oper_chwidth) {
+	case CHANWIDTH_80MHZ:
+		return ChannelBandwidth::BANDWIDTH_80;
+	case CHANWIDTH_80P80MHZ:
+		return ChannelBandwidth::BANDWIDTH_80P80;
+		break;
+	case CHANWIDTH_160MHZ:
+		return ChannelBandwidth::BANDWIDTH_160;
+		break;
+	case CHANWIDTH_USE_HT:
+		if (iconf->ieee80211n) {
+			return iconf->secondary_channel != 0 ?
+				ChannelBandwidth::BANDWIDTH_40 : ChannelBandwidth::BANDWIDTH_20;
+		}
+		return ChannelBandwidth::BANDWIDTH_20_NOHT;
+	case CHANWIDTH_2160MHZ:
+		return ChannelBandwidth::BANDWIDTH_2160;
+	case CHANWIDTH_4320MHZ:
+		return ChannelBandwidth::BANDWIDTH_4320;
+	case CHANWIDTH_6480MHZ:
+		return ChannelBandwidth::BANDWIDTH_6480;
+	case CHANWIDTH_8640MHZ:
+		return ChannelBandwidth::BANDWIDTH_8640;
+	default:
+		return ChannelBandwidth::BANDWIDTH_INVALID;
+	}
+}
+
+bool forceStaDisconnection(struct hostapd_data* hapd,
+			   const std::vector<uint8_t>& client_address,
+			   const uint16_t reason_code) {
+	struct sta_info *sta;
+	for (sta = hapd->sta_list; sta; sta = sta->next) {
+		int res;
+		res = memcmp(sta->addr, client_address.data(), ETH_ALEN);
+		if (res == 0) {
+			wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
+			    MAC2STR(client_address.data()), reason_code);
+			ap_sta_disconnect(hapd, sta, sta->addr, reason_code);
+			return true;
+		}
+	}
+	return false;
+}
+
+// hostapd core functions accept "C" style function pointers, so use global
+// functions to pass to the hostapd core function and store the corresponding
+// std::function methods to be invoked.
+//
+// NOTE: Using the pattern from the vendor HAL (wifi_legacy_hal.cpp).
+//
+// Callback to be invoked once setup is complete
+std::function<void(struct hostapd_data*)> on_setup_complete_internal_callback;
+void onAsyncSetupCompleteCb(void* ctx)
+{
+	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+	if (on_setup_complete_internal_callback) {
+		on_setup_complete_internal_callback(iface_hapd);
+		// Invalidate this callback since we don't want this firing
+		// again in single AP mode.
+		if (strlen(iface_hapd->conf->bridge) > 0) {
+			on_setup_complete_internal_callback = nullptr;
+		}
+	}
+}
+
+// Callback to be invoked on hotspot client connection/disconnection
+std::function<void(struct hostapd_data*, const u8 *mac_addr, int authorized,
+		const u8 *p2p_dev_addr)> on_sta_authorized_internal_callback;
+void onAsyncStaAuthorizedCb(void* ctx, const u8 *mac_addr, int authorized,
+		const u8 *p2p_dev_addr)
+{
+	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+	if (on_sta_authorized_internal_callback) {
+		on_sta_authorized_internal_callback(iface_hapd, mac_addr,
+			authorized, p2p_dev_addr);
+	}
+}
+
+std::function<void(struct hostapd_data*, int level,
+			enum wpa_msg_type type, const char *txt,
+			size_t len)> on_wpa_msg_internal_callback;
+
+void onAsyncWpaEventCb(void *ctx, int level,
+			enum wpa_msg_type type, const char *txt,
+			size_t len)
+{
+	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+	if (on_wpa_msg_internal_callback) {
+		on_wpa_msg_internal_callback(iface_hapd, level,
+					type, txt, len);
+	}
+}
+
+inline ndk::ScopedAStatus createStatus(HostapdStatusCode status_code) {
+	return ndk::ScopedAStatus::fromServiceSpecificError(
+		static_cast<int32_t>(status_code));
+}
+
+inline ndk::ScopedAStatus createStatusWithMsg(
+	HostapdStatusCode status_code, std::string msg)
+{
+	return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+		static_cast<int32_t>(status_code), msg.c_str());
+}
+
+// Method called by death_notifier_ on client death.
+void onDeath(void* cookie) {
+	wpa_printf(MSG_ERROR, "Client died. Terminating...");
+	eloop_terminate();
+}
+
+}  // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace hostapd {
+
+Hostapd::Hostapd(struct hapd_interfaces* interfaces)
+	: interfaces_(interfaces)
+{
+	death_notifier_ = AIBinder_DeathRecipient_new(onDeath);
+}
+
+::ndk::ScopedAStatus Hostapd::addAccessPoint(
+	const IfaceParams& iface_params, const NetworkParams& nw_params)
+{
+	return addAccessPointInternal(iface_params, nw_params);
+}
+
+::ndk::ScopedAStatus Hostapd::removeAccessPoint(const std::string& iface_name)
+{
+	return removeAccessPointInternal(iface_name);
+}
+
+::ndk::ScopedAStatus Hostapd::terminate()
+{
+	wpa_printf(MSG_INFO, "Terminating...");
+	// Clear the callback to avoid IPCThreadState shutdown during the
+	// callback event.
+	callbacks_.clear();
+	eloop_terminate();
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::registerCallback(
+	const std::shared_ptr<IHostapdCallback>& callback)
+{
+	return registerCallbackInternal(callback);
+}
+
+::ndk::ScopedAStatus Hostapd::forceClientDisconnect(
+	const std::string& iface_name, const std::vector<uint8_t>& client_address,
+	Ieee80211ReasonCode reason_code)
+{
+	return forceClientDisconnectInternal(iface_name, client_address, reason_code);
+}
+
+::ndk::ScopedAStatus Hostapd::setDebugParams(DebugLevel level)
+{
+	return setDebugParamsInternal(level);
+}
+
+::ndk::ScopedAStatus Hostapd::addAccessPointInternal(
+	const IfaceParams& iface_params,
+	const NetworkParams& nw_params)
+{
+	int channelParamsSize = iface_params.channelParams.size();
+	if (channelParamsSize == 1) {
+		// Single AP
+		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
+			iface_params.name.c_str());
+		return addSingleAccessPoint(iface_params, iface_params.channelParams[0],
+		    nw_params, "", "");
+	} else if (channelParamsSize == 2) {
+		// Concurrent APs
+		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
+			iface_params.name.c_str());
+		return addConcurrentAccessPoints(iface_params, nw_params);
+	}
+	return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
+}
+
+std::vector<uint8_t>  generateRandomOweSsid()
+{
+	u8 random[8] = {0};
+	os_get_random(random, 8);
+
+	std::string ssid = StringPrintf("Owe-%s", random);
+	wpa_printf(MSG_INFO, "Generated OWE SSID: %s", ssid.c_str());
+	std::vector<uint8_t> vssid(ssid.begin(), ssid.end());
+
+	return vssid;
+}
+
+::ndk::ScopedAStatus Hostapd::addConcurrentAccessPoints(
+	const IfaceParams& iface_params, const NetworkParams& nw_params)
+{
+	int channelParamsListSize = iface_params.channelParams.size();
+	// Get available interfaces in bridge
+	std::vector<std::string> managed_interfaces;
+	std::string br_name = StringPrintf(
+		"%s", iface_params.name.c_str());
+	if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
+		return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
+			"Get interfaces in bridge failed.");
+	}
+	if (managed_interfaces.size() < channelParamsListSize) {
+		return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
+			"Available interfaces less than requested bands");
+	}
+	// start BSS on specified bands
+	for (std::size_t i = 0; i < channelParamsListSize; i ++) {
+		IfaceParams iface_params_new = iface_params;
+		NetworkParams nw_params_new = nw_params;
+		iface_params_new.name = managed_interfaces[i];
+
+		std::string owe_transition_ifname = "";
+		if (nw_params.encryptionType == EncryptionType::WPA3_OWE_TRANSITION) {
+			if (i == 0 && i+1 < channelParamsListSize) {
+				owe_transition_ifname = managed_interfaces[i+1];
+				nw_params_new.encryptionType = EncryptionType::NONE;
+			} else {
+				owe_transition_ifname = managed_interfaces[0];
+				nw_params_new.isHidden = true;
+				nw_params_new.ssid = generateRandomOweSsid();
+			}
+		}
+
+		ndk::ScopedAStatus status = addSingleAccessPoint(
+		    iface_params_new, iface_params.channelParams[i], nw_params_new,
+		    br_name, owe_transition_ifname);
+		if (!status.isOk()) {
+			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
+				   managed_interfaces[i].c_str());
+			return status;
+		}
+	}
+	// Save bridge interface info
+	br_interfaces_[br_name] = managed_interfaces;
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::addSingleAccessPoint(
+	const IfaceParams& iface_params,
+	const ChannelParams& channelParams,
+	const NetworkParams& nw_params,
+	const std::string br_name,
+	const std::string owe_transition_ifname)
+{
+	if (hostapd_get_iface(interfaces_, iface_params.name.c_str())) {
+		wpa_printf(
+			MSG_ERROR, "Interface %s already present",
+			iface_params.name.c_str());
+		return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
+	}
+	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params,
+					br_name, owe_transition_ifname);
+	if (conf_params.empty()) {
+		wpa_printf(MSG_ERROR, "Failed to create config params");
+		return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
+	}
+	const auto conf_file_path =
+		WriteHostapdConfig(iface_params.name, conf_params);
+	if (conf_file_path.empty()) {
+		wpa_printf(MSG_ERROR, "Failed to write config file");
+		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+	}
+	std::string add_iface_param_str = StringPrintf(
+		"%s config=%s", iface_params.name.c_str(),
+		conf_file_path.c_str());
+	std::vector<char> add_iface_param_vec(
+		add_iface_param_str.begin(), add_iface_param_str.end() + 1);
+	if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
+		wpa_printf(
+			MSG_ERROR, "Adding interface %s failed",
+			add_iface_param_str.c_str());
+		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+	}
+	struct hostapd_data* iface_hapd =
+	    hostapd_get_iface(interfaces_, iface_params.name.c_str());
+	WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
+	// Register the setup complete callbacks
+	on_setup_complete_internal_callback =
+		[this](struct hostapd_data* iface_hapd) {
+			wpa_printf(
+			MSG_INFO, "AP interface setup completed - state %s",
+			hostapd_state_text(iface_hapd->iface->state));
+			if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
+				// Invoke the failure callback on all registered
+				// clients.
+				for (const auto& callback : callbacks_) {
+					callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
+						iface_hapd->conf->bridge : iface_hapd->conf->iface,
+							    iface_hapd->conf->iface);
+				}
+			}
+		};
+
+	// Register for new client connect/disconnect indication.
+	on_sta_authorized_internal_callback =
+		[this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
+			int authorized, const u8 *p2p_dev_addr) {
+		wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
+				MAC2STR(mac_addr),
+				(authorized) ? "Connected" : "Disconnected");
+		ClientInfo info;
+		info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
+			iface_hapd->conf->bridge : iface_hapd->conf->iface;
+		info.apIfaceInstance = iface_hapd->conf->iface;
+		info.clientAddress.assign(mac_addr, mac_addr + ETH_ALEN);
+		info.isConnected = authorized;
+		for (const auto &callback : callbacks_) {
+			callback->onConnectedClientsChanged(info);
+		}
+		};
+
+	// Register for wpa_event which used to get channel switch event
+	on_wpa_msg_internal_callback =
+		[this](struct hostapd_data* iface_hapd, int level,
+			enum wpa_msg_type type, const char *txt,
+			size_t len) {
+		wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
+		if (os_strncmp(txt, AP_EVENT_ENABLED,
+					strlen(AP_EVENT_ENABLED)) == 0 ||
+			os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
+					strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
+			ApInfo info;
+			info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
+				iface_hapd->conf->bridge : iface_hapd->conf->iface,
+			info.apIfaceInstance = iface_hapd->conf->iface;
+			info.freqMhz = iface_hapd->iface->freq;
+			info.channelBandwidth = getChannelBandwidth(iface_hapd->iconf);
+			info.generation = getGeneration(iface_hapd->iface->current_mode);
+			info.apIfaceInstanceMacAddress.assign(iface_hapd->own_addr,
+				iface_hapd->own_addr + ETH_ALEN);
+			for (const auto &callback : callbacks_) {
+				callback->onApInstanceInfoChanged(info);
+			}
+		} else if (os_strncmp(txt, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0
+                           || os_strncmp(txt, INTERFACE_DISABLED, strlen(INTERFACE_DISABLED)) == 0)
+		{
+			// Invoke the failure callback on all registered clients.
+			for (const auto& callback : callbacks_) {
+				callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
+					iface_hapd->conf->bridge : iface_hapd->conf->iface,
+						    iface_hapd->conf->iface);
+			}
+		}
+	};
+
+	// Setup callback
+	iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
+	iface_hapd->setup_complete_cb_ctx = iface_hapd;
+	iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
+	iface_hapd->sta_authorized_cb_ctx = iface_hapd;
+	wpa_msg_register_cb(onAsyncWpaEventCb);
+
+	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
+		wpa_printf(
+			MSG_ERROR, "Enabling interface %s failed",
+			iface_params.name.c_str());
+		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
+{
+	// interfaces to be removed
+	std::vector<std::string> interfaces;
+	bool is_error = false;
+
+	const auto it = br_interfaces_.find(iface_name);
+	if (it != br_interfaces_.end()) {
+		// In case bridge, remove managed interfaces
+		interfaces = it->second;
+		br_interfaces_.erase(iface_name);
+	} else {
+		// else remove current interface
+		interfaces.push_back(iface_name);
+	}
+
+	for (auto& iface : interfaces) {
+		std::vector<char> remove_iface_param_vec(
+		    iface.begin(), iface.end() + 1);
+		if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <  0) {
+			wpa_printf(MSG_INFO, "Remove interface %s failed", iface.c_str());
+			is_error = true;
+		}
+	}
+	if (is_error) {
+		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::registerCallbackInternal(
+	const std::shared_ptr<IHostapdCallback>& callback)
+{
+	binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+			death_notifier_, this /* cookie */);
+	if (status != STATUS_OK) {
+		wpa_printf(
+			MSG_ERROR,
+			"Error registering for death notification for "
+			"hostapd callback object");
+		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+	}
+	callbacks_.push_back(callback);
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Hostapd::forceClientDisconnectInternal(const std::string& iface_name,
+	const std::vector<uint8_t>& client_address, Ieee80211ReasonCode reason_code)
+{
+	struct hostapd_data *hapd = hostapd_get_iface(interfaces_, iface_name.c_str());
+	bool result;
+	if (!hapd) {
+		for (auto const& iface : br_interfaces_) {
+			if (iface.first == iface_name) {
+				for (auto const& instance : iface.second) {
+					hapd = hostapd_get_iface(interfaces_, instance.c_str());
+					if (hapd) {
+						result = forceStaDisconnection(hapd, client_address,
+								(uint16_t) reason_code);
+						if (result) break;
+					}
+				}
+			}
+		}
+	} else {
+		result = forceStaDisconnection(hapd, client_address, (uint16_t) reason_code);
+	}
+	if (!hapd) {
+		wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
+		return createStatus(HostapdStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	if (result) {
+		return ndk::ScopedAStatus::ok();
+	}
+	return createStatus(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN);
+}
+
+::ndk::ScopedAStatus Hostapd::setDebugParamsInternal(DebugLevel level)
+{
+	wpa_debug_level = static_cast<uint32_t>(level);
+	return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace hostapd
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/hostapd/aidl/hostapd.h b/hostapd/aidl/hostapd.h
new file mode 100644
index 0000000..ffdbd8e
--- /dev/null
+++ b/hostapd/aidl/hostapd.h
@@ -0,0 +1,95 @@
+/*
+ * aidl interface for wpa_hostapd daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#pragma once
+
+#include <map>
+#include <string>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/hostapd/BnHostapd.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+#include "utils/wpa_debug.h"
+#include "ap/hostapd.h"
+#include "ap/sta_info.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace hostapd {
+
+/**
+ * Implementation of the hostapd aidl object. This aidl
+ * object is used core for global control operations on
+ * hostapd.
+ */
+class Hostapd : public BnHostapd
+{
+public:
+	Hostapd(hapd_interfaces* interfaces);
+	~Hostapd() override = default;
+
+	// Aidl methods exposed.
+	::ndk::ScopedAStatus addAccessPoint(
+	    const IfaceParams& iface_params, const NetworkParams& nw_params) override;
+	::ndk::ScopedAStatus removeAccessPoint(const std::string& iface_name) override;
+	::ndk::ScopedAStatus terminate() override;
+	::ndk::ScopedAStatus registerCallback(
+	    const std::shared_ptr<IHostapdCallback>& callback) override;
+	::ndk::ScopedAStatus forceClientDisconnect(
+	    const std::string& iface_name,
+	    const std::vector<uint8_t>& client_address,
+	    Ieee80211ReasonCode reason_code) override;
+	::ndk::ScopedAStatus setDebugParams(DebugLevel level) override;
+private:
+	// Corresponding worker functions for the AIDL methods.
+	::ndk::ScopedAStatus addAccessPointInternal(
+	    const IfaceParams& iface_params,
+	    const NetworkParams& nw_params);
+	::ndk::ScopedAStatus addSingleAccessPoint(
+	    const IfaceParams& IfaceParams,
+	    const ChannelParams& channelParams,
+	    const NetworkParams& nw_params,
+	    std::string br_name,
+	    std::string owe_transition_ifname);
+	::ndk::ScopedAStatus addConcurrentAccessPoints(
+	    const IfaceParams& IfaceParams,
+	    const NetworkParams& nw_params);
+	::ndk::ScopedAStatus removeAccessPointInternal(const std::string& iface_name);
+	::ndk::ScopedAStatus registerCallbackInternal(
+	    const std::shared_ptr<IHostapdCallback>& callback);
+	::ndk::ScopedAStatus forceClientDisconnectInternal(
+	    const std::string& iface_name,
+	    const std::vector<uint8_t>& client_address,
+	    Ieee80211ReasonCode reason_code);
+	::ndk::ScopedAStatus setDebugParamsInternal(DebugLevel level);
+
+	// Raw pointer to the global structure maintained by the core.
+	struct hapd_interfaces* interfaces_;
+	// Callbacks registered.
+	std::vector<std::shared_ptr<IHostapdCallback>> callbacks_;
+	// Death notifier.
+	AIBinder_DeathRecipient* death_notifier_;
+	// Bridge and its managed interfaces.
+	std::map<std::string, std::vector<std::string>> br_interfaces_;
+	DISALLOW_COPY_AND_ASSIGN(Hostapd);
+};
+}  // namespace hostapd
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/hostapd/android.config b/hostapd/android.config
index fd3c1a1..6ed6f6a 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -25,13 +25,14 @@
 #LIBS += -L$(LIBNL)/lib
 CONFIG_LIBNL20=y
 
-# BCM vendor extensions to nl80211
+# Broadcom vendor extensions to nl80211
 ifeq ($(BOARD_WLAN_DEVICE),bcmdhd)
 CONFIG_DRIVER_NL80211_BRCM=y
 else
 # QCA vendor extensions to nl80211
 CONFIG_DRIVER_NL80211_QCA=y
 endif
+
 # Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
 #CONFIG_DRIVER_BSD=y
 #CFLAGS += -I/usr/local/include
@@ -219,9 +220,9 @@
 # either wpa_supplicant or hostapd are run.
 CONFIG_NO_RANDOM_POOL=y
 
-# Add support for Hidl control interface
+# Add support for Aidl control interface
 # Only applicable for Android platforms.
-CONFIG_CTRL_IFACE_HIDL=y
+CONFIG_CTRL_IFACE_AIDL=y
 
 # Enable support of Automatic Channel Selection
 CONFIG_ACS=y
diff --git a/hostapd/android.hardware.wifi.hostapd.xml b/hostapd/android.hardware.wifi.hostapd.xml
index c688d3e..eb91ee2 100644
--- a/hostapd/android.hardware.wifi.hostapd.xml
+++ b/hostapd/android.hardware.wifi.hostapd.xml
@@ -1,11 +1,6 @@
 <manifest version="1.0" type="device">
-    <hal format="hidl">
+    <hal format="aidl">
         <name>android.hardware.wifi.hostapd</name>
-        <transport>hwbinder</transport>
-        <version>1.3</version>
-        <interface>
-            <name>IHostapd</name>
-            <instance>default</instance>
-        </interface>
+        <fqname>IHostapd/default</fqname>
     </hal>
 </manifest>
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 03371e1..7e605ff 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -13,6 +13,7 @@
 
 #include "utils/common.h"
 #include "utils/uuid.h"
+#include "utils/crc32.h"
 #include "common/ieee802_11_defs.h"
 #include "common/sae.h"
 #include "crypto/sha256.h"
@@ -2332,6 +2333,22 @@
 #endif /* CONFIG_DPP2 */
 
 
+static int get_hex_config(u8 *buf, size_t max_len, int line,
+			  const char *field, const char *val)
+{
+	size_t hlen = os_strlen(val), len = hlen / 2;
+	u8 tmp[EXT_CAPA_MAX_LEN];
+
+	os_memset(tmp, 0, EXT_CAPA_MAX_LEN);
+	if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field);
+		return -1;
+	}
+	os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN);
+	return 0;
+}
+
+
 static int hostapd_config_fill(struct hostapd_config *conf,
 			       struct hostapd_bss_config *bss,
 			       const char *buf, char *pos, int line)
@@ -2380,16 +2397,19 @@
 		wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
 			   line);
 	} else if (os_strcmp(buf, "ssid") == 0) {
-		bss->ssid.ssid_len = os_strlen(pos);
-		if (bss->ssid.ssid_len > SSID_MAX_LEN ||
-		    bss->ssid.ssid_len < 1) {
+		struct hostapd_ssid *ssid = &bss->ssid;
+
+		ssid->ssid_len = os_strlen(pos);
+		if (ssid->ssid_len > SSID_MAX_LEN || ssid->ssid_len < 1) {
 			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
 				   line, pos);
 			return 1;
 		}
-		os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len);
-		bss->ssid.ssid_set = 1;
+		os_memcpy(ssid->ssid, pos, ssid->ssid_len);
+		ssid->ssid_set = 1;
+		ssid->short_ssid = crc32(ssid->ssid, ssid->ssid_len);
 	} else if (os_strcmp(buf, "ssid2") == 0) {
+		struct hostapd_ssid *ssid = &bss->ssid;
 		size_t slen;
 		char *str = wpa_config_parse_string(pos, &slen);
 		if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
@@ -2398,9 +2418,10 @@
 			os_free(str);
 			return 1;
 		}
-		os_memcpy(bss->ssid.ssid, str, slen);
-		bss->ssid.ssid_len = slen;
-		bss->ssid.ssid_set = 1;
+		os_memcpy(ssid->ssid, str, slen);
+		ssid->ssid_len = slen;
+		ssid->ssid_set = 1;
+		ssid->short_ssid = crc32(ssid->ssid, ssid->ssid_len);
 		os_free(str);
 	} else if (os_strcmp(buf, "utf8_ssid") == 0) {
 		bss->ssid.utf8_ssid = atoi(pos) > 0;
@@ -2458,12 +2479,13 @@
 		bss->ieee802_1x = atoi(pos);
 	} else if (os_strcmp(buf, "eapol_version") == 0) {
 		int eapol_version = atoi(pos);
-
 #ifdef CONFIG_MACSEC
-		if (eapol_version < 1 || eapol_version > 3) {
+		int max_ver = 3;
 #else /* CONFIG_MACSEC */
-		if (eapol_version < 1 || eapol_version > 2) {
+		int max_ver = 2;
 #endif /* CONFIG_MACSEC */
+
+		if (eapol_version < 1 || eapol_version > max_ver) {
 			wpa_printf(MSG_ERROR,
 				   "Line %d: invalid EAPOL version (%d): '%s'.",
 				   line, eapol_version, pos);
@@ -2711,6 +2733,9 @@
 			return 1;
 		}
 		bss->radius->force_client_addr = 1;
+	} else if (os_strcmp(buf, "radius_client_dev") == 0) {
+			os_free(bss->radius->force_client_dev);
+			bss->radius->force_client_dev = os_strdup(pos);
 	} else if (os_strcmp(buf, "auth_server_addr") == 0) {
 		if (hostapd_config_read_radius_addr(
 			    &bss->radius->auth_servers,
@@ -3168,6 +3193,16 @@
 		conf->acs_freq_list_present = 1;
 	} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
 		conf->acs_exclude_6ghz_non_psc = atoi(pos);
+	} else if (os_strcmp(buf, "min_tx_power") == 0) {
+		int val = atoi(pos);
+
+		if (val < 0 || val > 255) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid min_tx_power %d (expected 0..255)",
+				   line, val);
+			return 1;
+		}
+		conf->min_tx_power = val;
 	} else if (os_strcmp(buf, "beacon_int") == 0) {
 		int val = atoi(pos);
 		/* MIB defines range as 1..65535, but very small values
@@ -3491,8 +3526,12 @@
 		conf->he_op.he_default_pe_duration = atoi(pos);
 	} else if (os_strcmp(buf, "he_twt_required") == 0) {
 		conf->he_op.he_twt_required = atoi(pos);
+	} else if (os_strcmp(buf, "he_twt_responder") == 0) {
+		conf->he_op.he_twt_responder = atoi(pos);
 	} else if (os_strcmp(buf, "he_rts_threshold") == 0) {
 		conf->he_op.he_rts_threshold = atoi(pos);
+	} else if (os_strcmp(buf, "he_er_su_disable") == 0) {
+		conf->he_op.he_er_su_disable = atoi(pos);
 	} else if (os_strcmp(buf, "he_basic_mcs_nss_set") == 0) {
 		conf->he_op.he_basic_mcs_nss_set = atoi(pos);
 	} else if (os_strcmp(buf, "he_mu_edca_qos_info_param_count") == 0) {
@@ -4277,8 +4316,9 @@
 	} else if (os_strcmp(buf, "assocresp_elements") == 0) {
 		if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
 			return 1;
-	} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
-		bss->sae_anti_clogging_threshold = atoi(pos);
+	} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0 ||
+		   os_strcmp(buf, "anti_clogging_threshold") == 0) {
+		bss->anti_clogging_threshold = atoi(pos);
 	} else if (os_strcmp(buf, "sae_sync") == 0) {
 		bss->sae_sync = atoi(pos);
 	} else if (os_strcmp(buf, "sae_groups") == 0) {
@@ -4665,6 +4705,8 @@
 #ifdef CONFIG_TESTING_OPTIONS
 	} else if (os_strcmp(buf, "force_kdk_derivation") == 0) {
 		bss->force_kdk_derivation = atoi(pos);
+	} else if (os_strcmp(buf, "pasn_corrupt_mic") == 0) {
+		bss->pasn_corrupt_mic = atoi(pos);
 #endif /* CONFIG_TESTING_OPTIONS */
 	} else if (os_strcmp(buf, "pasn_groups") == 0) {
 		if (hostapd_parse_intlist(&bss->pasn_groups, pos)) {
@@ -4673,7 +4715,19 @@
 				   line, pos);
 			return 1;
 		}
+	} else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
+		bss->pasn_comeback_after = atoi(pos);
 #endif /* CONFIG_PASN */
+	} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
+		if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
+				   line, "ext_capa_mask", pos))
+			return 1;
+	} else if (os_strcmp(buf, "ext_capa") == 0) {
+		if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN,
+				   line, "ext_capa", pos))
+			return 1;
+	} else if (os_strcmp(buf, "rnr") == 0) {
+		bss->rnr = atoi(pos);
 	} else {
 		wpa_printf(MSG_ERROR,
 			   "Line %d: unknown configuration item '%s'",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 55f3da7..a62f3c7 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -840,7 +840,7 @@
 	const char *pos, *end;
 	int disassoc_timer = 0;
 	struct sta_info *sta;
-	u8 req_mode = 0, valid_int = 0x01;
+	u8 req_mode = 0, valid_int = 0x01, dialog_token = 0x01;
 	u8 bss_term_dur[12];
 	char *url = NULL;
 	int ret;
@@ -878,6 +878,12 @@
 		valid_int = atoi(pos);
 	}
 
+	pos = os_strstr(cmd, " dialog_token=");
+	if (pos) {
+		pos += 14;
+		dialog_token = atoi(pos);
+	}
+
 	pos = os_strstr(cmd, " bss_term=");
 	if (pos) {
 		pos += 10;
@@ -984,7 +990,7 @@
 #endif /* CONFIG_MBO */
 
 	ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
-				  valid_int, bss_term_dur, url,
+				  valid_int, bss_term_dur, dialog_token, url,
 				  nei_len ? nei_rep : NULL, nei_len,
 				  mbo_len ? mbo : NULL, mbo_len);
 #ifdef CONFIG_MBO
@@ -1455,10 +1461,10 @@
 				   wps_version_number & 0x0f);
 			hostapd_wps_update_ie(hapd);
 		}
-	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
-		wps_testing_dummy_cred = atoi(value);
-		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
-			   wps_testing_dummy_cred);
+	} else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
+		wps_testing_stub_cred = atoi(value);
+		wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
+			   wps_testing_stub_cred);
 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
 		wps_corrupt_pkhash = atoi(value);
 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
@@ -1469,6 +1475,8 @@
 		hapd->ext_mgmt_frame_handling = atoi(value);
 	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
 		hapd->ext_eapol_frame_io = atoi(value);
+	} else if (os_strcasecmp(cmd, "force_backlog_bytes") == 0) {
+		hapd->force_backlog_bytes = atoi(value);
 #ifdef CONFIG_DPP
 	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
 		os_free(hapd->dpp_config_obj_override);
@@ -1496,7 +1504,7 @@
 			return -1;
 
 		val = atoi(value);
-		if (val < 0 || val > 1)
+		if (val < 0 || val > MBO_ASSOC_DISALLOW_REASON_LOW_RSSI)
 			return -1;
 
 		hapd->mbo_assoc_disallow = val;
@@ -1511,6 +1519,16 @@
 	} else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) {
 		os_free(hapd->dpp_configurator_params);
 		hapd->dpp_configurator_params = os_strdup(value);
+	} else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) {
+		hapd->dpp_init_max_tries = atoi(value);
+	} else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) {
+		hapd->dpp_init_retry_time = atoi(value);
+	} else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
+		hapd->dpp_resp_wait_time = atoi(value);
+	} else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) {
+		hapd->dpp_resp_max_tries = atoi(value);
+	} else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) {
+		hapd->dpp_resp_retry_time = atoi(value);
 #endif /* CONFIG_DPP */
 	} else if (os_strcasecmp(cmd, "setband") == 0) {
 		ret = hostapd_ctrl_iface_set_band(hapd, value);
@@ -1938,6 +1956,52 @@
 }
 
 
+static int hostapd_ctrl_iface_eapol_tx(struct hostapd_data *hapd, char *cmd)
+{
+	char *pos, *pos2;
+	u8 dst[ETH_ALEN], *buf;
+	int used, ret;
+	size_t len;
+	unsigned int prev;
+	int encrypt = 0;
+
+	wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
+
+	pos = cmd;
+	used = hwaddr_aton2(pos, dst);
+	if (used < 0)
+		return -1;
+	pos += used;
+	while (*pos == ' ')
+		pos++;
+
+	pos2 = os_strchr(pos, ' ');
+	if (pos2) {
+		len = pos2 - pos;
+		encrypt = os_strstr(pos2, "encrypt=1") != NULL;
+	} else {
+		len = os_strlen(pos);
+	}
+	if (len & 1)
+		return -1;
+	len /= 2;
+
+	buf = os_malloc(len);
+	if (!buf || hexstr2bin(pos, buf, len) < 0) {
+		os_free(buf);
+		return -1;
+	}
+
+	prev = hapd->ext_eapol_frame_io;
+	hapd->ext_eapol_frame_io = 0;
+	ret = hostapd_wpa_auth_send_eapol(hapd, dst, buf, len, encrypt);
+	hapd->ext_eapol_frame_io = prev;
+	os_free(buf);
+
+	return ret;
+}
+
+
 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
 {
 	size_t i;
@@ -2516,6 +2580,22 @@
 }
 
 
+static int hostapd_ctrl_rekey_ptk(struct hostapd_data *hapd, const char *cmd)
+{
+	struct sta_info *sta;
+	u8 addr[ETH_ALEN];
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta || !sta->wpa_sm)
+		return -1;
+
+	return wpa_auth_rekey_ptk(hapd->wpa_auth, sta->wpa_sm);
+}
+
+
 static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr,
 				      char *buf, size_t buflen)
 {
@@ -2556,6 +2636,34 @@
 	return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
 }
 
+
+static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
+				       const char *cmd)
+{
+	u16 type;
+	char *pos, *end;
+	u8 match[10];
+	size_t match_len;
+	bool multicast = false;
+
+	type = strtol(cmd, &pos, 16);
+	if (*pos != ' ')
+		return -1;
+	pos++;
+	end = os_strchr(pos, ' ');
+	if (end) {
+		match_len = end - pos;
+		multicast = os_strstr(end, "multicast") != NULL;
+	} else {
+		match_len = os_strlen(pos) / 2;
+	}
+	if (hexstr2bin(pos, match, match_len))
+		return -1;
+
+	return hostapd_drv_register_frame(hapd, type, match, match_len,
+					  multicast);
+}
+
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
@@ -3087,8 +3195,9 @@
 	u8 bssid[ETH_ALEN];
 	struct wpabuf *nr, *lci = NULL, *civic = NULL;
 	int stationary = 0;
+	int bss_parameters = 0;
 	char *tmp;
-	int ret;
+	int ret = -1;
 
 	if (!(hapd->conf->radio_measurements[0] &
 	      WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
@@ -3142,8 +3251,7 @@
 		if (!lci) {
 			wpa_printf(MSG_ERROR,
 				   "CTRL: SET_NEIGHBOR: Bad LCI subelement");
-			wpabuf_free(nr);
-			return -1;
+			goto fail;
 		}
 	}
 
@@ -3159,9 +3267,7 @@
 		if (!civic) {
 			wpa_printf(MSG_ERROR,
 				   "CTRL: SET_NEIGHBOR: Bad civic subelement");
-			wpabuf_free(nr);
-			wpabuf_free(lci);
-			return -1;
+			goto fail;
 		}
 	}
 
@@ -3171,10 +3277,21 @@
 	if (os_strstr(buf, "stat"))
 		stationary = 1;
 
+	tmp = os_strstr(buf, "bss_parameter=");
+	if (tmp) {
+		bss_parameters = atoi(tmp + 14);
+		if (bss_parameters < 0 || bss_parameters > 0xff) {
+			wpa_printf(MSG_ERROR,
+				   "CTRL: SET_NEIGHBOR: Bad bss_parameters subelement");
+			goto fail;
+		}
+	}
+
 set:
 	ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic,
-				   stationary);
+				   stationary, bss_parameters);
 
+fail:
 	wpabuf_free(nr);
 	wpabuf_free(lci);
 	wpabuf_free(civic);
@@ -3350,7 +3467,9 @@
 	if (os_strcmp(field, "dpp") == 0) {
 		int res;
 
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+		res = os_snprintf(buf, buflen, "DPP=3");
+#elif defined(CONFIG_DPP2)
 		res = os_snprintf(buf, buflen, "DPP=2");
 #else /* CONFIG_DPP2 */
 		res = os_snprintf(buf, buflen, "DPP=1");
@@ -3368,6 +3487,23 @@
 }
 
 
+#ifdef ANDROID
+static int hostapd_ctrl_iface_driver_cmd(struct hostapd_data *hapd, char *cmd,
+					 char *buf, size_t buflen)
+{
+	int ret;
+
+	ret = hostapd_drv_driver_cmd(hapd, cmd, buf, buflen);
+	if (ret == 0) {
+		ret = os_snprintf(buf, buflen, "%s\n", "OK");
+		if (os_snprintf_error(buflen, ret))
+			ret = -1;
+	}
+	return ret;
+}
+#endif /* ANDROID */
+
+
 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
 					      char *buf, char *reply,
 					      int reply_size,
@@ -3582,6 +3718,9 @@
 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
 		if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
 			reply_len = -1;
+	} else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
+		if (hostapd_ctrl_iface_eapol_tx(hapd, buf + 9) < 0)
+			reply_len = -1;
 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
 		if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
 			reply_len = -1;
@@ -3617,12 +3756,18 @@
 	} else if (os_strncmp(buf, "RESEND_GROUP_M1 ", 16) == 0) {
 		if (hostapd_ctrl_resend_group_m1(hapd, buf + 16) < 0)
 			reply_len = -1;
+	} else if (os_strncmp(buf, "REKEY_PTK ", 10) == 0) {
+		if (hostapd_ctrl_rekey_ptk(hapd, buf + 10) < 0)
+			reply_len = -1;
 	} else if (os_strcmp(buf, "REKEY_GTK") == 0) {
 		if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0)
 			reply_len = -1;
 	} else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
 		reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
 						 reply_size);
+	} else if (os_strncmp(buf, "REGISTER_FRAME ", 15) == 0) {
+		if (hostapd_ctrl_register_frame(hapd, buf + 16) < 0)
+			reply_len = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
 		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
@@ -3870,6 +4015,11 @@
 	} else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
 		reply_len = ptksa_cache_list(hapd->ptksa, reply, reply_size);
 #endif /* CONFIG_PASN */
+#ifdef ANDROID
+	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
+		reply_len = hostapd_ctrl_iface_driver_cmd(hapd, buf + 7, reply,
+							  reply_size);
+#endif /* ANDROID */
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
@@ -4341,14 +4491,16 @@
 {
 #ifdef CONFIG_WPS_TESTING
 	wps_version_number = 0x20;
-	wps_testing_dummy_cred = 0;
+	wps_testing_stub_cred = 0;
 	wps_corrupt_pkhash = 0;
 #endif /* CONFIG_WPS_TESTING */
 
 #ifdef CONFIG_TESTING_OPTIONS
 #ifdef CONFIG_DPP
 	dpp_test = DPP_TEST_DISABLED;
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+	dpp_version_override = 3;
+#elif defined(CONFIG_DPP2)
 	dpp_version_override = 2;
 #else /* CONFIG_DPP2 */
 	dpp_version_override = 1;
diff --git a/hostapd/defconfig b/hostapd/defconfig
index d7626a2..2855acd 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -346,7 +346,7 @@
 # * ath10k
 #
 # For more details refer to:
-# http://wireless.kernel.org/en/users/Documentation/acs
+# https://wireless.wiki.kernel.org/en/users/documentation/acs
 #
 #CONFIG_ACS=y
 
@@ -407,3 +407,11 @@
 # production use.
 # This requires CONFIG_IEEE80211W=y to be enabled, too.
 #CONFIG_PASN=y
+
+# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
+CONFIG_DPP=y
+# DPP version 2 support
+CONFIG_DPP2=y
+# DPP version 3 support (experimental and still changing; do not enable for
+# production use)
+#CONFIG_DPP3=y
diff --git a/hostapd/hidl/1.3/hidl.cpp b/hostapd/hidl/1.3/hidl.cpp
deleted file mode 100644
index 8481908..0000000
--- a/hostapd/hidl/1.3/hidl.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include <hwbinder/IPCThreadState.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include "hostapd.h"
-
-extern "C"
-{
-#include "hidl.h"
-#include "utils/common.h"
-#include "utils/eloop.h"
-#include "utils/includes.h"
-}
-
-using android::hardware::configureRpcThreadpool;
-using android::hardware::IPCThreadState;
-using android::hardware::wifi::hostapd::V1_3::IHostapd;
-using android::hardware::wifi::hostapd::V1_3::implementation::Hostapd;
-
-// This file is a bridge between the hostapd code written in 'C' and the HIDL
-// interface in C++. So, using "C" style static globals here!
-static int hidl_fd = -1;
-static android::sp<IHostapd> service;
-
-void hostapd_hidl_sock_handler(
-    int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
-{
-	IPCThreadState::self()->handlePolledCommands();
-}
-
-int hostapd_hidl_init(struct hapd_interfaces *interfaces)
-{
-	wpa_printf(MSG_DEBUG, "Initing hidl control");
-
-	IPCThreadState::self()->setupPolling(&hidl_fd);
-	if (hidl_fd < 0)
-		goto err;
-
-	wpa_printf(MSG_INFO, "Processing hidl events on FD %d", hidl_fd);
-	// Look for read events from the hidl socket in the eloop.
-	if (eloop_register_read_sock(
-		hidl_fd, hostapd_hidl_sock_handler, interfaces, NULL) < 0)
-		goto err;
-	service = new Hostapd(interfaces);
-	if (!service)
-		goto err;
-	if (service->registerAsService() != android::NO_ERROR)
-		goto err;
-	return 0;
-err:
-	hostapd_hidl_deinit(interfaces);
-	return -1;
-}
-
-void hostapd_hidl_deinit(struct hapd_interfaces *interfaces)
-{
-	wpa_printf(MSG_INFO, "Deiniting hidl control");
-	// Before hidl init, make sure call terminate to clear callback_
-	service->terminate();
-	eloop_unregister_read_sock(hidl_fd);
-	IPCThreadState::shutdown();
-	hidl_fd = -1;
-	service.clear();
-}
diff --git a/hostapd/hidl/1.3/hidl.h b/hostapd/hidl/1.3/hidl.h
deleted file mode 100644
index 5decf64..0000000
--- a/hostapd/hidl/1.3/hidl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef HOSTAPD_HIDL_HIDL_H
-#define HOSTAPD_HIDL_HIDL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif  // _cplusplus
-#include "ap/hostapd.h"
-
-/**
- * This is the hidl RPC interface entry point to the hostapd core.
- * This initializes the hidl driver & IHostapd instance.
- */
-int hostapd_hidl_init(struct hapd_interfaces *interfaces);
-void hostapd_hidl_deinit(struct hapd_interfaces *interfaces);
-
-#ifdef __cplusplus
-}
-#endif  // _cplusplus
-
-#endif  // HOSTAPD_HIDL_HIDL_H
diff --git a/hostapd/hidl/1.3/hidl_return_util.h b/hostapd/hidl/1.3/hidl_return_util.h
deleted file mode 100644
index 6d50348..0000000
--- a/hostapd/hidl/1.3/hidl_return_util.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * hidl interface for wpa_hostapd daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef HIDL_RETURN_UTIL_H_
-#define HIDL_RETURN_UTIL_H_
-
-#include <functional>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace hostapd {
-namespace V1_3 {
-namespace implementation {
-namespace hidl_return_util {
-
-/**
- * These utility functions are used to invoke a method on the provided
- * HIDL interface object.
- */
-// Use for HIDL methods which return only an instance of HostapdStatus.
-template <typename ObjT, typename WorkFuncT, typename StatusT, typename... Args>
-Return<void> call(
-    ObjT* obj, WorkFuncT&& work,
-    const std::function<void(const StatusT&)>& hidl_cb, Args&&... args)
-{
-	hidl_cb((obj->*work)(std::forward<Args>(args)...));
-	return Void();
-}
-}  // namespace hidl_return_util
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace hostapd
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-#endif  // HIDL_RETURN_UTIL_H_
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
deleted file mode 100644
index 72efd3f..0000000
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * hidl interface for wpa_hostapd daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-#include <iomanip>
-#include <sstream>
-#include <string>
-#include <vector>
-#include <net/if.h>
-#include <sys/socket.h>
-#include <linux/if_bridge.h>
-
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
-
-#include "hostapd.h"
-#include "hidl_return_util.h"
-
-extern "C"
-{
-#include "common/wpa_ctrl.h"
-#include "drivers/linux_ioctl.h"
-}
-
-// The HIDL implementation for hostapd creates a hostapd.conf dynamically for
-// each interface. This file can then be used to hook onto the normal config
-// file parsing logic in hostapd code.  Helps us to avoid duplication of code
-// in the HIDL interface.
-// TOOD(b/71872409): Add unit tests for this.
-namespace {
-constexpr char kConfFileNameFmt[] = "/data/vendor/wifi/hostapd/hostapd_%s.conf";
-
-using android::base::RemoveFileIfExists;
-using android::base::StringPrintf;
-using android::base::WriteStringToFile;
-using android::hardware::wifi::hostapd::V1_3::IHostapd;
-using android::hardware::wifi::hostapd::V1_3::Generation;
-using android::hardware::wifi::hostapd::V1_3::Bandwidth;
-
-#define MAX_PORTS 1024
-bool GetInterfacesInBridge(std::string br_name,
-                           std::vector<std::string>* interfaces) {
-	android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
-	if (sock.get() < 0) {
-		wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
-			strerror(errno), __FUNCTION__);
-		return false;
-	}
-
-	struct ifreq request;
-	int i, ifindices[MAX_PORTS];
-	char if_name[IFNAMSIZ];
-	unsigned long args[3];
-
-	memset(ifindices, 0, MAX_PORTS * sizeof(int));
-
-	args[0] = BRCTL_GET_PORT_LIST;
-	args[1] = (unsigned long) ifindices;
-	args[2] = MAX_PORTS;
-
-	strlcpy(request.ifr_name, br_name.c_str(), IFNAMSIZ);
-	request.ifr_data = (char *)args;
-
-	if (ioctl(sock.get(), SIOCDEVPRIVATE, &request) < 0) {
-		wpa_printf(MSG_ERROR, "Failed to ioctl SIOCDEVPRIVATE in %s",
-			__FUNCTION__);
-		return false;
-	}
-
-	for (i = 0; i < MAX_PORTS; i ++) {
-		memset(if_name, 0, IFNAMSIZ);
-		if (ifindices[i] == 0 || !if_indextoname(ifindices[i], if_name)) {
-			continue;
-		}
-		interfaces->push_back(if_name);
-	}
-	return true;
-}
-
-std::string WriteHostapdConfig(
-    const std::string& interface_name, const std::string& config)
-{
-	const std::string file_path =
-	    StringPrintf(kConfFileNameFmt, interface_name.c_str());
-	if (WriteStringToFile(
-		config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		getuid(), getgid())) {
-		return file_path;
-	}
-	// Diagnose failure
-	int error = errno;
-	wpa_printf(
-	    MSG_ERROR, "Cannot write hostapd config to %s, error: %s",
-	    file_path.c_str(), strerror(error));
-	struct stat st;
-	int result = stat(file_path.c_str(), &st);
-	if (result == 0) {
-		wpa_printf(
-		    MSG_ERROR, "hostapd config file uid: %d, gid: %d, mode: %d",
-		    st.st_uid, st.st_gid, st.st_mode);
-	} else {
-		wpa_printf(
-		    MSG_ERROR,
-		    "Error calling stat() on hostapd config file: %s",
-		    strerror(errno));
-	}
-	return "";
-}
-
-/*
- * Get the op_class for a channel/band
- * The logic here is based on Table E-4 in the 802.11 Specification
- */
-int getOpClassForChannel(int channel, int band, bool support11n, bool support11ac) {
-	// 2GHz Band
-	if ((band & IHostapd::BandMask::BAND_2_GHZ) != 0) {
-		if (channel == 14) {
-			return 82;
-		}
-		if (channel >= 1 && channel <= 13) {
-			if (!support11n) {
-				//20MHz channel
-				return 81;
-			}
-			if (channel <= 9) {
-				// HT40 with secondary channel above primary
-				return 83;
-			}
-			// HT40 with secondary channel below primary
-			return 84;
-		}
-		// Error
-		return 0;
-	}
-
-	// 5GHz Band
-	if ((band & IHostapd::BandMask::BAND_5_GHZ) != 0) {
-		if (support11ac) {
-			switch (channel) {
-				case 42:
-				case 58:
-				case 106:
-				case 122:
-				case 138:
-				case 155:
-					// 80MHz channel
-					return 128;
-				case 50:
-				case 114:
-					// 160MHz channel
-					return 129;
-			}
-		}
-
-		if (!support11n) {
-			if (channel >= 36 && channel <= 48) {
-				return 115;
-			}
-			if (channel >= 52 && channel <= 64) {
-				return 118;
-			}
-			if (channel >= 100 && channel <= 144) {
-				return 121;
-			}
-			if (channel >= 149 && channel <= 161) {
-				return 124;
-			}
-			if (channel >= 165 && channel <= 169) {
-				return 125;
-			}
-		} else {
-			switch (channel) {
-				case 36:
-				case 44:
-					// HT40 with secondary channel above primary
-					return 116;
-				case 40:
-				case 48:
-					// HT40 with secondary channel below primary
-					return 117;
-				case 52:
-				case 60:
-					// HT40 with secondary channel above primary
-					return  119;
-				case 56:
-				case 64:
-					// HT40 with secondary channel below primary
-					return 120;
-				case 100:
-				case 108:
-				case 116:
-				case 124:
-				case 132:
-				case 140:
-					// HT40 with secondary channel above primary
-					return 122;
-				case 104:
-				case 112:
-				case 120:
-				case 128:
-				case 136:
-				case 144:
-					// HT40 with secondary channel below primary
-					return 123;
-				case 149:
-				case 157:
-					// HT40 with secondary channel above primary
-					return 126;
-				case 153:
-				case 161:
-					// HT40 with secondary channel below primary
-					return 127;
-			}
-		}
-		// Error
-		return 0;
-	}
-
-	// 6GHz Band
-	if ((band & IHostapd::BandMask::BAND_6_GHZ) != 0) {
-		// Channels 1, 5. 9, 13, ...
-		if ((channel & 0x03) == 0x01) {
-			// 20MHz channel
-			return 131;
-		}
-		// Channels 3, 11, 19, 27, ...
-		if ((channel & 0x07) == 0x03) {
-			// 40MHz channel
-			return 132;
-		}
-		// Channels 7, 23, 39, 55, ...
-		if ((channel & 0x0F) == 0x07) {
-			// 80MHz channel
-			return 133;
-		}
-		// Channels 15, 47, 69, ...
-		if ((channel & 0x1F) == 0x0F) {
-			// 160MHz channel
-			return 134;
-		}
-		if (channel == 2) {
-			// 20MHz channel
-			return 136;
-		}
-		// Error
-		return 0;
-	}
-
-	if ((band & IHostapd::BandMask::BAND_60_GHZ) != 0) {
-		if (1 <= channel && channel <= 8) {
-			return 180;
-		} else if (9 <= channel && channel <= 15) {
-			return 181;
-		} else if (17 <= channel && channel <= 22) {
-			return 182;
-		} else if (25 <= channel && channel <= 29) {
-			return 183;
-		}
-		// Error
-		return 0;
-	}
-
-	return 0;
-}
-
-bool validatePassphrase(int passphrase_len, int min_len, int max_len)
-{
-	if (min_len != -1 && passphrase_len < min_len) return false;
-	if (max_len != -1 && passphrase_len > max_len) return false;
-	return true;
-}
-
-std::string CreateHostapdConfig(
-    const android::hardware::wifi::hostapd::V1_3::IHostapd::IfaceParams& iface_params,
-    const android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams& channelParams,
-    const IHostapd::NetworkParams& nw_params,
-    const std::string br_name)
-{
-	if (nw_params.V1_2.V1_0.ssid.size() >
-	    static_cast<uint32_t>(
-		IHostapd::ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
-		wpa_printf(
-		    MSG_ERROR, "Invalid SSID size: %zu", nw_params.V1_2.V1_0.ssid.size());
-		return "";
-	}
-
-	// SSID string
-	std::stringstream ss;
-	ss << std::hex;
-	ss << std::setfill('0');
-	for (uint8_t b : nw_params.V1_2.V1_0.ssid) {
-		ss << std::setw(2) << static_cast<unsigned int>(b);
-	}
-	const std::string ssid_as_string = ss.str();
-
-	// Encryption config string
-	uint32_t band = 0;
-	band |= channelParams.bandMask;
-	bool is_6Ghz_band_only = band == static_cast<uint32_t>(IHostapd::BandMask::BAND_6_GHZ);
-	bool is_60Ghz_band_only = band == static_cast<uint32_t>(IHostapd::BandMask::BAND_60_GHZ);
-	std::string encryption_config_as_string;
-	switch (nw_params.V1_2.encryptionType) {
-	case IHostapd::EncryptionType::NONE:
-		// no security params
-		break;
-	case IHostapd::EncryptionType::WPA:
-		if (!validatePassphrase(
-		    nw_params.V1_2.passphrase.size(),
-		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
-				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
-		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
-				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
-			return "";
-		}
-		encryption_config_as_string = StringPrintf(
-		    "wpa=3\n"
-		    "wpa_pairwise=%s\n"
-		    "wpa_passphrase=%s",
-		    is_60Ghz_band_only ? "GCMP" : "TKIP CCMP",
-		    nw_params.V1_2.passphrase.c_str());
-		break;
-	case IHostapd::EncryptionType::WPA2:
-		if (!validatePassphrase(
-		    nw_params.V1_2.passphrase.size(),
-		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
-				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
-		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
-				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
-			return "";
-		}
-		encryption_config_as_string = StringPrintf(
-		    "wpa=2\n"
-		    "rsn_pairwise=%s\n"
-		    "wpa_passphrase=%s",
-		    is_60Ghz_band_only ? "GCMP" : "CCMP",
-		    nw_params.V1_2.passphrase.c_str());
-		break;
-	case IHostapd::EncryptionType::WPA3_SAE_TRANSITION:
-		if (!validatePassphrase(
-		    nw_params.V1_2.passphrase.size(),
-		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
-				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
-		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
-				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
-			return "";
-		}
-		encryption_config_as_string = StringPrintf(
-		    "wpa=2\n"
-		    "rsn_pairwise=%s\n"
-		    "wpa_key_mgmt=WPA-PSK SAE\n"
-		    "ieee80211w=1\n"
-		    "sae_require_mfp=1\n"
-		    "wpa_passphrase=%s\n"
-		    "sae_password=%s",
-		    is_60Ghz_band_only ? "GCMP" : "CCMP",
-		    nw_params.V1_2.passphrase.c_str(),
-		    nw_params.V1_2.passphrase.c_str());
-		break;
-	case IHostapd::EncryptionType::WPA3_SAE:
-		if (!validatePassphrase(nw_params.V1_2.passphrase.size(), 1, -1)) {
-			return "";
-		}
-		encryption_config_as_string = StringPrintf(
-		    "wpa=2\n"
-		    "rsn_pairwise=%s\n"
-		    "wpa_key_mgmt=SAE\n"
-		    "ieee80211w=2\n"
-		    "sae_require_mfp=2\n"
-		    "sae_pwe=%d\n"
-		    "sae_password=%s",
-		    is_60Ghz_band_only ? "GCMP" : "CCMP",
-		    is_6Ghz_band_only ? 1 : 2,
-		    nw_params.V1_2.passphrase.c_str());
-		break;
-	default:
-		wpa_printf(MSG_ERROR, "Unknown encryption type");
-		return "";
-	}
-
-	std::string channel_config_as_string;
-	bool isFirst = true;
-	if (channelParams.enableAcs) {
-		std::string freqList_as_string;
-		for (const auto &range :
-		    channelParams.V1_2.acsChannelFreqRangesMhz) {
-			if (!isFirst) {
-				freqList_as_string += ",";
-			}
-			isFirst = false;
-
-			if (range.start != range.end) {
-				freqList_as_string +=
-				    StringPrintf("%d-%d", range.start, range.end);
-			} else {
-				freqList_as_string += StringPrintf("%d", range.start);
-			}
-		}
-		channel_config_as_string = StringPrintf(
-		    "channel=0\n"
-		    "acs_exclude_dfs=%d\n"
-		    "freqlist=%s",
-		    iface_params.V1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs,
-		    freqList_as_string.c_str());
-	} else {
-		int op_class = getOpClassForChannel(
-		    channelParams.channel,
-		    band,
-		    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211N,
-		    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
-		channel_config_as_string = StringPrintf(
-		    "channel=%d\n"
-		    "op_class=%d",
-		    channelParams.channel, op_class);
-	}
-
-	std::string hw_mode_as_string;
-	std::string ht_cap_vht_oper_chwidth_as_string;
-	std::string enable_edmg_as_string;
-	std::string edmg_channel_as_string;
-	bool is_60Ghz_used = false;
-
-	if (((band & IHostapd::BandMask::BAND_60_GHZ) != 0)) {
-		hw_mode_as_string = "hw_mode=ad";
-		if (iface_params.hwModeParams.enableEdmg) {
-			enable_edmg_as_string = "enable_edmg=1";
-			edmg_channel_as_string = StringPrintf(
-				"edmg_channel=%d",
-				channelParams.channel);
-		}
-		is_60Ghz_used = true;
-	} else if ((band & IHostapd::BandMask::BAND_2_GHZ) != 0) {
-		if (((band & IHostapd::BandMask::BAND_5_GHZ) != 0)
-		    || ((band & IHostapd::BandMask::BAND_6_GHZ) != 0)) {
-			hw_mode_as_string = "hw_mode=any";
-			if (iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC) {
-				ht_cap_vht_oper_chwidth_as_string =
-				    "ht_capab=[HT40+]\n"
-				    "vht_oper_chwidth=1";
-			}
-		} else {
-			hw_mode_as_string = "hw_mode=g";
-		}
-	} else if (((band & IHostapd::BandMask::BAND_5_GHZ) != 0)
-		    || ((band & IHostapd::BandMask::BAND_6_GHZ) != 0)) {
-			hw_mode_as_string = "hw_mode=a";
-		if (iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC) {
-			ht_cap_vht_oper_chwidth_as_string =
-			    "ht_capab=[HT40+]\n"
-			    "vht_oper_chwidth=1";
-		}
-	} else {
-		wpa_printf(MSG_ERROR, "Invalid band");
-		return "";
-	}
-
-	std::string he_params_as_string;
-#ifdef CONFIG_IEEE80211AX
-	if (iface_params.V1_2.hwModeParams.enable80211AX && !is_60Ghz_used) {
-		he_params_as_string = StringPrintf(
-		    "ieee80211ax=1\n"
-		    "he_oper_chwidth=1\n"
-		    "he_su_beamformer=%d\n"
-		    "he_su_beamformee=%d\n"
-		    "he_mu_beamformer=%d\n"
-		    "he_twt_required=%d\n",
-		    iface_params.V1_2.hwModeParams.enableHeSingleUserBeamformer ? 1 : 0,
-		    iface_params.V1_2.hwModeParams.enableHeSingleUserBeamformee ? 1 : 0,
-		    iface_params.V1_2.hwModeParams.enableHeMultiUserBeamformer ? 1 : 0,
-		    iface_params.V1_2.hwModeParams.enableHeTargetWakeTime ? 1 : 0);
-	} else {
-		he_params_as_string = "ieee80211ax=0";
-	}
-#endif /* CONFIG_IEEE80211AX */
-
-#ifdef CONFIG_INTERWORKING
-	std::string access_network_params_as_string;
-	if (nw_params.isMetered) {
-		access_network_params_as_string = StringPrintf(
-		    "interworking=1\n"
-		    "access_network_type=2\n"); // CHARGEABLE_PUBLIC_NETWORK
-	} else {
-	    access_network_params_as_string = StringPrintf(
-		    "interworking=0\n");
-	}
-#endif /* CONFIG_INTERWORKING */
-
-	std::string bridge_as_string;
-	if (!br_name.empty()) {
-		bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
-	}
-
-	return StringPrintf(
-	    "interface=%s\n"
-	    "driver=nl80211\n"
-	    "ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
-	    // ssid2 signals to hostapd that the value is not a literal value
-	    // for use as a SSID.  In this case, we're giving it a hex
-	    // std::string and hostapd needs to expect that.
-	    "ssid2=%s\n"
-	    "%s\n"
-	    "ieee80211n=%d\n"
-	    "ieee80211ac=%d\n"
-	    "%s\n"
-	    "%s\n"
-	    "%s\n"
-	    "ignore_broadcast_ssid=%d\n"
-	    "wowlan_triggers=any\n"
-#ifdef CONFIG_INTERWORKING
-	    "%s\n"
-#endif /* CONFIG_INTERWORKING */
-	    "%s\n"
-	    "%s\n"
-	    "%s\n"
-	    "%s\n",
-	    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str(), ssid_as_string.c_str(),
-	    channel_config_as_string.c_str(),
-	    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211N ? 1 : 0,
-	    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC ? 1 : 0,
-	    he_params_as_string.c_str(),
-	    hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
-	    nw_params.V1_2.V1_0.isHidden ? 1 : 0,
-#ifdef CONFIG_INTERWORKING
-	    access_network_params_as_string.c_str(),
-#endif /* CONFIG_INTERWORKING */
-	    encryption_config_as_string.c_str(),
-	    bridge_as_string.c_str(),
-	    enable_edmg_as_string.c_str(),
-	    edmg_channel_as_string.c_str());
-}
-
-Generation getGeneration(hostapd_hw_modes *current_mode)
-{
-	wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d,"
-		   " vht_enabled=%d, he_supported=%d",
-		   current_mode->mode, current_mode->ht_capab != 0,
-		   current_mode->vht_capab != 0, current_mode->he_capab->he_supported);
-	switch (current_mode->mode) {
-	case HOSTAPD_MODE_IEEE80211B:
-		return Generation::WIFI_STANDARD_LEGACY;
-	case HOSTAPD_MODE_IEEE80211G:
-		return current_mode->ht_capab == 0 ?
-		       Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
-	case HOSTAPD_MODE_IEEE80211A:
-		if (current_mode->he_capab->he_supported) {
-			return Generation::WIFI_STANDARD_11AX;
-		}
-		return current_mode->vht_capab == 0 ?
-		       Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
-	case HOSTAPD_MODE_IEEE80211AD:
-		return Generation::WIFI_STANDARD_11AD;
-	default:
-		return Generation::WIFI_STANDARD_UNKNOWN;
-	}
-}
-
-Bandwidth getBandwidth(struct hostapd_config *iconf)
-{
-	wpa_printf(MSG_DEBUG, "getBandwidth %d, isHT=%d, isHT40=%d",
-		   iconf->vht_oper_chwidth, iconf->ieee80211n,
-		   iconf->secondary_channel);
-	switch (iconf->vht_oper_chwidth) {
-	case CHANWIDTH_80MHZ:
-		return Bandwidth::WIFI_BANDWIDTH_80;
-	case CHANWIDTH_80P80MHZ:
-		return Bandwidth::WIFI_BANDWIDTH_80P80;
-		break;
-	case CHANWIDTH_160MHZ:
-		return Bandwidth::WIFI_BANDWIDTH_160;
-		break;
-	case CHANWIDTH_USE_HT:
-		if (iconf->ieee80211n) {
-			return iconf->secondary_channel != 0 ?
-				Bandwidth::WIFI_BANDWIDTH_40 : Bandwidth::WIFI_BANDWIDTH_20;
-		}
-		return Bandwidth::WIFI_BANDWIDTH_20_NOHT;
-	case CHANWIDTH_2160MHZ:
-		return Bandwidth::WIFI_BANDWIDTH_2160;
-	case CHANWIDTH_4320MHZ:
-		return Bandwidth::WIFI_BANDWIDTH_4320;
-	case CHANWIDTH_6480MHZ:
-		return Bandwidth::WIFI_BANDWIDTH_6480;
-	case CHANWIDTH_8640MHZ:
-		return Bandwidth::WIFI_BANDWIDTH_8640;
-	default:
-		return Bandwidth::WIFI_BANDWIDTH_INVALID;
-	}
-}
-
-bool forceStaDisconnection(struct hostapd_data* hapd,
-			   const std::array<uint8_t, 6>& client_address,
-			   const uint16_t reason_code) {
-	struct sta_info *sta;
-	for (sta = hapd->sta_list; sta; sta = sta->next) {
-		int res;
-		res = memcmp(sta->addr, client_address.data(), ETH_ALEN);
-		if (res == 0) {
-			wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
-			    MAC2STR(client_address.data()), reason_code);
-			ap_sta_disconnect(hapd, sta, sta->addr, reason_code);
-			return true;
-		}
-	}
-	return false;
-}
-
-// hostapd core functions accept "C" style function pointers, so use global
-// functions to pass to the hostapd core function and store the corresponding
-// std::function methods to be invoked.
-//
-// NOTE: Using the pattern from the vendor HAL (wifi_legacy_hal.cpp).
-//
-// Callback to be invoked once setup is complete
-std::function<void(struct hostapd_data*)> on_setup_complete_internal_callback;
-void onAsyncSetupCompleteCb(void* ctx)
-{
-	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
-	if (on_setup_complete_internal_callback) {
-		on_setup_complete_internal_callback(iface_hapd);
-		// Invalidate this callback since we don't want this firing
-		// again in single AP mode.
-		if (strlen(iface_hapd->conf->bridge) > 0) {
-		    on_setup_complete_internal_callback = nullptr;
-		}
-	}
-}
-
-// Callback to be invoked on hotspot client connection/disconnection
-std::function<void(struct hostapd_data*, const u8 *mac_addr, int authorized,
-		   const u8 *p2p_dev_addr)> on_sta_authorized_internal_callback;
-void onAsyncStaAuthorizedCb(void* ctx, const u8 *mac_addr, int authorized,
-			    const u8 *p2p_dev_addr)
-{
-	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
-	if (on_sta_authorized_internal_callback) {
-		on_sta_authorized_internal_callback(iface_hapd, mac_addr,
-			authorized, p2p_dev_addr);
-	}
-}
-
-std::function<void(struct hostapd_data*, int level,
-                   enum wpa_msg_type type, const char *txt,
-                   size_t len)> on_wpa_msg_internal_callback;
-
-void onAsyncWpaEventCb(void *ctx, int level,
-                   enum wpa_msg_type type, const char *txt,
-                   size_t len)
-{
-	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
-	if (on_wpa_msg_internal_callback) {
-		on_wpa_msg_internal_callback(iface_hapd, level,
-					       type, txt, len);
-	}
-}
-
-
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace hostapd {
-namespace V1_3 {
-namespace implementation {
-using hidl_return_util::call;
-using namespace android::hardware::wifi::hostapd::V1_0;
-
-Hostapd::Hostapd(struct hapd_interfaces* interfaces)
-    : interfaces_(interfaces), death_notifier_(sp<DeathNotifier>::make())
-{}
-
-Return<void> Hostapd::addAccessPoint(
-    const V1_0::IHostapd::IfaceParams& iface_params,
-    const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::addAccessPointInternal, _hidl_cb, iface_params,
-	    nw_params);
-}
-
-Return<void> Hostapd::addAccessPoint_1_1(
-    const V1_1::IHostapd::IfaceParams& iface_params,
-    const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::addAccessPointInternal_1_1, _hidl_cb, iface_params,
-	    nw_params);
-}
-
-Return<void> Hostapd::addAccessPoint_1_2(
-    const V1_2::IHostapd::IfaceParams& iface_params,
-    const V1_2::IHostapd::NetworkParams& nw_params,
-    addAccessPoint_1_2_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::addAccessPointInternal_1_2, _hidl_cb, iface_params,
-	    nw_params);
-}
-
-Return<void> Hostapd::addAccessPoint_1_3(
-    const V1_3::IHostapd::IfaceParams& iface_params,
-    const V1_3::IHostapd::NetworkParams& nw_params,
-    addAccessPoint_1_3_cb _hidl_cb)
-{
-        return call(
-            this, &Hostapd::addAccessPointInternal_1_3, _hidl_cb, iface_params,
-            nw_params);
-}
-
-Return<void> Hostapd::removeAccessPoint(
-    const hidl_string& iface_name, removeAccessPoint_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::removeAccessPointInternal, _hidl_cb, iface_name);
-}
-
-Return<void> Hostapd::terminate()
-{
-	wpa_printf(MSG_INFO, "Terminating...");
-	// Clear the callback to avoid IPCThreadState shutdown during the
-	// callback event.
-	callbacks_.clear();
-	eloop_terminate();
-	return Void();
-}
-
-Return<void> Hostapd::registerCallback(
-    const sp<V1_1::IHostapdCallback>& callback, registerCallback_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::registerCallbackInternal, _hidl_cb, callback);
-}
-
-Return<void> Hostapd::registerCallback_1_3(
-    const sp<V1_3::IHostapdCallback>& callback, registerCallback_1_3_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::registerCallbackInternal_1_3, _hidl_cb, callback);
-}
-
-Return<void> Hostapd::forceClientDisconnect(
-    const hidl_string& iface_name, const hidl_array<uint8_t, 6>& client_address,
-    V1_2::Ieee80211ReasonCode reason_code, forceClientDisconnect_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::forceClientDisconnectInternal, _hidl_cb, iface_name,
-	    client_address, reason_code);
-}
-
-Return<void> Hostapd::setDebugParams(
-     V1_2::DebugLevel level, setDebugParams_cb _hidl_cb)
-{
-	return call(
-	    this, &Hostapd::setDebugParamsInternal, _hidl_cb, level);
-}
-
-V1_0::HostapdStatus Hostapd::addAccessPointInternal(
-    const V1_0::IHostapd::IfaceParams& iface_params,
-    const V1_0::IHostapd::NetworkParams& nw_params)
-{
-	return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_0::HostapdStatus Hostapd::addAccessPointInternal_1_1(
-    const V1_1::IHostapd::IfaceParams& iface_params,
-    const V1_1::IHostapd::NetworkParams& nw_params)
-{
-	return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_2(
-    const V1_2::IHostapd::IfaceParams& iface_params,
-    const V1_2::IHostapd::NetworkParams& nw_params) {
-	return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_3(
-    const V1_3::IHostapd::IfaceParams& iface_params,
-    const V1_3::IHostapd::NetworkParams& nw_params)
-{
-	int channelParamsListSize = iface_params.channelParamsList.size();
-	if (channelParamsListSize == 1) {
-		// Single AP
-		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
-		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
-		return addSingleAccessPoint(iface_params, iface_params.channelParamsList[0],
-		    nw_params, "");
-	} else if (channelParamsListSize == 2) {
-		// Concurrent APs
-		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
-		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
-		return addConcurrentAccessPoints(iface_params, nw_params);
-	}
-	return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
-}
-
-V1_2::HostapdStatus Hostapd::addConcurrentAccessPoints(
-    const V1_3::IHostapd::IfaceParams& iface_params, const V1_3::IHostapd::NetworkParams& nw_params)
-{
-	int channelParamsListSize = iface_params.channelParamsList.size();
-	// Get available interfaces in bridge
-	std::vector<std::string> managed_interfaces;
-	std::string br_name = StringPrintf(
-	    "%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
-	if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
-		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
-		    "Get interfaces in bridge failed."};
-	}
-	if (managed_interfaces.size() < channelParamsListSize) {
-		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
-		    "Available interfaces less than requested bands"};
-	}
-	// start BSS on specified bands
-	for (std::size_t i = 0; i < channelParamsListSize; i ++) {
-		V1_3::IHostapd::IfaceParams iface_params_new = iface_params;
-		iface_params_new.V1_2.V1_1.V1_0.ifaceName = managed_interfaces[i];
-		V1_2::HostapdStatus status = addSingleAccessPoint(
-		    iface_params_new, iface_params.channelParamsList[i], nw_params, br_name);
-		if (status.code != V1_2::HostapdStatusCode::SUCCESS) {
-			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
-				   managed_interfaces[i].c_str());
-			return status;
-		}
-	}
-	// Save bridge interface info
-	br_interfaces_[br_name] = managed_interfaces;
-	return {V1_2::HostapdStatusCode::SUCCESS, ""};
-}
-
-V1_2::HostapdStatus Hostapd::addSingleAccessPoint(
-    const V1_3::IHostapd::IfaceParams& iface_params,
-    const V1_3::IHostapd::ChannelParams& channelParams,
-    const V1_3::IHostapd::NetworkParams& nw_params,
-    const std::string br_name)
-{
-	if (hostapd_get_iface(interfaces_, iface_params.V1_2.V1_1.V1_0.ifaceName.c_str())) {
-		wpa_printf(
-		    MSG_ERROR, "Interface %s already present",
-		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
-		return {V1_2::HostapdStatusCode::FAILURE_IFACE_EXISTS, ""};
-	}
-	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params, br_name);
-	if (conf_params.empty()) {
-		wpa_printf(MSG_ERROR, "Failed to create config params");
-		return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	const auto conf_file_path =
-	    WriteHostapdConfig(iface_params.V1_2.V1_1.V1_0.ifaceName, conf_params);
-	if (conf_file_path.empty()) {
-		wpa_printf(MSG_ERROR, "Failed to write config file");
-		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	std::string add_iface_param_str = StringPrintf(
-	    "%s config=%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str(),
-	    conf_file_path.c_str());
-	std::vector<char> add_iface_param_vec(
-	    add_iface_param_str.begin(), add_iface_param_str.end() + 1);
-	if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
-		wpa_printf(
-		    MSG_ERROR, "Adding interface %s failed",
-		    add_iface_param_str.c_str());
-		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	struct hostapd_data* iface_hapd =
-	    hostapd_get_iface(interfaces_, iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
-	WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
-	// Register the setup complete callbacks
-	on_setup_complete_internal_callback =
-	    [this](struct hostapd_data* iface_hapd) {
-		    wpa_printf(
-			MSG_INFO, "AP interface setup completed - state %s",
-			hostapd_state_text(iface_hapd->iface->state));
-		    if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
-			    // Invoke the failure callback on all registered
-			    // clients.
-			    for (const auto& callback : callbacks_) {
-				callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
-					iface_hapd->conf->bridge : iface_hapd->conf->iface);
-			    }
-		    }
-	    };
-
-	// Rgegister for new client connect/disconnect indication.
-	on_sta_authorized_internal_callback =
-	    [this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
-		   int authorized, const u8 *p2p_dev_addr) {
-		wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
-			   MAC2STR(mac_addr),
-			   (authorized) ? "Connected" : "Disconnected");
-		for (const auto &callback : callbacks_) {
-		    callback->onConnectedClientsChanged(strlen(iface_hapd->conf->bridge) > 0 ?
-			    iface_hapd->conf->bridge : iface_hapd->conf->iface,
-			    iface_hapd->conf->iface, mac_addr, authorized);
-		}
-	    };
-
-	// Register for wpa_event which used to get channel switch event
-	on_wpa_msg_internal_callback =
-	    [this](struct hostapd_data* iface_hapd, int level,
-		   enum wpa_msg_type type, const char *txt,
-		   size_t len) {
-		wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
-		if (os_strncmp(txt, AP_EVENT_ENABLED,
-			       strlen(AP_EVENT_ENABLED)) == 0 ||
-		    os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
-			       strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
-		    for (const auto &callback : callbacks_) {
-			callback->onApInstanceInfoChanged(
-				strlen(iface_hapd->conf->bridge) > 0 ?
-				iface_hapd->conf->bridge : iface_hapd->conf->iface,
-				iface_hapd->conf->iface, iface_hapd->iface->freq,
-				getBandwidth(iface_hapd->iconf),
-				getGeneration(iface_hapd->iface->current_mode),
-				iface_hapd->own_addr);
-		    }
-		}
-		else if (os_strncmp(txt, AP_EVENT_DISABLED,
-			 strlen(AP_EVENT_DISABLED)) == 0) {
-		    // Invoke the failure callback on all registered clients.
-		    for (const auto& callback : callbacks_) {
-			    callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
-			        iface_hapd->conf->bridge : iface_hapd->conf->iface);
-		    }
-		}
-	};
-
-	// Setup callback
-	iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
-	iface_hapd->setup_complete_cb_ctx = iface_hapd;
-	iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
-	iface_hapd->sta_authorized_cb_ctx = iface_hapd;
-	wpa_msg_register_cb(onAsyncWpaEventCb);
-
-	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
-		wpa_printf(
-		    MSG_ERROR, "Enabling interface %s failed",
-		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
-		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {V1_2::HostapdStatusCode::SUCCESS, ""};
-}
-
-V1_0::HostapdStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
-{
-	// interfaces to be removed
-	std::vector<std::string> interfaces;
-	bool is_error = false;
-
-	const auto it = br_interfaces_.find(iface_name);
-	if (it != br_interfaces_.end()) {
-		// In case bridge, remove managed interfaces
-		interfaces = it->second;
-		br_interfaces_.erase(iface_name);
-	} else {
-		// else remove current interface
-		interfaces.push_back(iface_name);
-	}
-
-	for (auto& iface : interfaces) {
-		std::vector<char> remove_iface_param_vec(
-		    iface.begin(), iface.end() + 1);
-		if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <
-		    0) {
-			wpa_printf(MSG_INFO, "Remove interface %s failed",
-			    iface.c_str());
-			is_error = true;
-		}
-	}
-	if (is_error) {
-		return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {V1_0::HostapdStatusCode::SUCCESS, ""};
-}
-
-V1_0::HostapdStatus Hostapd::registerCallbackInternal(
-    const sp<V1_1::IHostapdCallback>& callback)
-{
-	return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::registerCallbackInternal_1_3(
-    const sp<V1_3::IHostapdCallback>& callback)
-{
-	if (!callback->linkToDeath(death_notifier_, 0)) {
-		wpa_printf(
-		    MSG_ERROR,
-		    "Error registering for death notification for "
-		    "hostapd callback object");
-		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	callbacks_.push_back(callback);
-	return {V1_2::HostapdStatusCode::SUCCESS, ""};
-}
-
-V1_2::HostapdStatus Hostapd::forceClientDisconnectInternal(const std::string& iface_name,
-    const std::array<uint8_t, 6>& client_address, V1_2::Ieee80211ReasonCode reason_code)
-{
-	struct hostapd_data *hapd = hostapd_get_iface(interfaces_, iface_name.c_str());
-	bool result;
-	if (!hapd) {
-	    for (auto const& iface : br_interfaces_) {
-		if (iface.first == iface_name) {
-		    for (auto const& instance : iface.second) {
-			hapd = hostapd_get_iface(interfaces_, instance.c_str());
-			if (hapd) {
-				result = forceStaDisconnection(hapd, client_address,
-							       (uint16_t) reason_code);
-				if (result) break;
-			}
-		    }
-		}
-	    }
-	} else {
-		result = forceStaDisconnection(hapd, client_address, (uint16_t) reason_code);
-	}
-	if (!hapd) {
-		wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
-		return {V1_2::HostapdStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-	if (result) {
-		return {V1_2::HostapdStatusCode::SUCCESS, ""};
-	}
-	return {V1_2::HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, ""};
-}
-
-V1_2::HostapdStatus Hostapd::setDebugParamsInternal(V1_2::DebugLevel level)
-{
-	wpa_debug_level = static_cast<uint32_t>(level);
-	return {V1_2::HostapdStatusCode::SUCCESS, ""};
-}
-
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace hostapd
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/hostapd/hidl/1.3/hostapd.h b/hostapd/hidl/1.3/hostapd.h
deleted file mode 100644
index dc45932..0000000
--- a/hostapd/hidl/1.3/hostapd.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * hidl interface for wpa_hostapd daemon
- * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef HOSTAPD_HIDL_SUPPLICANT_H
-#define HOSTAPD_HIDL_SUPPLICANT_H
-
-#include <string>
-
-#include <android-base/macros.h>
-
-#include <android/hardware/wifi/hostapd/1.3/IHostapd.h>
-#include <android/hardware/wifi/hostapd/1.3/IHostapdCallback.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/eloop.h"
-#include "utils/includes.h"
-#include "utils/wpa_debug.h"
-#include "ap/hostapd.h"
-#include "ap/sta_info.h"
-}
-
-class DeathNotifier : public android::hardware::hidl_death_recipient
-{
-public:
-	void serviceDied(
-	    uint64_t /*cookie*/,
-	    const android::wp<android::hidl::base::V1_0::IBase>
-		& /* who */) override
-	{
-		wpa_printf(MSG_ERROR, "Client died. Terminating...");
-		eloop_terminate();
-	}
-};
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace hostapd {
-namespace V1_3 {
-namespace implementation {
-using namespace android::hardware::wifi::hostapd::V1_0;
-
-/**
- * Implementation of the hostapd hidl object. This hidl
- * object is used core for global control operations on
- * hostapd.
- */
-class Hostapd : public V1_3::IHostapd
-{
-public:
-	Hostapd(hapd_interfaces* interfaces);
-	~Hostapd() override = default;
-
-	// Hidl methods exposed.
-	Return<void> addAccessPoint(
-	    const V1_0::IHostapd::IfaceParams& iface_params,
-	    const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb) override;
-	Return<void> addAccessPoint_1_1(
-	    const V1_1::IHostapd::IfaceParams& iface_params,
-	    const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb) override;
-	Return<void> addAccessPoint_1_2(
-	    const V1_2::IHostapd::IfaceParams& iface_params,
-	    const V1_2::IHostapd::NetworkParams& nw_params,
-	    addAccessPoint_1_2_cb _hidl_cb) override;
-	Return<void> addAccessPoint_1_3(
-	    const V1_3::IHostapd::IfaceParams& iface_params,
-	    const V1_3::IHostapd::NetworkParams& nw_params,
-	    addAccessPoint_1_3_cb _hidl_cb) override;
-	Return<void> removeAccessPoint(
-	    const hidl_string& iface_name,
-	    removeAccessPoint_cb _hidl_cb) override;
-	Return<void> terminate() override;
-	Return<void> registerCallback(
-	    const sp<V1_1::IHostapdCallback>& callback,
-	    registerCallback_cb _hidl_cb) override;
-	Return<void> registerCallback_1_3(
-	    const sp<V1_3::IHostapdCallback>& callback,
-	    registerCallback_1_3_cb _hidl_cb) override;
-	Return<void>forceClientDisconnect(
-	    const hidl_string& iface_name,
-	    const hidl_array<uint8_t, 6>& client_address,
-	    V1_2::Ieee80211ReasonCode reason_code, forceClientDisconnect_cb _hidl_cb) override;
-	Return<void> setDebugParams(
-	    V1_2::DebugLevel level, setDebugParams_cb _hidl_cb) override;
-private:
-	// Corresponding worker functions for the HIDL methods.
-	V1_0::HostapdStatus addAccessPointInternal(
-	    const V1_0::IHostapd::IfaceParams& iface_params,
-	    const V1_0::IHostapd::NetworkParams& nw_params);
-	V1_0::HostapdStatus addAccessPointInternal_1_1(
-	    const V1_1::IHostapd::IfaceParams& IfaceParams,
-	    const V1_0::IHostapd::NetworkParams& nw_params);
-	V1_2::HostapdStatus addAccessPointInternal_1_2(
-	    const V1_2::IHostapd::IfaceParams& IfaceParams,
-	    const V1_2::IHostapd::NetworkParams& nw_params);
-	V1_2::HostapdStatus addAccessPointInternal_1_3(
-	    const V1_3::IHostapd::IfaceParams& IfaceParams,
-	    const V1_3::IHostapd::NetworkParams& nw_params);
-	V1_2::HostapdStatus addSingleAccessPoint(
-	    const V1_3::IHostapd::IfaceParams& IfaceParams,
-	    const V1_3::IHostapd::ChannelParams& channelParams,
-	    const V1_3::IHostapd::NetworkParams& nw_params,
-	    std::string br_name);
-	V1_2::HostapdStatus addConcurrentAccessPoints(
-	    const V1_3::IHostapd::IfaceParams& IfaceParams,
-	    const V1_3::IHostapd::NetworkParams& nw_params);
-	V1_0::HostapdStatus removeAccessPointInternal(const std::string& iface_name);
-	V1_0::HostapdStatus registerCallbackInternal(
-	    const sp<V1_1::IHostapdCallback>& callback);
-	V1_2::HostapdStatus registerCallbackInternal_1_3(
-	    const sp<V1_3::IHostapdCallback>& callback);
-	V1_2::HostapdStatus forceClientDisconnectInternal(
-	    const std::string& iface_name,
-	    const std::array<uint8_t, 6>& client_address,
-	    V1_2::Ieee80211ReasonCode reason_code);
-	V1_2::HostapdStatus setDebugParamsInternal(V1_2::DebugLevel level);
-	// Raw pointer to the global structure maintained by the core.
-	struct hapd_interfaces* interfaces_;
-	// Callbacks registered.
-	std::vector<sp<V1_3::IHostapdCallback>> callbacks_;
-	// Death notifier.
-	android::sp<DeathNotifier> death_notifier_;
-	// Bridge and its managed interfaces.
-	std::map<std::string, std::vector<std::string>> br_interfaces_;
-	DISALLOW_COPY_AND_ASSIGN(Hostapd);
-};
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace hostapd
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // HOSTAPD_HIDL_SUPPLICANT_H
diff --git a/hostapd/hlr_auc_gw.milenage_db b/hostapd/hlr_auc_gw.milenage_db
index c156a29..a250653 100644
--- a/hostapd/hlr_auc_gw.milenage_db
+++ b/hostapd/hlr_auc_gw.milenage_db
@@ -3,7 +3,7 @@
 # 4.3.20 Test Set 20. SQN is the last used SQN value.
 # These values can be used for both UMTS (EAP-AKA) and GSM (EAP-SIM)
 # authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
-# dummy values will need to be included in this file.
+# stub values will need to be included in this file.
 
 # IMSI Ki OPc AMF SQN [RES_len]
 232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
diff --git a/hostapd/hostapd.android.rc b/hostapd/hostapd.android.rc
index 7cc45bd..4b6b17b 100644
--- a/hostapd/hostapd.android.rc
+++ b/hostapd/hostapd.android.rc
@@ -12,10 +12,7 @@
     mkdir /data/vendor/wifi/hostapd/sockets 0770 wifi wifi
 
 service hostapd /vendor/bin/hw/hostapd
-    interface android.hardware.wifi.hostapd@1.0::IHostapd default
-    interface android.hardware.wifi.hostapd@1.1::IHostapd default
-    interface android.hardware.wifi.hostapd@1.2::IHostapd default
-    interface android.hardware.wifi.hostapd@1.3::IHostapd default
+    interface aidl android.hardware.wifi.hostapd.IHostapd/default
     class main
     capabilities NET_ADMIN NET_RAW
     user wifi
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index a3d28ef..3c2019f 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -171,7 +171,7 @@
 #op_class=131
 
 # ACS tuning - Automatic Channel Selection
-# See: http://wireless.kernel.org/en/users/Documentation/acs
+# See: https://wireless.wiki.kernel.org/en/users/documentation/acs
 #
 # You can customize the ACS survey algorithm with following variables:
 #
@@ -225,6 +225,10 @@
 # Default behavior is to include all PSC and non-PSC channels.
 #acs_exclude_6ghz_non_psc=1
 
+# Set minimum permitted max TX power (in dBm) for ACS and DFS channel selection.
+# (default 0, i.e., not constraint)
+#min_tx_power=20
+
 # Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
 beacon_int=100
 
@@ -831,12 +835,27 @@
 # 1 = required
 #he_twt_required=0
 
+#he_twt_responder: Whether TWT (HE) responder is enabled
+# 0 = disabled
+# 1 = enabled if supported by the driver (default)
+#he_twt_responder=1
+
 #he_rts_threshold: Duration of STA transmission
 # 0 = not set (default)
 # unsigned integer = duration in units of 16 us
 #he_rts_threshold=0
 
+#he_er_su_disable: Disable 242-tone HE ER SU PPDU reception by the AP
+# 0 = enable reception (default)
+# 1 = disable reception
+#he_er_su_disable=0
+
 # HE operating channel information; see matching vht_* parameters for details.
+# he_oper_centr_freq_seg0_idx field is used to indicate center frequency of 80
+# and 160 MHz bandwidth operation. In 80+80 MHz operation, it is the center
+# frequency of the lower frequency segment. he_oper_centr_freq_seg1_idx field
+# is used only with 80+80 MHz bandwidth operation and it is used to transmit
+# the center frequency of the second segment.
 # On the 6 GHz band the center freq calculation starts from 5.950 GHz offset.
 # For example idx=3 would result in 5965 MHz center frequency. In addition,
 # he_oper_chwidth is ignored, and the channel width is derived from the
@@ -877,18 +896,31 @@
 #he_mu_edca_ac_vo_timer=255
 
 # Spatial Reuse Parameter Set
+#
+# SR Control field value
+# B0 = PSR Disallowed
+# B1 = Non-SRG OBSS PD SR Disallowed
+# B2 = Non-SRG Offset Present
+# B3 = SRG Information Present
+# B4 = HESIGA_Spatial_reuse_value15_allowed
 #he_spr_sr_control
+#
+# Non-SRG OBSS PD Max Offset (included if he_spr_sr_control B2=1)
 #he_spr_non_srg_obss_pd_max_offset
+
+# SRG OBSS PD Min Offset (included if he_spr_sr_control B3=1)
 #he_spr_srg_obss_pd_min_offset
+#
+# SRG OBSS PD Max Offset (included if he_spr_sr_control B3=1)
 #he_spr_srg_obss_pd_max_offset
 #
-# SPR SRG BSS Color
+# SPR SRG BSS Color (included if he_spr_sr_control B3=1)
 # This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter
 # Set element that indicates the BSS color values used by members of the
 # SRG of which the transmitting STA is a member. The value is in range of 0-63.
 #he_spr_srg_bss_colors=1 2 10 63
 #
-# SPR SRG Partial BSSID
+# SPR SRG Partial BSSID (included if he_spr_sr_control B3=1)
 # This config represents SRG Partial BSSID Bitmap field of Spatial Reuse
 # Parameter Set element that indicates the Partial BSSID values used by members
 # of the SRG of which the transmitting STA is a member. The value range
@@ -1381,6 +1413,12 @@
 # used, e.g., when the device has multiple IP addresses.
 #radius_client_addr=127.0.0.1
 
+# RADIUS client forced local interface. Helps run properly with VRF
+# Default is none set which allows the network stack to pick the appropriate
+# interface automatically.
+# Example below binds to eth0
+#radius_client_dev=eth0
+
 # RADIUS authentication server
 #auth_server_addr=127.0.0.1
 #auth_server_port=1812
@@ -1803,7 +1841,7 @@
 #assoc_sa_query_retry_timeout=201
 
 # ocv: Operating Channel Validation
-# This is a countermeasure against multi-channel man-in-the-middle attacks.
+# This is a countermeasure against multi-channel on-path attacks.
 # Enabling this depends on the driver's support for OCV when the driver SME is
 # used. If hostapd SME is used, this will be enabled just based on this
 # configuration.
@@ -1880,7 +1918,8 @@
 # SAE threshold for anti-clogging mechanism (dot11RSNASAEAntiCloggingThreshold)
 # This parameter defines how many open SAE instances can be in progress at the
 # same time before the anti-clogging mechanism is taken into use.
-#sae_anti_clogging_threshold=5
+#sae_anti_clogging_threshold=5 (deprecated)
+#anti_clogging_threshold=5
 
 # Maximum number of SAE synchronization errors (dot11RSNASAESync)
 # The offending SAE peer will be disconnected if more than this many
@@ -2031,6 +2070,13 @@
 # http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
 #pasn_groups=19 20 21
 
+# PASN comeback after time in TUs
+# In case the AP is temporarily unable to handle a PASN authentication exchange
+# due to a too large number of parallel operations, this value indicates to the
+# peer after how many TUs it can try the PASN exchange again.
+# (default: 10 TUs)
+#pasn_comeback_after=10
+
 ##### IEEE 802.11r configuration ##############################################
 
 # Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
@@ -2879,6 +2925,9 @@
 # that allows sending of such data. Default: 0.
 #stationary_ap=0
 
+# Enable reduced neighbor reporting (RNR)
+#rnr=0
+
 ##### Airtime policy configuration ###########################################
 
 # Set the airtime policy operating mode:
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 249e466..2609121 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1,6 +1,6 @@
 /*
  * hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -21,7 +21,7 @@
 
 static const char *const hostapd_cli_version =
 "hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi> and contributors";
 
 static struct wpa_ctrl *ctrl_conn;
 static int hostapd_cli_quit = 0;
@@ -1048,7 +1048,7 @@
 	int arg = get_cmd_arg_num(str, pos);
 	const char *fields[] = {
 #ifdef CONFIG_WPS_TESTING
-		"wps_version_number", "wps_testing_dummy_cred",
+		"wps_version_number", "wps_testing_stub_cred",
 		"wps_corrupt_pkhash",
 #endif /* CONFIG_WPS_TESTING */
 #ifdef CONFIG_INTERWORKING
@@ -1541,6 +1541,14 @@
 }
 
 
+#ifdef ANDROID
+static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return hostapd_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
+}
+#endif /* ANDROID */
+
+
 struct hostapd_cli_cmd {
 	const char *cmd;
 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
@@ -1732,6 +1740,10 @@
 	  "<addr> [req_mode=] <measurement request hexdump>  = send a Beacon report request to a station" },
 	{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
 	  "= reload wpa_psk_file only" },
+#ifdef ANDROID
+	{ "driver", hostapd_cli_cmd_driver, NULL,
+	  "<driver sub command> [<hex formatted data>] = send driver command data" },
+#endif /* ANDROID */
 	{ NULL, NULL, NULL, NULL }
 };
 
diff --git a/hostapd/main.c b/hostapd/main.c
index 346df48..d028fb5 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / main()
- * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -30,9 +30,9 @@
 #include "config_file.h"
 #include "eap_register.h"
 #include "ctrl_iface.h"
-#ifdef CONFIG_CTRL_IFACE_HIDL
-#include "hidl.h"
-#endif /* CONFIG_CTRL_IFACE_HIDL */
+#ifdef CONFIG_CTRL_IFACE_AIDL
+#include "aidl.h"
+#endif /* CONFIG_CTRL_IFACE_AIDL */
 
 struct hapd_global {
 	void **drv_priv;
@@ -456,7 +456,7 @@
 		"hostapd v%s\n"
 		"User space daemon for IEEE 802.11 AP management,\n"
 		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
-		"Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> "
+		"Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> "
 		"and contributors\n",
 		VERSION_STR);
 }
@@ -766,7 +766,7 @@
 		}
 	}
 
-#ifndef CONFIG_CTRL_IFACE_HIDL
+#ifndef CONFIG_CTRL_IFACE_AIDL
 	if (optind == argc && interfaces.global_iface_path == NULL &&
 	    num_bss_configs == 0)
 		usage();
@@ -891,12 +891,12 @@
 			goto out;
 	}
 
-#ifdef CONFIG_CTRL_IFACE_HIDL
-	if (hostapd_hidl_init(&interfaces)) {
-		wpa_printf(MSG_ERROR, "Failed to initialize HIDL interface");
+#ifdef CONFIG_CTRL_IFACE_AIDL
+	if (hostapd_aidl_init(&interfaces)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize AIDL interface");
 		goto out;
 	}
-#endif /* CONFIG_CTRL_IFACE_HIDL */
+#endif /* CONFIG_CTRL_IFACE_AIDL */
 	hostapd_global_ctrl_iface_init(&interfaces);
 
 	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
@@ -907,9 +907,9 @@
 	ret = 0;
 
  out:
-#ifdef CONFIG_CTRL_IFACE_HIDL
-	hostapd_hidl_deinit(&interfaces);
-#endif /* CONFIG_CTRL_IFACE_HIDL */
+#ifdef CONFIG_CTRL_IFACE_AIDL
+	hostapd_aidl_deinit(&interfaces);
+#endif /* CONFIG_CTRL_IFACE_AIDL */
 	hostapd_global_ctrl_iface_deinit(&interfaces);
 	/* Deinitialize all interfaces */
 	for (i = 0; i < interfaces.count; i++) {
diff --git a/src/ap/acs.c b/src/ap/acs.c
index aa2ceb0..0030edc 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -309,8 +309,6 @@
 	else if (survey->filled & SURVEY_HAS_CHAN_TIME_RX)
 		busy = survey->channel_time_rx;
 	else {
-		/* This shouldn't really happen as survey data is checked in
-		 * acs_sanity_check() */
 		wpa_printf(MSG_ERROR, "ACS: Survey data missing");
 		return 0;
 	}
@@ -372,40 +370,47 @@
 }
 
 
-static int acs_usable_ht40_chan(const struct hostapd_channel_data *chan)
+static int acs_usable_bw40_chan(const struct hostapd_channel_data *chan)
 {
-	const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149,
-				157, 184, 192 };
+	const int allowed[] = { 5180, 5220, 5260, 5300, 5500, 5540, 5580, 5620,
+				5660, 5745, 5785, 4920, 4960, 5955, 5995, 6035,
+				6075, 6115, 6155, 6195, 6235, 6275, 6315, 6355,
+				6395, 6435, 6475, 6515, 6555, 6595, 6635, 6675,
+				6715, 6755, 6795, 6835, 6875, 6915, 6955, 6995,
+				7035, 7075 };
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(allowed); i++)
-		if (chan->chan == allowed[i])
+		if (chan->freq == allowed[i])
 			return 1;
 
 	return 0;
 }
 
 
-static int acs_usable_vht80_chan(const struct hostapd_channel_data *chan)
+static int acs_usable_bw80_chan(const struct hostapd_channel_data *chan)
 {
-	const int allowed[] = { 36, 52, 100, 116, 132, 149 };
+	const int allowed[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955, 6035,
+				6115, 6195, 6275, 6355, 6435, 6515, 6595, 6675,
+				6755, 6835, 6915, 6995 };
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(allowed); i++)
-		if (chan->chan == allowed[i])
+		if (chan->freq == allowed[i])
 			return 1;
 
 	return 0;
 }
 
 
-static int acs_usable_vht160_chan(const struct hostapd_channel_data *chan)
+static int acs_usable_bw160_chan(const struct hostapd_channel_data *chan)
 {
-	const int allowed[] = { 36, 100 };
+	const int allowed[] = { 5180, 5500, 5955, 6115, 6275, 6435, 6595, 6755,
+				6915 };
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(allowed); i++)
-		if (chan->chan == allowed[i])
+		if (chan->freq == allowed[i])
 			return 1;
 
 	return 0;
@@ -541,6 +546,9 @@
 		if (!is_in_freqlist(iface, chan))
 			continue;
 
+		if (chan->max_tx_power < iface->conf->min_tx_power)
+			continue;
+
 		wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
 			   chan->chan, chan->freq);
 
@@ -668,6 +676,9 @@
 		if (!is_in_freqlist(iface, chan))
 			continue;
 
+		if (chan->max_tx_power < iface->conf->min_tx_power)
+			continue;
+
 		if (!chan_bw_allowed(chan, bw, 1, 1)) {
 			wpa_printf(MSG_DEBUG,
 				   "ACS: Channel %d: BW %u is not supported",
@@ -678,10 +689,12 @@
 		/* HT40 on 5 GHz has a limited set of primary channels as per
 		 * 11n Annex J */
 		if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
-		    iface->conf->ieee80211n &&
-		    iface->conf->secondary_channel &&
-		    !acs_usable_ht40_chan(chan)) {
-			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40",
+		    ((iface->conf->ieee80211n &&
+		      iface->conf->secondary_channel) ||
+		     is_6ghz_freq(chan->freq)) &&
+		    !acs_usable_bw40_chan(chan)) {
+			wpa_printf(MSG_DEBUG,
+				   "ACS: Channel %d: not allowed as primary channel for 40 MHz bandwidth",
 				   chan->chan);
 			continue;
 		}
@@ -690,18 +703,18 @@
 		    (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
 			if (hostapd_get_oper_chwidth(iface->conf) ==
 			    CHANWIDTH_80MHZ &&
-			    !acs_usable_vht80_chan(chan)) {
+			    !acs_usable_bw80_chan(chan)) {
 				wpa_printf(MSG_DEBUG,
-					   "ACS: Channel %d: not allowed as primary channel for VHT80",
+					   "ACS: Channel %d: not allowed as primary channel for 80 MHz bandwidth",
 					   chan->chan);
 				continue;
 			}
 
 			if (hostapd_get_oper_chwidth(iface->conf) ==
 			    CHANWIDTH_160MHZ &&
-			    !acs_usable_vht160_chan(chan)) {
+			    !acs_usable_bw160_chan(chan)) {
 				wpa_printf(MSG_DEBUG,
-					   "ACS: Channel %d: not allowed as primary channel for VHT160",
+					   "ACS: Channel %d: not allowed as primary channel for 160 MHz bandwidth",
 					   chan->chan);
 				continue;
 			}
@@ -832,6 +845,12 @@
 	u32 bw;
 	struct hostapd_hw_modes *mode;
 
+	if (is_6ghz_op_class(iface->conf->op_class)) {
+		bw = op_class_to_bandwidth(iface->conf->op_class);
+		n_chans = bw / 20;
+		goto bw_selected;
+	}
+
 	/* TODO: HT40- support */
 
 	if (iface->conf->ieee80211n &&
@@ -857,6 +876,7 @@
 
 	bw = num_chan_to_bw(n_chans);
 
+bw_selected:
 	/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
 
 	wpa_printf(MSG_DEBUG,
@@ -1033,6 +1053,9 @@
 		if (!is_in_freqlist(iface, chan))
 			continue;
 
+		if (chan->max_tx_power < iface->conf->min_tx_power)
+			continue;
+
 		*freq++ = chan->freq;
 	}
 
diff --git a/src/ap/airtime_policy.c b/src/ap/airtime_policy.c
index 1e67f0d..abe817c 100644
--- a/src/ap/airtime_policy.c
+++ b/src/ap/airtime_policy.c
@@ -79,6 +79,10 @@
 	for (sta = hapd->sta_list; sta; sta = sta->next) {
 		if (hostapd_drv_read_sta_data(hapd, &data, sta->addr))
 			continue;
+#ifdef CONFIG_TESTING_OPTIONS
+		if (hapd->force_backlog_bytes)
+			data.backlog_bytes = 1;
+#endif /* CONFIG_TESTING_OPTIONS */
 
 		if (data.backlog_bytes > 0)
 			set_new_backlog_time(hapd, sta, &now);
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index b0d8ec8..33c68d4 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -121,7 +121,7 @@
 
 	bss->radius_das_time_window = 300;
 
-	bss->sae_anti_clogging_threshold = 5;
+	bss->anti_clogging_threshold = 5;
 	bss->sae_sync = 5;
 
 	bss->gas_frag_limit = 1400;
@@ -165,6 +165,11 @@
 #ifdef CONFIG_TESTING_OPTIONS
 	bss->sae_commit_status = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
+
+#ifdef CONFIG_PASN
+	/* comeback after 10 TUs */
+	bss->pasn_comeback_after = 10;
+#endif /* CONFIG_PASN */
 }
 
 
@@ -270,7 +275,8 @@
 	conf->he_op.he_basic_mcs_nss_set = 0xfffc;
 	conf->he_op.he_bss_color_disabled = 1;
 	conf->he_op.he_bss_color_partial = 0;
-	conf->he_op.he_bss_color = 1;
+	conf->he_op.he_bss_color = os_random() % 63 + 1;
+	conf->he_op.he_twt_responder = 1;
 	conf->he_6ghz_max_mpdu = 2;
 	conf->he_6ghz_max_ampdu_len_exp = 7;
 	conf->he_6ghz_rx_ant_pat = 1;
@@ -781,6 +787,7 @@
 					   conf->radius->num_auth_servers);
 		hostapd_config_free_radius(conf->radius->acct_servers,
 					   conf->radius->num_acct_servers);
+		os_free(conf->radius->force_client_dev);
 	}
 	hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
 	hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
@@ -1418,6 +1425,15 @@
 	}
 #endif /* CONFIG_SAE_PK */
 
+#ifdef CONFIG_FILS
+	if (full_config && bss->fils_discovery_min_int &&
+	    bss->unsol_bcast_probe_resp_interval) {
+		wpa_printf(MSG_ERROR,
+			   "Cannot enable both FILS discovery and unsolicited broadcast Probe Response at the same time");
+		return -1;
+	}
+#endif /* CONFIG_FILS */
+
 	return 0;
 }
 
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index e1b17f5..c1a0f71 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -51,6 +51,7 @@
 	int dot11MeshRetryTimeout; /* msec */
 	int dot11MeshConfirmTimeout; /* msec */
 	int dot11MeshHoldingTimeout; /* msec */
+	int mesh_fwding;
 };
 
 #define MAX_STA_COUNT 2007
@@ -267,6 +268,8 @@
 	u8 addr[ETH_ALEN];
 };
 
+#define EXT_CAPA_MAX_LEN 15
+
 /**
  * struct hostapd_bss_config - Per-BSS configuration
  */
@@ -655,7 +658,7 @@
 	struct wpabuf *vendor_elements;
 	struct wpabuf *assocresp_elements;
 
-	unsigned int sae_anti_clogging_threshold;
+	unsigned int anti_clogging_threshold;
 	unsigned int sae_sync;
 	int sae_require_mfp;
 	int sae_confirm_immediate;
@@ -694,6 +697,7 @@
 
 #define MESH_ENABLED BIT(0)
 	int mesh;
+	int mesh_fwding;
 
 	u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
 
@@ -874,12 +878,26 @@
 	 * secure LTF. Allow forcing KDK derivation for testing purposes.
 	 */
 	int force_kdk_derivation;
+
+	/* If set, corrupt the MIC in the 2nd Authentication frame of PASN */
+	int pasn_corrupt_mic;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	int *pasn_groups;
+
+	/*
+	 * The time in TUs after which the non-AP STA is requested to retry the
+	 * PASN authentication in case there are too many parallel operations.
+	 */
+	u16 pasn_comeback_after;
 #endif /* CONFIG_PASN */
 
 	unsigned int unsol_bcast_probe_resp_interval;
+
+	u8 ext_capa_mask[EXT_CAPA_MAX_LEN];
+	u8 ext_capa[EXT_CAPA_MAX_LEN];
+
+	u8 rnr;
 };
 
 /**
@@ -900,7 +918,9 @@
 	u8 he_bss_color_partial;
 	u8 he_default_pe_duration;
 	u8 he_twt_required;
+	u8 he_twt_responder;
 	u16 he_rts_threshold;
+	u8 he_er_su_disable;
 	u16 he_basic_mcs_nss_set;
 };
 
@@ -935,6 +955,7 @@
 	struct wpa_freq_range_list acs_freq_list;
 	u8 acs_freq_list_present;
 	int acs_exclude_dfs;
+	u8 min_tx_power;
 	enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
 	int acs_exclude_6ghz_non_psc;
 	enum {
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index d1642d7..e917736 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -888,7 +888,8 @@
 			continue;
 		if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
 		    !(hapd->iface->conf->acs_exclude_dfs &&
-		      (chan->flag & HOSTAPD_CHAN_RADAR)))
+		      (chan->flag & HOSTAPD_CHAN_RADAR)) &&
+		    !(chan->max_tx_power < hapd->iface->conf->min_tx_power))
 			int_array_add_unique(freq_list, chan->freq);
 	}
 }
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 582ab61..61c8f64 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -393,4 +393,27 @@
 	return hapd->driver->set_band(hapd->drv_priv, band_mask);
 }
 
+#ifdef ANDROID
+static inline int hostapd_drv_driver_cmd(struct hostapd_data *hapd,
+					 char *cmd, char *buf, size_t buf_len)
+{
+	if (!hapd->driver->driver_cmd)
+		return -1;
+	return hapd->driver->driver_cmd(hapd->drv_priv, cmd, buf, buf_len);
+}
+#endif /* ANDROID */
+
+#ifdef CONFIG_TESTING_OPTIONS
+static inline int
+hostapd_drv_register_frame(struct hostapd_data *hapd, u16 type,
+			   const u8 *match, size_t match_len,
+			   bool multicast)
+{
+	if (!hapd->driver || !hapd->drv_priv || !hapd->driver->register_frame)
+		return -1;
+	return hapd->driver->register_frame(hapd->drv_priv, type, match,
+					    match_len, multicast);
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 #endif /* AP_DRV_OPS */
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 7d9e8b9..8cd1c41 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -469,6 +469,7 @@
 	}
 #endif /* CONFIG_IEEE80211AX */
 
+	buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
 	buflen += hostapd_mbo_ie_len(hapd);
 	buflen += hostapd_eid_owe_trans_len(hapd);
 	buflen += hostapd_eid_dpp_cc_len(hapd);
@@ -569,10 +570,9 @@
 		pos = hostapd_eid_txpower_envelope(hapd, pos);
 #endif /* CONFIG_IEEE80211AX */
 
-	if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
-	    (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
-		pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
+	pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
 
+	pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
 	pos = hostapd_eid_fils_indic(hapd, pos, 0);
 	pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
 
@@ -642,7 +642,8 @@
 enum ssid_match_result {
 	NO_SSID_MATCH,
 	EXACT_SSID_MATCH,
-	WILDCARD_SSID_MATCH
+	WILDCARD_SSID_MATCH,
+	CO_LOCATED_SSID_MATCH,
 };
 
 static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
@@ -653,7 +654,9 @@
 					 size_t short_ssid_list_len)
 {
 	const u8 *pos, *end;
+	struct hostapd_iface *iface = hapd->iface;
 	int wildcard = 0;
+	size_t i, j;
 
 	if (ssid_len == 0)
 		wildcard = 1;
@@ -687,7 +690,33 @@
 		}
 	}
 
-	return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
+	if (wildcard)
+		return WILDCARD_SSID_MATCH;
+
+	if (!iface->interfaces || iface->interfaces->count <= 1 ||
+	    is_6ghz_op_class(hapd->iconf->op_class))
+		return NO_SSID_MATCH;
+
+	for (i = 0; i < iface->interfaces->count; i++) {
+		struct hostapd_iface *colocated;
+
+		colocated = iface->interfaces->iface[i];
+
+		if (colocated == iface ||
+		    !is_6ghz_op_class(colocated->conf->op_class))
+			continue;
+
+		for (j = 0; j < colocated->num_bss; j++) {
+			struct hostapd_bss_config *conf;
+
+			conf = colocated->bss[j]->conf;
+			if (ssid_len == conf->ssid.ssid_len &&
+			    os_memcmp(ssid, conf->ssid.ssid, ssid_len) == 0)
+				return CO_LOCATED_SSID_MATCH;
+		}
+	}
+
+	return NO_SSID_MATCH;
 }
 
 
@@ -1284,6 +1313,8 @@
 		total_len += 3;
 	}
 
+	total_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_ACTION);
+
 	pos = hostapd_eid_fils_indic(hapd, buf, 0);
 	buf_len = pos - buf;
 	total_len += buf_len;
@@ -1352,6 +1383,8 @@
 	/* Fill in the Length field value */
 	*length_pos = pos - (length_pos + 1);
 
+	pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_ACTION);
+
 	/* FILS Indication element */
 	if (buf_len) {
 		os_memcpy(pos, buf, buf_len);
@@ -1438,6 +1471,7 @@
 	}
 #endif /* CONFIG_IEEE80211AX */
 
+	tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
 	tail_len += hostapd_mbo_ie_len(hapd);
 	tail_len += hostapd_eid_owe_trans_len(hapd);
 	tail_len += hostapd_eid_dpp_cc_len(hapd);
@@ -1558,10 +1592,9 @@
 		tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
 #endif /* CONFIG_IEEE80211AX */
 
-	if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) ||
-	    (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax))
-		tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
+	tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
 
+	tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON);
 	tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
 	tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
 
@@ -1743,7 +1776,7 @@
 }
 
 
-int ieee802_11_set_beacon(struct hostapd_data *hapd)
+static int __ieee802_11_set_beacon(struct hostapd_data *hapd)
 {
 	struct wpa_driver_ap_params params;
 	struct hostapd_freq_params freq;
@@ -1753,6 +1786,11 @@
 	struct wpabuf *beacon, *proberesp, *assocresp;
 	int res, ret = -1;
 
+	if (!hapd->drv_priv) {
+		wpa_printf(MSG_ERROR, "Interface is disabled");
+		return -1;
+	}
+
 	if (hapd->csa_in_progress) {
 		wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
 		return -1;
@@ -1827,6 +1865,42 @@
 }
 
 
+int ieee802_11_set_beacon(struct hostapd_data *hapd)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	int ret;
+	size_t i, j;
+	bool is_6g;
+
+	ret = __ieee802_11_set_beacon(hapd);
+	if (ret != 0)
+		return ret;
+
+	if (!iface->interfaces || iface->interfaces->count <= 1)
+		return 0;
+
+	/* Update Beacon frames in case of 6 GHz colocation */
+	is_6g = is_6ghz_op_class(iface->conf->op_class);
+	for (j = 0; j < iface->interfaces->count; j++) {
+		struct hostapd_iface *colocated;
+
+		colocated = iface->interfaces->iface[j];
+		if (colocated == iface || !colocated || !colocated->conf)
+			continue;
+
+		if (is_6g == is_6ghz_op_class(colocated->conf->op_class))
+			continue;
+
+		for (i = 0; i < colocated->num_bss; i++) {
+			if (colocated->bss[i] && colocated->bss[i]->started)
+				__ieee802_11_set_beacon(colocated->bss[i]);
+		}
+	}
+
+	return 0;
+}
+
+
 int ieee802_11_set_beacons(struct hostapd_iface *iface)
 {
 	size_t i;
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 28e40ba..1d8fb82 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -50,9 +50,35 @@
 }
 
 
-static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd,
-				 struct sta_info *sta,
-				 char *buf, size_t buflen)
+static int hostapd_get_sta_conn_time(struct sta_info *sta,
+				     struct hostap_sta_driver_data *data,
+				     char *buf, size_t buflen)
+{
+	struct os_reltime age;
+	unsigned long secs;
+	int ret;
+
+	if (sta->connected_time.sec) {
+		/* Locally maintained time in AP mode */
+		os_reltime_age(&sta->connected_time, &age);
+		secs = (unsigned long) age.sec;
+	} else if (data->flags & STA_DRV_DATA_CONN_TIME) {
+		/* Time from the driver in mesh mode */
+		secs = data->connected_sec;
+	} else {
+		return 0;
+	}
+
+	ret = os_snprintf(buf, buflen, "connected_time=%lu\n", secs);
+	if (os_snprintf_error(buflen, ret))
+		return 0;
+	return ret;
+}
+
+
+static int hostapd_get_sta_info(struct hostapd_data *hapd,
+				struct sta_info *sta,
+				char *buf, size_t buflen)
 {
 	struct hostap_sta_driver_data data;
 	int ret;
@@ -160,29 +186,12 @@
 			len += ret;
 	}
 
+	len += hostapd_get_sta_conn_time(sta, &data, buf + len, buflen - len);
+
 	return len;
 }
 
 
-static int hostapd_get_sta_conn_time(struct sta_info *sta,
-				     char *buf, size_t buflen)
-{
-	struct os_reltime age;
-	int ret;
-
-	if (!sta->connected_time.sec)
-		return 0;
-
-	os_reltime_age(&sta->connected_time, &age);
-
-	ret = os_snprintf(buf, buflen, "connected_time=%u\n",
-			  (unsigned int) age.sec);
-	if (os_snprintf_error(buflen, ret))
-		return 0;
-	return ret;
-}
-
-
 static const char * timeout_next_str(int val)
 {
 	switch (val) {
@@ -263,8 +272,7 @@
 	if (res >= 0)
 		len += res;
 
-	len += hostapd_get_sta_tx_rx(hapd, sta, buf + len, buflen - len);
-	len += hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
+	len += hostapd_get_sta_info(hapd, sta, buf + len, buflen - len);
 
 #ifdef CONFIG_SAE
 	if (sta->sae && sta->sae->state == SAE_ACCEPTED) {
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index b990fb3..5c99ecf 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -246,6 +246,9 @@
 			continue;
 		}
 
+		if (chan->max_tx_power < iface->conf->min_tx_power)
+			continue;
+
 		if (ret_chan && idx == channel_idx) {
 			wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
 				   chan->freq, chan->chan);
@@ -1228,7 +1231,9 @@
 {
 	int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
 
-	if (!iface->conf->ieee80211h || !iface->current_mode ||
+	if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+	     !iface->conf->ieee80211h) ||
+	    !iface->current_mode ||
 	    iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
 		return 0;
 
@@ -1279,6 +1284,8 @@
  */
 int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
 {
+	int dfs_res;
+
 	wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
 		   __func__, iface->cac_started);
 
@@ -1294,10 +1301,11 @@
 		return 1;
 	}
 
-	if (ieee80211_is_dfs(iface->freq, iface->hw_features,
-			     iface->num_hw_features)) {
-		wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS",
-			   __func__, iface->freq);
+	dfs_res = hostapd_is_dfs_required(iface);
+	if (dfs_res > 0) {
+		wpa_printf(MSG_DEBUG,
+			   "%s: freq %d MHz requires DFS for %d chans",
+			   __func__, iface->freq, dfs_res);
 		return 0;
 	}
 
diff --git a/src/ap/dhcp_snoop.c b/src/ap/dhcp_snoop.c
index edc77da..551936b 100644
--- a/src/ap/dhcp_snoop.c
+++ b/src/ap/dhcp_snoop.c
@@ -88,6 +88,7 @@
 		}
 	}
 
+#ifdef CONFIG_HS20
 	if (hapd->conf->disable_dgaf && is_broadcast_ether_addr(buf)) {
 		for (sta = hapd->sta_list; sta; sta = sta->next) {
 			if (!(sta->flags & WLAN_STA_AUTHORIZED))
@@ -96,6 +97,7 @@
 							    (u8 *) buf, len);
 		}
 	}
+#endif /* CONFIG_HS20 */
 
 	if (msgtype == DHCPACK) {
 		if (b->your_ip == 0)
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index e1e5a3a..96a13fb 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -2,6 +2,7 @@
  * hostapd / DPP integration
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -28,12 +29,16 @@
 static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
 static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
 static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
+static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
+					    struct dpp_authentication *auth);
 #ifdef CONFIG_DPP2
 static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
 						    void *timeout_ctx);
 static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
 					  struct dpp_authentication *auth,
 					  struct dpp_config_obj *conf);
+static int hostapd_dpp_process_conf_obj(void *ctx,
+					struct dpp_authentication *auth);
 #endif /* CONFIG_DPP2 */
 
 static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -216,6 +221,255 @@
 }
 
 
+static int hostapd_dpp_allow_ir(struct hostapd_data *hapd, unsigned int freq)
+{
+	int i, j;
+
+	if (!hapd->iface->hw_features)
+		return -1;
+
+	for (i = 0; i < hapd->iface->num_hw_features; i++) {
+		struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i];
+
+		for (j = 0; j < mode->num_channels; j++) {
+			struct hostapd_channel_data *chan = &mode->channels[j];
+
+			if (chan->freq != (int) freq)
+				continue;
+
+			if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+					  HOSTAPD_CHAN_NO_IR |
+					  HOSTAPD_CHAN_RADAR))
+				continue;
+
+			return 1;
+		}
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
+		   freq);
+
+	return 0;
+}
+
+
+static int hostapd_dpp_pkex_next_channel(struct hostapd_data *hapd,
+					 struct dpp_pkex *pkex)
+{
+	if (pkex->freq == 2437)
+		pkex->freq = 5745;
+	else if (pkex->freq == 5745)
+		pkex->freq = 5220;
+	else if (pkex->freq == 5220)
+		pkex->freq = 60480;
+	else
+		return -1; /* no more channels to try */
+
+	if (hostapd_dpp_allow_ir(hapd, pkex->freq) == 1) {
+		wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
+			   pkex->freq);
+		return 0;
+	}
+
+	/* Could not use this channel - try the next one */
+	return hostapd_dpp_pkex_next_channel(hapd, pkex);
+}
+
+
+#ifdef CONFIG_DPP2
+static int hostapd_dpp_pkex_done(void *ctx, void *conn,
+				 struct dpp_bootstrap_info *peer_bi)
+{
+	struct hostapd_data *hapd = ctx;
+	const char *cmd = hapd->dpp_pkex_auth_cmd;
+	const char *pos;
+	u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
+	struct dpp_bootstrap_info *own_bi = NULL;
+	struct dpp_authentication *auth;
+
+	if (!cmd)
+		cmd = "";
+	wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
+		   cmd);
+
+	pos = os_strstr(cmd, " own=");
+	if (pos) {
+		pos += 5;
+		own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
+					      atoi(pos));
+		if (!own_bi) {
+			wpa_printf(MSG_INFO,
+				   "DPP: Could not find bootstrapping info for the identified local entry");
+			return -1;
+		}
+
+		if (peer_bi->curve != own_bi->curve) {
+			wpa_printf(MSG_INFO,
+				   "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
+				   peer_bi->curve->name, own_bi->curve->name);
+			return -1;
+		}
+	}
+
+	pos = os_strstr(cmd, " role=");
+	if (pos) {
+		pos += 6;
+		if (os_strncmp(pos, "configurator", 12) == 0)
+			allowed_roles = DPP_CAPAB_CONFIGURATOR;
+		else if (os_strncmp(pos, "enrollee", 8) == 0)
+			allowed_roles = DPP_CAPAB_ENROLLEE;
+		else if (os_strncmp(pos, "either", 6) == 0)
+			allowed_roles = DPP_CAPAB_CONFIGURATOR |
+				DPP_CAPAB_ENROLLEE;
+		else
+			return -1;
+	}
+
+	auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
+			     peer_bi, own_bi, allowed_roles, 0,
+			     hapd->iface->hw_features,
+			     hapd->iface->num_hw_features);
+	if (!auth)
+		return -1;
+
+	hostapd_dpp_set_testing_options(hapd, auth);
+	if (dpp_set_configurator(auth, cmd) < 0) {
+		dpp_auth_deinit(auth);
+		return -1;
+	}
+
+	return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth,
+			    hapd->conf->dpp_name, DPP_NETROLE_AP,
+			    hostapd_dpp_process_conf_obj, NULL);
+}
+#endif /* CONFIG_DPP2 */
+
+
+enum hostapd_dpp_pkex_ver {
+	PKEX_VER_AUTO,
+	PKEX_VER_ONLY_1,
+	PKEX_VER_ONLY_2,
+};
+
+static int hostapd_dpp_pkex_init(struct hostapd_data *hapd,
+				 enum hostapd_dpp_pkex_ver ver,
+				 const struct hostapd_ip_addr *ipaddr,
+				 int tcp_port)
+{
+	struct dpp_pkex *pkex;
+	struct wpabuf *msg;
+	unsigned int wait_time;
+	bool v2 = ver != PKEX_VER_ONLY_1;
+
+	wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
+	dpp_pkex_free(hapd->dpp_pkex);
+	hapd->dpp_pkex = NULL;
+	pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
+			     hapd->dpp_pkex_identifier,
+			     hapd->dpp_pkex_code, v2);
+	if (!pkex)
+		return -1;
+	pkex->forced_ver = ver != PKEX_VER_AUTO;
+
+	if (ipaddr) {
+#ifdef CONFIG_DPP2
+		return dpp_tcp_pkex_init(hapd->iface->interfaces->dpp, pkex,
+					 ipaddr, tcp_port,
+					 hapd->msg_ctx, hapd,
+					 hostapd_dpp_pkex_done);
+#else /* CONFIG_DPP2 */
+		return -1;
+#endif /* CONFIG_DPP2 */
+	}
+
+	hapd->dpp_pkex = pkex;
+	msg = hapd->dpp_pkex->exchange_req;
+	wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
+	pkex->freq = 2437;
+	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+		" freq=%u type=%d", MAC2STR(broadcast), pkex->freq,
+		v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
+		DPP_PA_PKEX_V1_EXCHANGE_REQ);
+	hostapd_drv_send_action(hapd, pkex->freq, 0, broadcast,
+				wpabuf_head(msg), wpabuf_len(msg));
+	pkex->exch_req_wait_time = wait_time;
+	pkex->exch_req_tries = 1;
+
+	return 0;
+}
+
+
+static void hostapd_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	struct dpp_pkex *pkex = hapd->dpp_pkex;
+
+	if (!pkex || !pkex->exchange_req)
+		return;
+	if (pkex->exch_req_tries >= 5) {
+		if (hostapd_dpp_pkex_next_channel(hapd, pkex) < 0) {
+#ifdef CONFIG_DPP3
+			if (pkex->v2 && !pkex->forced_ver) {
+				wpa_printf(MSG_DEBUG,
+					   "DPP: Fall back to PKEXv1");
+				hostapd_dpp_pkex_init(hapd, PKEX_VER_ONLY_1,
+						      NULL, 0);
+				return;
+			}
+#endif /* CONFIG_DPP3 */
+			wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
+				"No response from PKEX peer");
+			dpp_pkex_free(pkex);
+			hapd->dpp_pkex = NULL;
+			return;
+		}
+		pkex->exch_req_tries = 0;
+	}
+
+	pkex->exch_req_tries++;
+	wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
+		   pkex->exch_req_tries);
+	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+		" freq=%u type=%d",
+		MAC2STR(broadcast), pkex->freq,
+		pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
+		DPP_PA_PKEX_V1_EXCHANGE_REQ);
+	hostapd_drv_send_action(hapd, pkex->freq, pkex->exch_req_wait_time,
+				broadcast,
+				wpabuf_head(pkex->exchange_req),
+				wpabuf_len(pkex->exchange_req));
+}
+
+
+static void hostapd_dpp_pkex_tx_status(struct hostapd_data *hapd, const u8 *dst,
+				       const u8 *data, size_t data_len, int ok)
+{
+	struct dpp_pkex *pkex = hapd->dpp_pkex;
+
+	if (pkex->failed) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Terminate PKEX exchange due to an earlier error");
+		if (pkex->t > pkex->own_bi->pkex_t)
+			pkex->own_bi->pkex_t = pkex->t;
+		dpp_pkex_free(pkex);
+		hapd->dpp_pkex = NULL;
+		return;
+	}
+
+	if (pkex->exch_req_wait_time && pkex->exchange_req) {
+		/* Wait for PKEX Exchange Response frame and retry request if
+		 * no response is seen. */
+		eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd,
+				     NULL);
+		eloop_register_timeout(pkex->exch_req_wait_time / 1000,
+				       (pkex->exch_req_wait_time % 1000) * 1000,
+				       hostapd_dpp_pkex_retry_timeout, hapd,
+				       NULL);
+	}
+}
+
+
 void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
 			   const u8 *data, size_t data_len, int ok)
 {
@@ -227,6 +481,11 @@
 		" result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
 
 	if (!hapd->dpp_auth) {
+		if (hapd->dpp_pkex) {
+			hostapd_dpp_pkex_tx_status(hapd, dst, data, data_len,
+						   ok);
+			return;
+		}
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Ignore TX status since there is no ongoing authentication exchange");
 		return;
@@ -664,7 +923,7 @@
 		return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
 				    &ipaddr, tcp_port, hapd->conf->dpp_name,
 				    DPP_NETROLE_AP, hapd->msg_ctx, hapd,
-				    hostapd_dpp_process_conf_obj);
+				    hostapd_dpp_process_conf_obj, NULL);
 #endif /* CONFIG_DPP2 */
 
 	hapd->dpp_auth = auth;
@@ -757,7 +1016,7 @@
 	if (!own_bi) {
 		if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
 					src, hdr, buf, len, freq, i_bootstrap,
-					r_bootstrap) == 0)
+					r_bootstrap, hapd) == 0)
 			return;
 	}
 #endif /* CONFIG_DPP2 */
@@ -915,7 +1174,8 @@
 		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
 		return;
 	}
-	if (!resp || status_code != WLAN_STATUS_SUCCESS) {
+	if (result != GAS_QUERY_AP_SUCCESS ||
+	    !resp || status_code != WLAN_STATUS_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
 		goto fail;
 	}
@@ -1189,6 +1449,7 @@
 		wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
 		eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
 				     hapd, NULL);
+		auth->waiting_conn_status_result = 1;
 		eloop_cancel_timeout(
 			hostapd_dpp_conn_status_result_wait_timeout,
 			hapd, NULL);
@@ -1274,7 +1535,7 @@
 	if (!peer_bi) {
 		if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
 					src, hdr, buf, len, freq, NULL,
-					r_bootstrap) == 0)
+					r_bootstrap, hapd) == 0)
 			return;
 		wpa_printf(MSG_DEBUG,
 			   "DPP: No matching bootstrapping information found");
@@ -1364,7 +1625,7 @@
 	if (!conf) {
 		if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
 					src, hdr, buf, len, freq, NULL,
-					NULL) == 0)
+					NULL, hapd) == 0)
 			return;
 		wpa_printf(MSG_DEBUG,
 			   "DPP: No matching Configurator information found");
@@ -1552,17 +1813,45 @@
 
 #ifdef CONFIG_TESTING_OPTIONS
 skip_connector:
+	if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
+		goto skip_proto_ver;
+	}
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_DPP2
 	if (DPP_VERSION > 1) {
+		u8 ver = DPP_VERSION;
+#ifdef CONFIG_DPP3
+		int conn_ver;
+
+		conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
+		if (conn_ver > 0 && ver != conn_ver) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: Use Connector version %d instead of current protocol version %d",
+				   conn_ver, ver);
+			ver = conn_ver;
+		}
+#endif /* CONFIG_DPP3 */
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
+		ver = 1;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 		/* Protocol Version */
 		wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
 		wpabuf_put_le16(msg, 1);
-		wpabuf_put_u8(msg, DPP_VERSION);
+		wpabuf_put_u8(msg, ver);
 	}
 #endif /* CONFIG_DPP2 */
 
+#ifdef CONFIG_TESTING_OPTIONS
+skip_proto_ver:
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
 		   " status=%d", MAC2STR(src), status);
 	wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
@@ -1646,6 +1935,28 @@
 		return;
 	}
 
+#ifdef CONFIG_DPP3
+	if (intro.peer_version && intro.peer_version >= 2) {
+		const u8 *version;
+		u16 version_len;
+		u8 attr_version = 1;
+
+		version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
+				       &version_len);
+		if (version && version_len >= 1)
+			attr_version = version[0];
+		if (attr_version != intro.peer_version) {
+			wpa_printf(MSG_INFO,
+				   "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
+				   intro.peer_version, attr_version);
+			hostapd_dpp_send_peer_disc_resp(hapd, src, freq,
+							trans_id[0],
+							DPP_STATUS_NO_MATCH);
+			return;
+		}
+	}
+#endif /* CONFIG_DPP3 */
+
 	if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
 		expire = hapd->conf->dpp_netaccesskey_expiry;
 	if (expire)
@@ -1667,8 +1978,8 @@
 
 static void
 hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
-				 const u8 *buf, size_t len,
-				 unsigned int freq)
+				 const u8 *hdr, const u8 *buf, size_t len,
+				 unsigned int freq, bool v2)
 {
 	struct wpabuf *msg;
 
@@ -1681,14 +1992,14 @@
 	if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: No PKEX code configured - ignore request");
-		return;
+		goto try_relay;
 	}
 
 	if (hapd->dpp_pkex) {
 		/* TODO: Support parallel operations */
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Already in PKEX session - ignore new request");
-		return;
+		goto try_relay;
 	}
 
 	hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
@@ -1696,11 +2007,11 @@
 						  hapd->own_addr, src,
 						  hapd->dpp_pkex_identifier,
 						  hapd->dpp_pkex_code,
-						  buf, len);
+						  buf, len, v2);
 	if (!hapd->dpp_pkex) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Failed to process the request - ignore it");
-		return;
+		goto try_relay;
 	}
 
 	msg = hapd->dpp_pkex->exchange_resp;
@@ -1717,6 +2028,17 @@
 		dpp_pkex_free(hapd->dpp_pkex);
 		hapd->dpp_pkex = NULL;
 	}
+
+	return;
+
+try_relay:
+#ifdef CONFIG_DPP2
+	if (v2)
+		dpp_relay_rx_action(hapd->iface->interfaces->dpp,
+				    src, hdr, buf, len, freq, NULL, NULL, hapd);
+#else /* CONFIG_DPP2 */
+	wpa_printf(MSG_DEBUG, "DPP: No relay functionality included - skip");
+#endif /* CONFIG_DPP2 */
 }
 
 
@@ -1738,6 +2060,9 @@
 		return;
 	}
 
+	eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
+	hapd->dpp_pkex->exch_req_wait_time = 0;
+
 	msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
 	if (!msg) {
 		wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
@@ -1890,7 +2215,8 @@
 
 #ifdef CONFIG_DPP2
 	if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
-				src, hdr, buf, len, freq, NULL, NULL) == 0)
+				src, hdr, buf, len, freq, NULL, NULL,
+				hapd) == 0)
 		return;
 #endif /* CONFIG_DPP2 */
 
@@ -1907,8 +2233,18 @@
 	case DPP_PA_PEER_DISCOVERY_REQ:
 		hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
 		break;
+#ifdef CONFIG_DPP3
 	case DPP_PA_PKEX_EXCHANGE_REQ:
-		hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
+		/* This is for PKEXv2, but for now, process only with
+		 * CONFIG_DPP3 to avoid issues with a capability that has not
+		 * been tested with other implementations. */
+		hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
+						 true);
+		break;
+#endif /* CONFIG_DPP3 */
+	case DPP_PA_PKEX_V1_EXCHANGE_REQ:
+		hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
+						 false);
 		break;
 	case DPP_PA_PKEX_EXCHANGE_RESP:
 		hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
@@ -1981,6 +2317,19 @@
 		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
 		return NULL;
 	}
+
+	if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
+		/* hostapd_dpp_auth_success() would normally have been called
+		 * from TX status handler, but since there was no such handler
+		 * call yet, simply send out the event message and proceed with
+		 * exchange. */
+		wpa_msg(hapd->msg_ctx, MSG_INFO,
+			DPP_EVENT_AUTH_SUCCESS "init=1");
+		hapd->dpp_auth_ok_on_ack = 0;
+	}
+
 	wpa_hexdump(MSG_DEBUG,
 		    "DPP: Received Configuration Request (GAS Query Request)",
 		    query, query_len);
@@ -2060,6 +2409,29 @@
 {
 	struct dpp_bootstrap_info *own_bi;
 	const char *pos, *end;
+	int tcp_port = DPP_TCP_PORT;
+	struct hostapd_ip_addr *ipaddr = NULL;
+#ifdef CONFIG_DPP2
+	struct hostapd_ip_addr ipaddr_buf;
+	char *addr;
+
+	pos = os_strstr(cmd, " tcp_port=");
+	if (pos) {
+		pos += 10;
+		tcp_port = atoi(pos);
+	}
+
+	addr = get_param(cmd, " tcp_addr=");
+	if (addr) {
+		int res;
+
+		res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
+		os_free(addr);
+		if (res)
+			return -1;
+		ipaddr = &ipaddr_buf;
+	}
+#endif /* CONFIG_DPP2 */
 
 	pos = os_strstr(cmd, " own=");
 	if (!pos)
@@ -2103,24 +2475,34 @@
 		return -1;
 
 	if (os_strstr(cmd, " init=1")) {
-		struct wpabuf *msg;
+#ifdef CONFIG_DPP3
+		enum hostapd_dpp_pkex_ver ver = PKEX_VER_AUTO;
+#else /* CONFIG_DPP3 */
+		enum hostapd_dpp_pkex_ver ver = PKEX_VER_ONLY_1;
+#endif /* CONFIG_DPP3 */
 
-		wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
-		dpp_pkex_free(hapd->dpp_pkex);
-		hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
-					       hapd->own_addr,
-					       hapd->dpp_pkex_identifier,
-					       hapd->dpp_pkex_code);
-		if (!hapd->dpp_pkex)
+		pos = os_strstr(cmd, " ver=");
+		if (pos) {
+			int v;
+
+			pos += 5;
+			v = atoi(pos);
+			if (v == 1)
+				ver = PKEX_VER_ONLY_1;
+			else if (v == 2)
+				ver = PKEX_VER_ONLY_2;
+			else
+				return -1;
+		}
+
+		if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0)
 			return -1;
-
-		msg = hapd->dpp_pkex->exchange_req;
-		/* TODO: Which channel to use? */
-		wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
-			" freq=%u type=%d", MAC2STR(broadcast), 2437,
-			DPP_PA_PKEX_EXCHANGE_REQ);
-		hostapd_drv_send_action(hapd, 2437, 0, broadcast,
-					wpabuf_head(msg), wpabuf_len(msg));
+	} else {
+#ifdef CONFIG_DPP2
+		dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi,
+					hapd->dpp_pkex_code,
+					hapd->dpp_pkex_identifier);
+#endif /* CONFIG_DPP2 */
 	}
 
 	/* TODO: Support multiple PKEX info entries */
@@ -2248,6 +2630,7 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 	if (!hapd->dpp_init_done)
 		return;
+	eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
 	eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
 	eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
 	eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
@@ -2260,6 +2643,8 @@
 	eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
 			     NULL);
 	hostapd_dpp_chirp_stop(hapd);
+	if (hapd->iface->interfaces)
+		dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd);
 #endif /* CONFIG_DPP2 */
 	dpp_auth_deinit(hapd->dpp_auth);
 	hapd->dpp_auth = NULL;
@@ -2371,6 +2756,7 @@
 	unsigned int i;
 	struct hostapd_hw_modes *mode;
 	int c;
+	bool chan6 = hapd->iface->hw_features == NULL;
 
 	if (!bi)
 		return;
@@ -2390,7 +2776,21 @@
 	}
 
 	/* Preferred chirping channels */
-	int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
+	mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211G);
+	if (mode) {
+		for (c = 0; c < mode->num_channels; c++) {
+			struct hostapd_channel_data *chan = &mode->channels[c];
+
+			if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+					  HOSTAPD_CHAN_RADAR) ||
+			    chan->freq != 2437)
+				continue;
+			chan6 = true;
+			break;
+		}
+	}
+	if (chan6)
+		int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
 
 	mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
 	if (mode) {
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index de51772..f353a0e 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -459,8 +459,8 @@
 		if (hapd->conf->sae_pwe == 2 &&
 		    sta->auth_alg == WLAN_AUTH_SAE &&
 		    sta->sae && !sta->sae->h2e &&
-		    elems.rsnxe && elems.rsnxe_len >= 1 &&
-		    (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+		    ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
+					      WLAN_RSNX_CAPAB_SAE_H2E)) {
 			wpa_printf(MSG_INFO, "SAE: " MACSTR
 				   " indicates support for SAE H2E, but did not use it",
 				   MAC2STR(sta->addr));
@@ -957,10 +957,25 @@
 	hapd->iconf->ch_switch_vht_config = 0;
 	hapd->iconf->ch_switch_he_config = 0;
 
+	if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 ||
+	    width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160)
+		hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+	else if (width == CHAN_WIDTH_20 || width == CHAN_WIDTH_20_NOHT)
+		hapd->iconf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+
 	hapd->iconf->secondary_channel = offset;
 	hostapd_set_oper_chwidth(hapd->iconf, chwidth);
 	hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
 	hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx);
+	if (hapd->iconf->ieee80211ac) {
+		hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+		if (chwidth == CHANWIDTH_160MHZ)
+			hapd->iconf->vht_capab |=
+				VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+		else if (chwidth == CHANWIDTH_80P80MHZ)
+			hapd->iconf->vht_capab |=
+				VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+	}
 
 	is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features,
 				  hapd->iface->num_hw_features);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index e257174..4b88641 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / Initialization and configuration
- * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2021, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -107,7 +107,8 @@
 		return;
 
 	if (hapd->conf->wmm_enabled < 0)
-		hapd->conf->wmm_enabled = hapd->iconf->ieee80211n;
+		hapd->conf->wmm_enabled = hapd->iconf->ieee80211n |
+			hapd->iconf->ieee80211ax;
 
 #ifndef CONFIG_NO_RADIUS
 	radius_client_reconfig(hapd->radius, hapd->conf->radius);
@@ -392,6 +393,7 @@
 #ifdef CONFIG_DPP
 	hostapd_dpp_deinit(hapd);
 	gas_query_ap_deinit(hapd->gas);
+	hapd->gas = NULL;
 #endif /* CONFIG_DPP */
 
 	authsrv_deinit(hapd);
@@ -414,6 +416,7 @@
 	}
 
 	wpabuf_free(hapd->time_adv);
+	hapd->time_adv = NULL;
 
 #ifdef CONFIG_INTERWORKING
 	gas_serv_deinit(hapd);
@@ -429,6 +432,7 @@
 		       hapd->tmp_eap_user.identity_len);
 	bin_clear_free(hapd->tmp_eap_user.password,
 		       hapd->tmp_eap_user.password_len);
+	os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
 #endif /* CONFIG_SQLITE */
 
 #ifdef CONFIG_MESH
@@ -1170,7 +1174,8 @@
 	}
 
 	if (conf->wmm_enabled < 0)
-		conf->wmm_enabled = hapd->iconf->ieee80211n;
+		conf->wmm_enabled = hapd->iconf->ieee80211n |
+			hapd->iconf->ieee80211ax;
 
 #ifdef CONFIG_IEEE80211R_AP
 	if (is_zero_ether_addr(conf->r1_key_holder))
@@ -1669,6 +1674,26 @@
 }
 
 
+static void hostapd_set_6ghz_sec_chan(struct hostapd_iface *iface)
+{
+	int bw, seg0;
+
+	if (!is_6ghz_op_class(iface->conf->op_class))
+		return;
+
+	seg0 = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
+	bw = center_idx_to_bw_6ghz(seg0);
+	/* Assign the secondary channel if absent in config for
+	 * bandwidths > 20 MHz */
+	if (bw > 20 && !iface->conf->secondary_channel) {
+		if (((iface->conf->channel - 1) / 4) % 2)
+			iface->conf->secondary_channel = -1;
+		else
+			iface->conf->secondary_channel = 1;
+	}
+}
+
+
 static int setup_interface2(struct hostapd_iface *iface)
 {
 	iface->wait_channel_update = 0;
@@ -1688,6 +1713,7 @@
 
 			ch_width = op_class_to_ch_width(iface->conf->op_class);
 			hostapd_set_oper_chwidth(iface->conf, ch_width);
+			hostapd_set_6ghz_sec_chan(iface);
 		}
 
 		ret = hostapd_select_hw_mode(iface);
@@ -2308,10 +2334,12 @@
 {
 	int ret;
 
+	if (!iface->conf)
+		return -1;
 	ret = setup_interface(iface);
 	if (ret) {
 		wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
-			   iface->conf ? iface->conf->bss[0]->iface : "N/A");
+			   iface->conf->bss[0]->iface);
 		return -1;
 	}
 
@@ -3436,6 +3464,20 @@
 	switch (params->bandwidth) {
 	case 0:
 	case 20:
+		conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+		break;
+	case 40:
+	case 80:
+	case 160:
+		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+		break;
+	default:
+		return -1;
+	}
+
+	switch (params->bandwidth) {
+	case 0:
+	case 20:
 	case 40:
 		hostapd_set_oper_chwidth(conf, CHANWIDTH_USE_HT);
 		break;
@@ -3454,6 +3496,7 @@
 
 	conf->channel = channel;
 	conf->ieee80211n = params->ht_enabled;
+	conf->ieee80211ac = params->vht_enabled;
 	conf->secondary_channel = params->sec_channel_offset;
 	ieee80211_freq_to_chan(params->center_freq1,
 			       &seg0);
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 591996a..7f7877b 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -138,6 +138,8 @@
 	/* LCI update time */
 	struct os_time lci_date;
 	int stationary;
+	u32 short_ssid;
+	u8 bss_parameters;
 };
 
 struct hostapd_sae_commit_queue {
@@ -326,10 +328,10 @@
 
 #ifdef CONFIG_SAE
 	/** Key used for generating SAE anti-clogging tokens */
-	u8 sae_token_key[8];
-	struct os_reltime last_sae_token_key_update;
-	u16 sae_token_idx;
-	u16 sae_pending_token_idx[256];
+	u8 comeback_key[8];
+	struct os_reltime last_comeback_key_update;
+	u16 comeback_idx;
+	u16 comeback_pending_idx[256];
 	int dot11RSNASAERetransPeriod; /* msec */
 	struct dl_list sae_commit_queue; /* struct hostapd_sae_commit_queue */
 #endif /* CONFIG_SAE */
@@ -354,6 +356,8 @@
 	int last_bigtk_key_idx;
 	u8 last_bigtk[WPA_BIGTK_MAX_LEN];
 	size_t last_bigtk_len;
+
+	bool force_backlog_bytes;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_MBO
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 7849be1..4b66b02 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -838,6 +838,8 @@
 				       iface->freq, NULL,
 				       iface->hw_features,
 				       iface->num_hw_features);
+	if (!pri_chan)
+		return 0;
 	hostapd_encode_edmg_chan(iface->conf->enable_edmg,
 				 iface->conf->edmg_channel,
 				 pri_chan->chan,
@@ -917,8 +919,14 @@
 		return 1;
 
 	if (hostapd_is_usable_chan(iface, iface->freq +
-				   iface->conf->secondary_channel * 20, 0))
-		return 1;
+				   iface->conf->secondary_channel * 20, 0)) {
+		if (iface->conf->secondary_channel == 1 &&
+		    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))
+			return 1;
+		if (iface->conf->secondary_channel == -1 &&
+		    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M))
+			return 1;
+	}
 	if (!iface->conf->ht40_plus_minus_allowed)
 		return 0;
 
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 40d4a33..6140a49 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -572,7 +572,7 @@
 
 	if (update && !use_pt &&
 	    sae_prepare_commit(hapd->own_addr, sta->addr,
-			       (u8 *) password, os_strlen(password), rx_id,
+			       (u8 *) password, os_strlen(password),
 			       sta->sae) < 0) {
 		wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
 		return NULL;
@@ -687,42 +687,53 @@
 	return reply_res;
 }
 
+#endif /* CONFIG_SAE */
 
-static int use_sae_anti_clogging(struct hostapd_data *hapd)
+
+#if defined(CONFIG_SAE) || defined(CONFIG_PASN)
+
+static int use_anti_clogging(struct hostapd_data *hapd)
 {
 	struct sta_info *sta;
 	unsigned int open = 0;
 
-	if (hapd->conf->sae_anti_clogging_threshold == 0)
+	if (hapd->conf->anti_clogging_threshold == 0)
 		return 1;
 
 	for (sta = hapd->sta_list; sta; sta = sta->next) {
-		if (!sta->sae)
-			continue;
-		if (sta->sae->state != SAE_COMMITTED &&
-		    sta->sae->state != SAE_CONFIRMED)
-			continue;
-		open++;
-		if (open >= hapd->conf->sae_anti_clogging_threshold)
+#ifdef CONFIG_SAE
+		if (sta->sae &&
+		    (sta->sae->state == SAE_COMMITTED ||
+		     sta->sae->state == SAE_CONFIRMED))
+			open++;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_PASN
+		if (sta->pasn && sta->pasn->ecdh)
+			open++;
+#endif /* CONFIG_PASN */
+		if (open >= hapd->conf->anti_clogging_threshold)
 			return 1;
 	}
 
+#ifdef CONFIG_SAE
 	/* In addition to already existing open SAE sessions, check whether
 	 * there are enough pending commit messages in the processing queue to
 	 * potentially result in too many open sessions. */
 	if (open + dl_list_len(&hapd->sae_commit_queue) >=
-	    hapd->conf->sae_anti_clogging_threshold)
+	    hapd->conf->anti_clogging_threshold)
 		return 1;
+#endif /* CONFIG_SAE */
 
 	return 0;
 }
 
 
-static int sae_token_hash(struct hostapd_data *hapd, const u8 *addr, u8 *idx)
+static int comeback_token_hash(struct hostapd_data *hapd, const u8 *addr,
+			       u8 *idx)
 {
 	u8 hash[SHA256_MAC_LEN];
 
-	if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+	if (hmac_sha256(hapd->comeback_key, sizeof(hapd->comeback_key),
 			addr, ETH_ALEN, hash) < 0)
 		return -1;
 	*idx = hash[0];
@@ -730,8 +741,8 @@
 }
 
 
-static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
-			   const u8 *token, size_t token_len)
+static int check_comeback_token(struct hostapd_data *hapd, const u8 *addr,
+				const u8 *token, size_t token_len)
 {
 	u8 mac[SHA256_MAC_LEN];
 	const u8 *addrs[2];
@@ -739,11 +750,13 @@
 	u16 token_idx;
 	u8 idx;
 
-	if (token_len != SHA256_MAC_LEN || sae_token_hash(hapd, addr, &idx) < 0)
+	if (token_len != SHA256_MAC_LEN ||
+	    comeback_token_hash(hapd, addr, &idx) < 0)
 		return -1;
-	token_idx = hapd->sae_pending_token_idx[idx];
+	token_idx = hapd->comeback_pending_idx[idx];
 	if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
-		wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
+		wpa_printf(MSG_DEBUG,
+			   "Comeback: Invalid anti-clogging token from "
 			   MACSTR " - token_idx 0x%04x, expected 0x%04x",
 			   MAC2STR(addr), WPA_GET_BE16(token), token_idx);
 		return -1;
@@ -753,12 +766,12 @@
 	len[0] = ETH_ALEN;
 	addrs[1] = token;
 	len[1] = 2;
-	if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+	if (hmac_sha256_vector(hapd->comeback_key, sizeof(hapd->comeback_key),
 			       2, addrs, len, mac) < 0 ||
 	    os_memcmp_const(token + 2, &mac[2], SHA256_MAC_LEN - 2) != 0)
 		return -1;
 
-	hapd->sae_pending_token_idx[idx] = 0; /* invalidate used token */
+	hapd->comeback_pending_idx[idx] = 0; /* invalidate used token */
 
 	return 0;
 }
@@ -777,25 +790,26 @@
 	u16 token_idx;
 
 	os_get_reltime(&now);
-	if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
-	    os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60) ||
-	    hapd->sae_token_idx == 0xffff) {
-		if (random_get_bytes(hapd->sae_token_key,
-				     sizeof(hapd->sae_token_key)) < 0)
+	if (!os_reltime_initialized(&hapd->last_comeback_key_update) ||
+	    os_reltime_expired(&now, &hapd->last_comeback_key_update, 60) ||
+	    hapd->comeback_idx == 0xffff) {
+		if (random_get_bytes(hapd->comeback_key,
+				     sizeof(hapd->comeback_key)) < 0)
 			return NULL;
-		wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
-			    hapd->sae_token_key, sizeof(hapd->sae_token_key));
-		hapd->last_sae_token_key_update = now;
-		hapd->sae_token_idx = 0;
-		os_memset(hapd->sae_pending_token_idx, 0,
-			  sizeof(hapd->sae_pending_token_idx));
+		wpa_hexdump(MSG_DEBUG, "Comeback: Updated token key",
+			    hapd->comeback_key, sizeof(hapd->comeback_key));
+		hapd->last_comeback_key_update = now;
+		hapd->comeback_idx = 0;
+		os_memset(hapd->comeback_pending_idx, 0,
+			  sizeof(hapd->comeback_pending_idx));
 	}
 
 	buf = wpabuf_alloc(sizeof(le16) + 3 + SHA256_MAC_LEN);
 	if (buf == NULL)
 		return NULL;
 
-	wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
+	if (group)
+		wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
 
 	if (h2e) {
 		/* Encapsulate Anti-clogging Token field in a container IE */
@@ -804,15 +818,16 @@
 		wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
 	}
 
-	if (sae_token_hash(hapd, addr, &p_idx) < 0) {
+	if (comeback_token_hash(hapd, addr, &p_idx) < 0) {
 		wpabuf_free(buf);
 		return NULL;
 	}
-	token_idx = hapd->sae_pending_token_idx[p_idx];
+
+	token_idx = hapd->comeback_pending_idx[p_idx];
 	if (!token_idx) {
-		hapd->sae_token_idx++;
-		token_idx = hapd->sae_token_idx;
-		hapd->sae_pending_token_idx[p_idx] = token_idx;
+		hapd->comeback_idx++;
+		token_idx = hapd->comeback_idx;
+		hapd->comeback_pending_idx[p_idx] = token_idx;
 	}
 	WPA_PUT_BE16(idx, token_idx);
 	token = wpabuf_put(buf, SHA256_MAC_LEN);
@@ -820,7 +835,7 @@
 	len[0] = ETH_ALEN;
 	addrs[1] = idx;
 	len[1] = sizeof(idx);
-	if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+	if (hmac_sha256_vector(hapd->comeback_key, sizeof(hapd->comeback_key),
 			       2, addrs, len, token) < 0) {
 		wpabuf_free(buf);
 		return NULL;
@@ -830,6 +845,10 @@
 	return buf;
 }
 
+#endif /* defined(CONFIG_SAE) || defined(CONFIG_PASN) */
+
+
+#ifdef CONFIG_SAE
 
 static int sae_check_big_sync(struct hostapd_data *hapd, struct sta_info *sta)
 {
@@ -1452,7 +1471,8 @@
 			goto remove_sta;
 		}
 
-		if (token && check_sae_token(hapd, sta->addr, token, token_len)
+		if (token &&
+		    check_comeback_token(hapd, sta->addr, token, token_len)
 		    < 0) {
 			wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
 				   "incorrect token from " MACSTR,
@@ -1469,7 +1489,7 @@
 			goto reply;
 		}
 
-		if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
+		if (!token && use_anti_clogging(hapd) && !allow_reuse) {
 			int h2e = 0;
 
 			wpa_printf(MSG_DEBUG,
@@ -2363,11 +2383,12 @@
 				     struct wpabuf *wd)
 {
 	struct pasn_data *pasn = sta->pasn;
-	const char *password = NULL;
+	const char *password;
 	const u8 *data;
 	size_t buf_len;
 	u16 res, alg, seq, status;
 	int groups[] = { pasn->group, 0 };
+	struct sae_pt *pt = NULL;
 	int ret;
 
 	if (!wd)
@@ -2377,7 +2398,7 @@
 	buf_len = wpabuf_len(wd);
 
 	if (buf_len < 6) {
-		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short. len=%lu",
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short. len=%zu",
 			   buf_len);
 		return -1;
 	}
@@ -2389,8 +2410,8 @@
 	wpa_printf(MSG_DEBUG, "PASN: SAE commit: alg=%u, seq=%u, status=%u",
 		   alg, seq, status);
 
-	/* TODO: SAE H2E */
-	if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+	if (alg != WLAN_AUTH_SAE || seq != 1 ||
+	    status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
 		wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit");
 		return -1;
 	}
@@ -2404,15 +2425,14 @@
 		return -1;
 	}
 
-	password = sae_get_password(hapd, sta, NULL, NULL, NULL, NULL);
-	if (!password) {
-		wpa_printf(MSG_DEBUG, "PASN: No SAE password found");
+	password = sae_get_password(hapd, sta, NULL, NULL, &pt, NULL);
+	if (!password || !pt) {
+		wpa_printf(MSG_DEBUG, "PASN: No SAE PT found");
 		return -1;
 	}
 
-	ret = sae_prepare_commit(hapd->own_addr, sta->addr,
-				 (const u8 *) password, os_strlen(password), 0,
-				 &pasn->sae);
+	ret = sae_prepare_commit_pt(&pasn->sae, pt, hapd->own_addr, sta->addr,
+				    NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
 		return -1;
@@ -2454,7 +2474,7 @@
 	buf_len = wpabuf_len(wd);
 
 	if (buf_len < 6) {
-		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short. len=%lu",
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short. len=%zu",
 			   buf_len);
 		return -1;
 	}
@@ -2509,7 +2529,7 @@
 	len_ptr = wpabuf_put(buf, 2);
 	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
 	wpabuf_put_le16(buf, 1);
-	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+	wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
 
 	/* Write the actual commit and update the length accordingly */
 	sae_write_commit(&pasn->sae, buf, NULL, 0);
@@ -2626,7 +2646,7 @@
 			      wpabuf_head(pasn->secret),
 			      wpabuf_len(pasn->secret),
 			      &sta->pasn->ptk, sta->pasn->akmp,
-			      sta->pasn->cipher, WPA_KDK_MAX_LEN);
+			      sta->pasn->cipher, sta->pasn->kdk_len);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK");
 		goto fail;
@@ -2656,6 +2676,10 @@
 static int pasn_wd_handle_fils(struct hostapd_data *hapd, struct sta_info *sta,
 			       struct wpabuf *wd)
 {
+#ifdef CONFIG_NO_RADIUS
+	wpa_printf(MSG_DEBUG, "PASN: FILS: RADIUS is not configured. Fail");
+	return -1;
+#else /* CONFIG_NO_RADIUS */
 	struct pasn_data *pasn = sta->pasn;
 	struct pasn_fils_data *fils = &pasn->fils;
 	struct ieee802_11_elems elems;
@@ -2680,7 +2704,7 @@
 	buf_len = wpabuf_len(wd);
 
 	if (buf_len < 6) {
-		wpa_printf(MSG_DEBUG, "PASN: FILS: Buffer too short. len=%lu",
+		wpa_printf(MSG_DEBUG, "PASN: FILS: Buffer too short. len=%zu",
 			   buf_len);
 		return -1;
 	}
@@ -2740,11 +2764,6 @@
 		    FILS_SESSION_LEN);
 	os_memcpy(fils->session, elems.fils_session, FILS_SESSION_LEN);
 
-#ifdef CONFIG_NO_RADIUS
-	wpa_printf(MSG_DEBUG, "PASN: FILS: RADIUS is not configured. Fail");
-	return -1;
-#endif /* CONFIG_NO_RADIUS */
-
 	fils_wd = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION,
 				    WLAN_EID_EXT_WRAPPED_DATA);
 
@@ -2775,6 +2794,7 @@
 
 	wpabuf_free(fils_wd);
 	return 0;
+#endif /* CONFIG_NO_RADIUS */
 }
 
 #endif /* CONFIG_FILS */
@@ -2863,7 +2883,7 @@
 	ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr,
 			      wpabuf_head(secret), wpabuf_len(secret),
 			      &sta->pasn->ptk, sta->pasn->akmp,
-			      sta->pasn->cipher, WPA_KDK_MAX_LEN);
+			      sta->pasn->cipher, sta->pasn->kdk_len);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
 		return -1;
@@ -2874,6 +2894,54 @@
 }
 
 
+static void handle_auth_pasn_comeback(struct hostapd_data *hapd,
+				      struct sta_info *sta, u16 group)
+{
+	struct wpabuf *buf, *comeback;
+	int ret;
+
+	wpa_printf(MSG_DEBUG,
+		   "PASN: Building comeback frame 2. Comeback after=%u",
+		   hapd->conf->pasn_comeback_after);
+
+	buf = wpabuf_alloc(1500);
+	if (!buf)
+		return;
+
+	wpa_pasn_build_auth_header(buf, hapd->own_addr, hapd->own_addr,
+				   sta->addr, 2,
+				   WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY);
+
+	/*
+	 * Do not include the group as a part of the token since it is not going
+	 * to be used.
+	 */
+	comeback = auth_build_token_req(hapd, 0, sta->addr, 0);
+	if (!comeback) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Failed sending auth with comeback");
+		wpabuf_free(buf);
+		return;
+	}
+
+	wpa_pasn_add_parameter_ie(buf, group,
+				  WPA_PASN_WRAPPED_DATA_NO,
+				  NULL, 0, comeback,
+				  hapd->conf->pasn_comeback_after);
+	wpabuf_free(comeback);
+
+	wpa_printf(MSG_DEBUG,
+		   "PASN: comeback: STA=" MACSTR, MAC2STR(sta->addr));
+
+	ret = hostapd_drv_send_mlme(hapd, wpabuf_head(buf), wpabuf_len(buf), 0,
+				    NULL, 0, 0);
+	if (ret)
+		wpa_printf(MSG_INFO, "PASN: Failed to send comeback frame 2");
+
+	wpabuf_free(buf);
+}
+
+
 static int handle_auth_pasn_resp(struct hostapd_data *hapd,
 				 struct sta_info *sta,
 				 struct rsn_pmksa_cache_entry *pmksa,
@@ -2881,12 +2949,13 @@
 {
 	struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
 	u8 mic[WPA_PASN_MAX_MIC_LEN];
-	u8 mic_len, frame_len, data_len;
+	u8 mic_len;
 	u8 *ptr;
 	const u8 *frame, *data, *rsn_ie, *rsnxe_ie;
 	u8 *data_buf = NULL;
-	size_t rsn_ie_len;
+	size_t rsn_ie_len, frame_len, data_len;
 	int ret;
+	const u8 *pmkid = NULL;
 
 	wpa_printf(MSG_DEBUG, "PASN: Building frame 2: status=%u", status);
 
@@ -2900,7 +2969,22 @@
 	if (status != WLAN_STATUS_SUCCESS)
 		goto done;
 
-	if (wpa_pasn_add_rsne(buf, pmksa ? pmksa->pmkid : NULL,
+	if (pmksa) {
+		pmkid = pmksa->pmkid;
+#ifdef CONFIG_SAE
+	} else if (sta->pasn->akmp == WPA_KEY_MGMT_SAE) {
+		wpa_printf(MSG_DEBUG, "PASN: Use SAE PMKID");
+		pmkid = sta->pasn->sae.pmkid;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+	} else if (sta->pasn->akmp == WPA_KEY_MGMT_FILS_SHA256 ||
+		   sta->pasn->akmp == WPA_KEY_MGMT_FILS_SHA384) {
+		wpa_printf(MSG_DEBUG, "PASN: Use FILS ERP PMKID");
+		pmkid = sta->pasn->fils.erp_pmkid;
+#endif /* CONFIG_FILS */
+	}
+
+	if (wpa_pasn_add_rsne(buf, pmkid,
 			      sta->pasn->akmp, sta->pasn->cipher) < 0)
 		goto fail;
 
@@ -2921,7 +3005,7 @@
 
 	wpa_pasn_add_parameter_ie(buf, sta->pasn->group,
 				  sta->pasn->wrapped_data_format,
-				  pubkey, NULL, 0);
+				  pubkey, true, NULL, 0);
 
 	if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
 		goto fail;
@@ -2979,6 +3063,13 @@
 		goto fail;
 	}
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->conf->pasn_corrupt_mic) {
+		wpa_printf(MSG_DEBUG, "PASN: frame 2: Corrupt MIC");
+		mic[0] = ~mic[0];
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	os_memcpy(ptr, mic, mic_len);
 
 done:
@@ -3018,7 +3109,7 @@
 	const int *groups = hapd->conf->pasn_groups;
 	static const int default_groups[] = { 19, 0 };
 	u16 status = WLAN_STATUS_SUCCESS;
-	int ret;
+	int ret, inc_y;
 	bool derive_keys;
 	u32 i;
 
@@ -3060,6 +3151,15 @@
 	sta->pasn->akmp = rsn_data.key_mgmt;
 	sta->pasn->cipher = rsn_data.pairwise_cipher;
 
+	if (hapd->conf->force_kdk_derivation ||
+	    ((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) &&
+	     ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
+				       WLAN_RSNX_CAPAB_SECURE_LTF)))
+		sta->pasn->kdk_len = WPA_KDK_MAX_LEN;
+	else
+		sta->pasn->kdk_len = 0;
+	wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", sta->pasn->kdk_len);
+
 	if (!elems.pasn_params || !elems.pasn_params_len) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: No PASN Parameters element found");
@@ -3093,6 +3193,25 @@
 		goto send_resp;
 	}
 
+	if (pasn_params.comeback) {
+		wpa_printf(MSG_DEBUG, "PASN: Checking peer comeback token");
+
+		ret = check_comeback_token(hapd, sta->addr,
+					   pasn_params.comeback,
+					   pasn_params.comeback_len);
+
+		if (ret) {
+			wpa_printf(MSG_DEBUG, "PASN: Invalid comeback token");
+			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			goto send_resp;
+		}
+	} else if (use_anti_clogging(hapd)) {
+		wpa_printf(MSG_DEBUG, "PASN: Respond with comeback");
+		handle_auth_pasn_comeback(hapd, sta, pasn_params.group);
+		ap_free_sta(hapd, sta);
+		return;
+	}
+
 	sta->pasn->ecdh = crypto_ecdh_init(pasn_params.group);
 	if (!sta->pasn->ecdh) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
@@ -3102,9 +3221,22 @@
 
 	sta->pasn->group = pasn_params.group;
 
-	secret = crypto_ecdh_set_peerkey(sta->pasn->ecdh, 0,
-					 pasn_params.pubkey,
-					 pasn_params.pubkey_len);
+	if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) {
+		inc_y = 1;
+	} else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 ||
+		   pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) {
+		inc_y = 0;
+	} else {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Invalid first octet in pubkey=0x%x",
+			   pasn_params.pubkey[0]);
+		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+		goto send_resp;
+	}
+
+	secret = crypto_ecdh_set_peerkey(sta->pasn->ecdh, inc_y,
+					 pasn_params.pubkey + 1,
+					 pasn_params.pubkey_len - 1);
 	if (!secret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -3811,8 +3943,10 @@
 
  fail:
 	reply_res = send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, auth_alg,
-				    auth_transaction + 1, resp, resp_ies,
-				    resp_ies_len, "handle-auth");
+				    auth_alg == WLAN_AUTH_SAE ?
+				    auth_transaction : auth_transaction + 1,
+				    resp, resp_ies, resp_ies_len,
+				    "handle-auth");
 
 	if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
 					  reply_res != WLAN_STATUS_SUCCESS)) {
@@ -4561,8 +4695,8 @@
 		if (hapd->conf->sae_pwe == 2 &&
 		    sta->auth_alg == WLAN_AUTH_SAE &&
 		    sta->sae && !sta->sae->h2e &&
-		    elems.rsnxe && elems.rsnxe_len >= 1 &&
-		    (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+		    ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
+					      WLAN_RSNX_CAPAB_SAE_H2E)) {
 			wpa_printf(MSG_INFO, "SAE: " MACSTR
 				   " indicates support for SAE H2E, but did not use it",
 				   MAC2STR(sta->addr));
@@ -5784,6 +5918,9 @@
 		" reason_code=%d",
 		MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
 
+	/* Clear the PTKSA cache entries for PASN */
+	ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
+
 	sta = ap_get_sta(hapd, mgmt->sa);
 	if (sta == NULL) {
 		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
@@ -5961,19 +6098,17 @@
 			end = ((const u8 *) mgmt) + len;
 			gas_query_ap_rx(hapd->gas, mgmt->sa,
 					mgmt->u.action.category,
-					pos, end - pos, hapd->iface->freq);
+					pos, end - pos, freq);
 			return 1;
 		}
 #endif /* CONFIG_DPP */
 		if (hapd->public_action_cb) {
 			hapd->public_action_cb(hapd->public_action_cb_ctx,
-					       (u8 *) mgmt, len,
-					       hapd->iface->freq);
+					       (u8 *) mgmt, len, freq);
 		}
 		if (hapd->public_action_cb2) {
 			hapd->public_action_cb2(hapd->public_action_cb2_ctx,
-						(u8 *) mgmt, len,
-						hapd->iface->freq);
+						(u8 *) mgmt, len, freq);
 		}
 		if (hapd->public_action_cb || hapd->public_action_cb2)
 			return 1;
@@ -5981,8 +6116,7 @@
 	case WLAN_ACTION_VENDOR_SPECIFIC:
 		if (hapd->vendor_action_cb) {
 			if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
-						   (u8 *) mgmt, len,
-						   hapd->iface->freq) == 0)
+						   (u8 *) mgmt, len, freq) == 0)
 				return 1;
 		}
 		break;
@@ -6484,8 +6618,6 @@
 	struct sta_info *sta;
 	const struct rrm_measurement_report_element *report;
 
-	if (is_multicast_ether_addr(mgmt->da))
-		return;
 #ifdef CONFIG_DPP
 	if (len >= IEEE80211_HDRLEN + 6 &&
 	    mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
@@ -6516,6 +6648,8 @@
 		return;
 	}
 #endif /* CONFIG_DPP */
+	if (is_multicast_ether_addr(mgmt->da))
+		return;
 	sta = ap_get_sta(hapd, mgmt->da);
 	if (!sta) {
 		wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR
@@ -6934,4 +7068,386 @@
 	return eid;
 }
 
+
+static size_t hostapd_eid_nr_db_len(struct hostapd_data *hapd,
+				    size_t *current_len)
+{
+	struct hostapd_neighbor_entry *nr;
+	size_t total_len = 0, len = *current_len;
+
+	dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
+			 list) {
+		if (!nr->nr || wpabuf_len(nr->nr) < 12)
+			continue;
+
+		if (nr->short_ssid == hapd->conf->ssid.short_ssid)
+			continue;
+
+		/* Start a new element */
+		if (!len ||
+		    len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) {
+			len = RNR_HEADER_LEN;
+			total_len += RNR_HEADER_LEN;
+		}
+
+		len += RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN;
+		total_len += RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN;
+	}
+
+	*current_len = len;
+	return total_len;
+}
+
+
+static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
+					struct hostapd_data *reporting_hapd,
+					size_t *current_len)
+{
+	size_t total_len = 0, len = *current_len;
+	int tbtt_count = 0;
+	size_t i, start = 0;
+
+	while (start < hapd->iface->num_bss) {
+		if (!len ||
+		    len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) {
+			len = RNR_HEADER_LEN;
+			total_len += RNR_HEADER_LEN;
+		}
+
+		len += RNR_TBTT_HEADER_LEN;
+		total_len += RNR_TBTT_HEADER_LEN;
+
+		for (i = start; i < hapd->iface->num_bss; i++) {
+			struct hostapd_data *bss = hapd->iface->bss[i];
+
+			if (!bss || !bss->conf || !bss->started)
+				continue;
+
+			if (bss == reporting_hapd ||
+			    bss->conf->ignore_broadcast_ssid)
+				continue;
+
+			if (len + RNR_TBTT_INFO_LEN > 255 ||
+			    tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+				break;
+
+			len += RNR_TBTT_INFO_LEN;
+			total_len += RNR_TBTT_INFO_LEN;
+			tbtt_count++;
+		}
+		start = i;
+	}
+
+	if (!tbtt_count)
+		total_len = 0;
+	else
+		*current_len = len;
+
+	return total_len;
+}
+
+
+enum colocation_mode {
+	NO_COLOCATED_6GHZ,
+	STANDALONE_6GHZ,
+	COLOCATED_6GHZ,
+	COLOCATED_LOWER_BAND,
+};
+
+static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd)
+{
+	u8 i;
+	bool is_6ghz = is_6ghz_op_class(hapd->iconf->op_class);
+
+	if (!hapd->iface || !hapd->iface->interfaces)
+		return NO_COLOCATED_6GHZ;
+
+	if (is_6ghz && hapd->iface->interfaces->count == 1)
+		return STANDALONE_6GHZ;
+
+	for (i = 0; i < hapd->iface->interfaces->count; i++) {
+		struct hostapd_iface *iface;
+		bool is_colocated_6ghz;
+
+		iface = hapd->iface->interfaces->iface[i];
+		if (iface == hapd->iface || !iface || !iface->conf)
+			continue;
+
+		is_colocated_6ghz = is_6ghz_op_class(iface->conf->op_class);
+		if (!is_6ghz && is_colocated_6ghz)
+			return COLOCATED_LOWER_BAND;
+		if (is_6ghz && !is_colocated_6ghz)
+			return COLOCATED_6GHZ;
+	}
+
+	if (is_6ghz)
+		return STANDALONE_6GHZ;
+
+	return NO_COLOCATED_6GHZ;
+}
+
+
+static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd,
+					     size_t *current_len)
+{
+	struct hostapd_iface *iface;
+	size_t len = 0;
+	size_t i;
+
+	if (!hapd->iface || !hapd->iface->interfaces)
+		return 0;
+
+	for (i = 0; i < hapd->iface->interfaces->count; i++) {
+		iface = hapd->iface->interfaces->iface[i];
+
+		if (iface == hapd->iface ||
+		    !is_6ghz_op_class(iface->conf->op_class))
+			continue;
+
+		len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
+						 current_len);
+	}
+
+	return len;
+}
+
+
+size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
+{
+	size_t total_len = 0, current_len = 0;
+	enum colocation_mode mode = get_colocation_mode(hapd);
+
+	switch (type) {
+	case WLAN_FC_STYPE_BEACON:
+		if (hapd->conf->rnr)
+			total_len += hostapd_eid_nr_db_len(hapd, &current_len);
+		/* fallthrough */
+
+	case WLAN_FC_STYPE_PROBE_RESP:
+		if (mode == COLOCATED_LOWER_BAND)
+			total_len += hostapd_eid_rnr_colocation_len(
+				hapd, &current_len);
+
+		if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+			total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
+							       &current_len);
+		break;
+
+	case WLAN_FC_STYPE_ACTION:
+		if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
+			total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
+							       &current_len);
+		break;
+
+	default:
+		break;
+	}
+
+	return total_len;
+}
+
+
+static u8 * hostapd_eid_nr_db(struct hostapd_data *hapd, u8 *eid,
+			      size_t *current_len)
+{
+	struct hostapd_neighbor_entry *nr;
+	size_t len = *current_len;
+	u8 *size_offset = (eid - len) + 1;
+
+	dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
+			 list) {
+		if (!nr->nr || wpabuf_len(nr->nr) < 12)
+			continue;
+
+		if (nr->short_ssid == hapd->conf->ssid.short_ssid)
+			continue;
+
+		/* Start a new element */
+		if (!len ||
+		    len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) {
+			*eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
+			size_offset = eid++;
+			len = RNR_HEADER_LEN;
+		}
+
+		/* TBTT Information Header subfield (2 octets) */
+		*eid++ = 0;
+		/* TBTT Information Length */
+		*eid++ = RNR_TBTT_INFO_LEN;
+		/* Operating Class */
+		*eid++ = wpabuf_head_u8(nr->nr)[10];
+		/* Channel Number */
+		*eid++ = wpabuf_head_u8(nr->nr)[11];
+		len += RNR_TBTT_HEADER_LEN;
+		/* TBTT Information Set */
+		/* TBTT Information field */
+		/* Neighbor AP TBTT Offset */
+		*eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN;
+		/* BSSID */
+		os_memcpy(eid, nr->bssid, ETH_ALEN);
+		eid += ETH_ALEN;
+		/* Short SSID */
+		os_memcpy(eid, &nr->short_ssid, 4);
+		eid += 4;
+		/* BSS parameters */
+		*eid++ = nr->bss_parameters;
+		/* 20 MHz PSD */
+		*eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1;
+		len += RNR_TBTT_INFO_LEN;
+		*size_offset = (eid - size_offset) - 1;
+	}
+
+	*current_len = len;
+	return eid;
+}
+
+
+static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
+				  struct hostapd_data *reporting_hapd,
+				  u8 *eid, size_t *current_len)
+{
+	struct hostapd_data *bss;
+	struct hostapd_iface *iface = hapd->iface;
+	size_t i, start = 0;
+	size_t len = *current_len;
+	u8 *tbtt_count_pos, *eid_start = eid, *size_offset = (eid - len) + 1;
+	u8 tbtt_count = 0, op_class, channel, bss_param;
+
+	if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq)
+		return eid;
+
+	if (ieee80211_freq_to_channel_ext(iface->freq,
+					  hapd->iconf->secondary_channel,
+					  hostapd_get_oper_chwidth(hapd->iconf),
+					  &op_class, &channel) ==
+	    NUM_HOSTAPD_MODES)
+		return eid;
+
+	while (start < iface->num_bss) {
+		if (!len ||
+		    len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) {
+			eid_start = eid;
+			*eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
+			size_offset = eid++;
+			len = RNR_HEADER_LEN;
+			tbtt_count = 0;
+		}
+
+		tbtt_count_pos = eid++;
+		*eid++ = RNR_TBTT_INFO_LEN;
+		*eid++ = op_class;
+		*eid++ = hapd->iconf->channel;
+		len += RNR_TBTT_HEADER_LEN;
+
+		for (i = start; i < iface->num_bss; i++) {
+			bss_param = 0;
+			bss = iface->bss[i];
+			if (!bss || !bss->conf || !bss->started)
+				continue;
+
+			if (bss == reporting_hapd ||
+			    bss->conf->ignore_broadcast_ssid)
+				continue;
+
+			if (len + RNR_TBTT_INFO_LEN > 255 ||
+			    tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+				break;
+
+			*eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN;
+			os_memcpy(eid, bss->conf->bssid, ETH_ALEN);
+			eid += ETH_ALEN;
+			os_memcpy(eid, &bss->conf->ssid.short_ssid, 4);
+			eid += 4;
+			if (bss->conf->ssid.short_ssid ==
+			    reporting_hapd->conf->ssid.short_ssid)
+				bss_param |= RNR_BSS_PARAM_SAME_SSID;
+
+			if (is_6ghz_op_class(hapd->iconf->op_class) &&
+			    bss->conf->unsol_bcast_probe_resp_interval)
+				bss_param |=
+					RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE;
+
+			bss_param |= RNR_BSS_PARAM_CO_LOCATED;
+
+			*eid++ = bss_param;
+			*eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1;
+			len += RNR_TBTT_INFO_LEN;
+			tbtt_count += 1;
+		}
+
+		start = i;
+		*tbtt_count_pos = RNR_TBTT_INFO_COUNT(tbtt_count - 1);
+		*size_offset = (eid - size_offset) - 1;
+	}
+
+	if (tbtt_count == 0)
+		return eid_start;
+
+	*current_len = len;
+	return eid;
+}
+
+
+static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid,
+				       size_t *current_len)
+{
+	struct hostapd_iface *iface;
+	size_t i;
+
+	if (!hapd->iface || !hapd->iface->interfaces)
+		return eid;
+
+	for (i = 0; i < hapd->iface->interfaces->count; i++) {
+		iface = hapd->iface->interfaces->iface[i];
+
+		if (iface == hapd->iface ||
+		    !is_6ghz_op_class(iface->conf->op_class))
+			continue;
+
+		eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
+					    current_len);
+	}
+
+	return eid;
+}
+
+
+u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+{
+	u8 *eid_start = eid;
+	size_t current_len = 0;
+	enum colocation_mode mode = get_colocation_mode(hapd);
+
+	switch (type) {
+	case WLAN_FC_STYPE_BEACON:
+		if (hapd->conf->rnr)
+			eid = hostapd_eid_nr_db(hapd, eid, &current_len);
+		/* fallthrough */
+
+	case WLAN_FC_STYPE_PROBE_RESP:
+		if (mode == COLOCATED_LOWER_BAND)
+			eid = hostapd_eid_rnr_colocation(hapd, eid,
+							 &current_len);
+
+		if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+			eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
+						    &current_len);
+		break;
+
+	case WLAN_FC_STYPE_ACTION:
+		if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
+			eid = hostapd_eid_rnr_iface(hapd, hapd,	eid,
+						    &current_len);
+		break;
+
+	default:
+		return eid_start;
+	}
+
+	if (eid == eid_start + 2)
+		return eid_start;
+
+	return eid;
+}
+
 #endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index ea8c608..c59ad5e 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -194,5 +194,7 @@
 
 void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
 u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
+size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
+u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
 
 #endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index c27bb1f..6cd6c90 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -192,6 +192,9 @@
 		params |= (hapd->iface->conf->he_op.he_rts_threshold <<
 			   HE_OPERATION_RTS_THRESHOLD_OFFSET);
 
+	if (hapd->iface->conf->he_op.he_er_su_disable)
+		params |= HE_OPERATION_ER_SU_DISABLE;
+
 	if (hapd->iface->conf->he_op.he_bss_color_disabled)
 		params |= HE_OPERATION_BSS_COLOR_DISABLED;
 	if (hapd->iface->conf->he_op.he_bss_color_partial)
@@ -216,7 +219,10 @@
 
 		params |= HE_OPERATION_6GHZ_OPER_INFO;
 
-		/* 6 GHz Operation Information field */
+		/* 6 GHz Operation Information field
+		 * IEEE P802.11ax/D8.0, 9.4.2.249 HE Operation element,
+		 * Figure 9-788k
+		 */
 		*pos++ = hapd->iconf->channel; /* Primary Channel */
 
 		/* Control: Channel Width */
@@ -226,6 +232,18 @@
 			*pos++ = center_idx_to_bw_6ghz(seg0);
 
 		/* Channel Center Freq Seg0/Seg1 */
+		if (hapd->iconf->he_oper_chwidth == 2) {
+			/*
+			 * Seg 0 indicates the channel center frequency index of
+			 * the 160 MHz channel.
+			 */
+			seg1 = seg0;
+			if (hapd->iconf->channel < seg0)
+				seg0 -= 8;
+			else
+				seg0 += 8;
+		}
+
 		*pos++ = seg0;
 		*pos++ = seg1;
 		/* Minimum Rate */
@@ -434,8 +452,8 @@
 		      enum ieee80211_op_mode opmode, const u8 *he_capab,
 		      size_t he_capab_len)
 {
-	if (!he_capab || !hapd->iconf->ieee80211ax ||
-	    hapd->conf->disable_11ax ||
+	if (!he_capab || !(sta->flags & WLAN_STA_WMM) ||
+	    !hapd->iconf->ieee80211ax || hapd->conf->disable_11ax ||
 	    !check_valid_he_mcs(hapd, he_capab, opmode) ||
 	    ieee80211_invalid_he_cap_size(he_capab, he_capab_len) ||
 	    he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
@@ -499,5 +517,6 @@
 
 	mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap;
 
-	return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER);
+	return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER) &&
+		hapd->iface->conf->he_op.he_twt_responder;
 }
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index a429b5d..4bff9e5 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -241,6 +241,12 @@
 			   (unsigned long) len);
 		return;
 	}
+	if (is_multicast_ether_addr(mgmt->da)) {
+		wpa_printf(MSG_DEBUG,
+			   "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
+			   MAC2STR(mgmt->da), MAC2STR(mgmt->sa));
+		return;
+	}
 
 	sta = ap_get_sta(hapd, sa);
 
@@ -445,70 +451,10 @@
 u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
 {
 	u8 *pos = eid;
-	u8 len = 0, i;
+	u8 len = EXT_CAPA_MAX_LEN, i;
 
-	if (hapd->conf->qos_map_set_len ||
-	    (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)))
-		len = 5;
-	if (len < 4 &&
-	    (hapd->conf->time_advertisement == 2 || hapd->conf->interworking))
-		len = 4;
-	if (len < 3 &&
-	    (hapd->conf->wnm_sleep_mode || hapd->conf->bss_transition))
-		len = 3;
-	if (len < 1 &&
-	    (hapd->iconf->obss_interval ||
-	     (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)))
-		len = 1;
-	if (len < 2 &&
-	    (hapd->conf->proxy_arp || hapd->conf->coloc_intf_reporting))
-		len = 2;
-	if (len < 7 && hapd->conf->ssid.utf8_ssid)
-		len = 7;
-	if (len < 9 &&
-	    (hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
-		len = 9;
-#ifdef CONFIG_WNM_AP
-	if (len < 4)
-		len = 4;
-#endif /* CONFIG_WNM_AP */
-#ifdef CONFIG_HS20
-	if (hapd->conf->hs20 && len < 6)
-		len = 6;
-#endif /* CONFIG_HS20 */
-#ifdef CONFIG_MBO
-	if (hapd->conf->mbo_enabled && len < 6)
-		len = 6;
-#endif /* CONFIG_MBO */
-#ifdef CONFIG_FILS
-	if ((!(hapd->conf->wpa & WPA_PROTO_RSN) ||
-	     !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
-		len = 10;
-#endif /* CONFIG_FILS */
-#ifdef CONFIG_IEEE80211AX
-	if (len < 10 && hapd->iconf->ieee80211ax &&
-	    hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
-		len = 10;
-#endif /* CONFIG_IEEE80211AX */
-#ifdef CONFIG_SAE
-	if (len < 11 && hapd->conf->wpa &&
-	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
-	    hostapd_sae_pw_id_in_use(hapd->conf))
-		len = 11;
-#endif /* CONFIG_SAE */
-	if (len < 11 && hapd->conf->beacon_prot &&
-	    (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
-		len = 11;
-#ifdef CONFIG_SAE_PK
-	if (len < 12 && hapd->conf->wpa &&
-	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
-	    hostapd_sae_pk_exclusively(hapd->conf))
-		len = 12;
-#endif /* CONFIG_SAE_PK */
 	if (len < hapd->iface->extended_capa_len)
 		len = hapd->iface->extended_capa_len;
-	if (len == 0)
-		return eid;
 
 	*pos++ = WLAN_EID_EXT_CAPAB;
 	*pos++ = len;
@@ -519,6 +465,11 @@
 			*pos &= ~hapd->iface->extended_capa_mask[i];
 			*pos |= hapd->iface->extended_capa[i];
 		}
+
+		if (i < EXT_CAPA_MAX_LEN) {
+			*pos &= ~hapd->conf->ext_capa_mask[i];
+			*pos |= hapd->conf->ext_capa[i];
+		}
 	}
 
 	while (len > 0 && eid[1 + len] == 0) {
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index d037022..828f0ab 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -171,7 +171,7 @@
 		       const u8 *vht_capab)
 {
 	/* Disable VHT caps for STAs associated to no-VHT BSSes. */
-	if (!vht_capab ||
+	if (!vht_capab || !(sta->flags & WLAN_STA_WMM) ||
 	    !hapd->iconf->ieee80211ac || hapd->conf->disable_11ac ||
 	    !check_valid_vht_mcs(hapd->iface->current_mode, vht_capab)) {
 		sta->flags &= ~WLAN_STA_VHT;
diff --git a/src/ap/ndisc_snoop.c b/src/ap/ndisc_snoop.c
index 4d6a92e..788c12f 100644
--- a/src/ap/ndisc_snoop.c
+++ b/src/ap/ndisc_snoop.c
@@ -150,10 +150,12 @@
 				return;
 		}
 		break;
+#ifdef CONFIG_HS20
 	case ROUTER_ADVERTISEMENT:
 		if (hapd->conf->disable_dgaf)
 			ucast_to_stas(hapd, buf, len);
 		break;
+#endif /* CONFIG_HS20 */
 	case NEIGHBOR_ADVERTISEMENT:
 		if (hapd->conf->na_mcast_to_ucast)
 			ucast_to_stas(hapd, buf, len);
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index 2bbe318..229edd2 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -10,6 +10,7 @@
 #include "utils/includes.h"
 
 #include "utils/common.h"
+#include "utils/crc32.h"
 #include "hostapd.h"
 #include "ieee802_11.h"
 #include "neighbor_db.h"
@@ -120,7 +121,8 @@
 int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
 			 const struct wpa_ssid_value *ssid,
 			 const struct wpabuf *nr, const struct wpabuf *lci,
-			 const struct wpabuf *civic, int stationary)
+			 const struct wpabuf *civic, int stationary,
+			 u8 bss_parameters)
 {
 	struct hostapd_neighbor_entry *entry;
 
@@ -134,6 +136,7 @@
 
 	os_memcpy(entry->bssid, bssid, ETH_ALEN);
 	os_memcpy(&entry->ssid, ssid, sizeof(entry->ssid));
+	entry->short_ssid = crc32(ssid->ssid, ssid->ssid_len);
 
 	entry->nr = wpabuf_dup(nr);
 	if (!entry->nr)
@@ -152,6 +155,7 @@
 	}
 
 	entry->stationary = stationary;
+	entry->bss_parameters = bss_parameters;
 
 	return 0;
 
@@ -311,7 +315,7 @@
 	wpabuf_put_u8(nr, center_freq2_idx);
 
 	hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
-			     hapd->iconf->civic, hapd->iconf->stationary_ap);
+			     hapd->iconf->civic, hapd->iconf->stationary_ap, 0);
 
 	wpabuf_free(nr);
 #endif /* NEED_AP_MLME */
diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
index bed0a2f..992671b 100644
--- a/src/ap/neighbor_db.h
+++ b/src/ap/neighbor_db.h
@@ -17,7 +17,8 @@
 int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
 			 const struct wpa_ssid_value *ssid,
 			 const struct wpabuf *nr, const struct wpabuf *lci,
-			 const struct wpabuf *civic, int stationary);
+			 const struct wpabuf *civic, int stationary,
+			 u8 bss_parameters);
 void hostapd_neighbor_set_own_report(struct hostapd_data *hapd);
 int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
 			    const struct wpa_ssid_value *ssid);
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index fe5f817..b67b852 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -516,7 +516,8 @@
 	for (entry = pmksa->pmksa; entry; entry = entry->next) {
 		if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
 			continue;
-		if (wpa_key_mgmt_sae(entry->akmp)) {
+		if (wpa_key_mgmt_sae(entry->akmp) ||
+		    wpa_key_mgmt_fils(entry->akmp)) {
 			if (os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)
 				return entry;
 			continue;
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index efa48e7..27e72f9 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -88,6 +88,7 @@
 	u16 group;
 	u8 trans_seq;
 	u8 wrapped_data_format;
+	size_t kdk_len;
 
 	u8 hash[SHA384_MAC_LEN];
 	struct wpa_ptk ptk;
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index d32967e..0042ed6 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -788,8 +788,8 @@
 
 int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
 			u8 req_mode, int disassoc_timer, u8 valid_int,
-			const u8 *bss_term_dur, const char *url,
-			const u8 *nei_rep, size_t nei_rep_len,
+			const u8 *bss_term_dur, u8 dialog_token,
+			const char *url, const u8 *nei_rep, size_t nei_rep_len,
 			const u8 *mbo_attrs, size_t mbo_len)
 {
 	u8 *buf, *pos;
@@ -797,8 +797,10 @@
 	size_t url_len;
 
 	wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
-		   MACSTR " req_mode=0x%x disassoc_timer=%d valid_int=0x%x",
-		   MAC2STR(sta->addr), req_mode, disassoc_timer, valid_int);
+		   MACSTR
+		   " req_mode=0x%x disassoc_timer=%d valid_int=0x%x dialog_token=%u",
+		   MAC2STR(sta->addr), req_mode, disassoc_timer, valid_int,
+		   dialog_token);
 	buf = os_zalloc(1000 + nei_rep_len + mbo_len);
 	if (buf == NULL)
 		return -1;
@@ -810,7 +812,7 @@
 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
 	mgmt->u.action.category = WLAN_ACTION_WNM;
 	mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
-	mgmt->u.action.u.bss_tm_req.dialog_token = 1;
+	mgmt->u.action.u.bss_tm_req.dialog_token = dialog_token;
 	mgmt->u.action.u.bss_tm_req.req_mode = req_mode;
 	mgmt->u.action.u.bss_tm_req.disassoc_timer =
 		host_to_le16(disassoc_timer);
diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h
index 1806ba0..f86c6b2 100644
--- a/src/ap/wnm_ap.h
+++ b/src/ap/wnm_ap.h
@@ -20,8 +20,8 @@
 				   int disassoc_timer);
 int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
 			u8 req_mode, int disassoc_timer, u8 valid_int,
-			const u8 *bss_term_dur, const char *url,
-			const u8 *nei_rep, size_t nei_rep_len,
+			const u8 *bss_term_dur, u8 dialog_token,
+			const char *url, const u8 *nei_rep, size_t nei_rep_len,
 			const u8 *mbo_attrs, size_t mbo_len);
 void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx);
 int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index e2e6e1f..bb7ee25 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1005,6 +1005,18 @@
 }
 
 
+static bool wpa_auth_gtk_rekey_in_process(struct wpa_authenticator *wpa_auth)
+{
+	struct wpa_group *group;
+
+	for (group = wpa_auth->group; group; group = group->next) {
+		if (group->GKeyDoneStations)
+			return true;
+	}
+	return false;
+}
+
+
 void wpa_receive(struct wpa_authenticator *wpa_auth,
 		 struct wpa_state_machine *sm,
 		 u8 *data, size_t data_len)
@@ -1372,7 +1384,11 @@
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
 					"received EAPOL-Key Request for GTK rekeying");
 			eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
-			wpa_rekey_gtk(wpa_auth, NULL);
+			if (wpa_auth_gtk_rekey_in_process(wpa_auth))
+				wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
+						"skip new GTK rekey - already in process");
+			else
+				wpa_rekey_gtk(wpa_auth, NULL);
 		}
 	} else {
 		/* Do not allow the same key replay counter to be reused. */
@@ -2292,8 +2308,7 @@
 
 	if (sm->wpa_auth->conf.force_kdk_derivation ||
 	    (sm->wpa_auth->conf.secure_ltf &&
-	     sm->rsnxe && sm->rsnxe_len >= 4 &&
-	     sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+	     ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
 		kdk_len = WPA_KDK_MAX_LEN;
 	else
 		kdk_len = 0;
@@ -2347,8 +2362,7 @@
 
 	if (sm->wpa_auth->conf.force_kdk_derivation ||
 	    (sm->wpa_auth->conf.secure_ltf &&
-	     sm->rsnxe && sm->rsnxe_len >= 4 &&
-	     sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+	     ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
 		kdk_len = WPA_KDK_MAX_LEN;
 	else
 		kdk_len = 0;
@@ -2737,7 +2751,7 @@
 	struct wpabuf *plain;
 	u8 *len, *tmp, *tmp2;
 	u8 hdr[2];
-	u8 *gtk, dummy_gtk[32];
+	u8 *gtk, stub_gtk[32];
 	size_t gtk_len;
 	struct wpa_group *gsm;
 	size_t plain_len;
@@ -2780,11 +2794,11 @@
 		 * Provide unique random GTK to each STA to prevent use
 		 * of GTK in the BSS.
 		 */
-		if (random_get_bytes(dummy_gtk, gtk_len) < 0) {
+		if (random_get_bytes(stub_gtk, gtk_len) < 0) {
 			wpabuf_clear_free(plain);
 			return NULL;
 		}
-		gtk = dummy_gtk;
+		gtk = stub_gtk;
 	}
 	hdr[0] = gsm->GN & 0x03;
 	hdr[1] = 0;
@@ -3367,7 +3381,7 @@
 
 SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 {
-	u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32];
+	u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
 	size_t gtk_len, kde_len, wpa_ie_len;
 	struct wpa_group *gsm = sm->group;
 	u8 *wpa_ie;
@@ -3453,9 +3467,9 @@
 			 * Provide unique random GTK to each STA to prevent use
 			 * of GTK in the BSS.
 			 */
-			if (random_get_bytes(dummy_gtk, gtk_len) < 0)
+			if (random_get_bytes(stub_gtk, gtk_len) < 0)
 				goto done;
-			gtk = dummy_gtk;
+			gtk = stub_gtk;
 		}
 		gtkidx = gsm->GN;
 		_rsc = rsc;
@@ -3689,6 +3703,8 @@
 	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
 			 "pairwise key handshake completed (%s)",
 			 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
+	wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
+		MACSTR, MAC2STR(sm->addr));
 
 #ifdef CONFIG_IEEE80211R_AP
 	wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
@@ -3846,7 +3862,7 @@
 	const u8 *kde;
 	u8 *kde_buf = NULL, *pos, hdr[2];
 	size_t kde_len;
-	u8 *gtk, dummy_gtk[32];
+	u8 *gtk, stub_gtk[32];
 	struct wpa_auth_config *conf = &sm->wpa_auth->conf;
 
 	SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
@@ -3878,9 +3894,9 @@
 		 * Provide unique random GTK to each STA to prevent use
 		 * of GTK in the BSS.
 		 */
-		if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0)
+		if (random_get_bytes(stub_gtk, gsm->GTK_len) < 0)
 			return;
-		gtk = dummy_gtk;
+		gtk = stub_gtk;
 	}
 	if (sm->wpa == WPA_VERSION_WPA2) {
 		kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
@@ -4276,7 +4292,7 @@
 	wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
 		   gsm->GN_bigtk);
 	wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
-			gsm->IGTK[gsm->GN_bigtk - 6], len);
+			gsm->BIGTK[gsm->GN_bigtk - 6], len);
 
 	return pos - start;
 }
@@ -4840,7 +4856,7 @@
 			const u8 *pmk, size_t pmk_len, const u8 *pmkid,
 			int session_timeout, int akmp)
 {
-	if (wpa_auth->conf.disable_pmksa_caching)
+	if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
 		return -1;
 
 	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
@@ -5638,6 +5654,18 @@
 }
 
 
+int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
+		       struct wpa_state_machine *sm)
+{
+	if (!wpa_auth || !sm)
+		return -1;
+	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
+	wpa_request_new_ptk(sm);
+	wpa_sm_step(sm);
+	return 0;
+}
+
+
 void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
 {
 	if (wpa_auth)
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 70c13f6..8f0b5a7 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -555,7 +555,12 @@
 int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
 			     void (*cb)(void *ctx1, void *ctx2),
 			     void *ctx1, void *ctx2);
+int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
+		       struct wpa_state_machine *sm);
 int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
+int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
+				const u8 *data, size_t data_len,
+				int encrypt);
 void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
 void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val);
 
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 32b7456..fef1104 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -455,7 +455,7 @@
 	pos += wpa_ft_tlv_lin(tlvs2, pos, endpos);
 	pos += wpa_ft_vlan_lin(vlan, pos, endpos);
 
-	/* sanity check */
+	/* validity check */
 	if (pos != endpos) {
 		wpa_printf(MSG_ERROR, "FT: Length error building RRB");
 		goto err;
@@ -2259,7 +2259,7 @@
 	const u8 *kek, *igtk;
 	size_t kek_len;
 	size_t igtk_len;
-	u8 dummy_igtk[WPA_IGTK_MAX_LEN];
+	u8 stub_igtk[WPA_IGTK_MAX_LEN];
 
 	if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
 		kek = sm->PTK.kek2;
@@ -2292,11 +2292,11 @@
 		 * Provide unique random IGTK to each STA to prevent use of
 		 * IGTK in the BSS.
 		 */
-		if (random_get_bytes(dummy_igtk, igtk_len / 8) < 0) {
+		if (random_get_bytes(stub_igtk, igtk_len / 8) < 0) {
 			os_free(subelem);
 			return NULL;
 		}
-		igtk = dummy_igtk;
+		igtk = stub_igtk;
 	}
 	if (aes_wrap(kek, kek_len, igtk_len / 8, igtk, pos)) {
 		wpa_printf(MSG_DEBUG,
@@ -2319,7 +2319,7 @@
 	const u8 *kek, *bigtk;
 	size_t kek_len;
 	size_t bigtk_len;
-	u8 dummy_bigtk[WPA_IGTK_MAX_LEN];
+	u8 stub_bigtk[WPA_IGTK_MAX_LEN];
 
 	if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
 		kek = sm->PTK.kek2;
@@ -2352,11 +2352,11 @@
 		 * Provide unique random BIGTK to each OSEN STA to prevent use
 		 * of BIGTK in the BSS.
 		 */
-		if (random_get_bytes(dummy_bigtk, bigtk_len / 8) < 0) {
+		if (random_get_bytes(stub_bigtk, bigtk_len / 8) < 0) {
 			os_free(subelem);
 			return NULL;
 		}
-		bigtk = dummy_bigtk;
+		bigtk = stub_bigtk;
 	}
 	if (aes_wrap(kek, kek_len, bigtk_len / 8, bigtk, pos)) {
 		wpa_printf(MSG_DEBUG,
@@ -3198,8 +3198,7 @@
 
 	if (sm->wpa_auth->conf.force_kdk_derivation ||
 	    (sm->wpa_auth->conf.secure_ltf &&
-	     sm->rsnxe && sm->rsnxe_len >= 4 &&
-	     sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+	     ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
 		kdk_len = WPA_KDK_MAX_LEN;
 	else
 		kdk_len = 0;
@@ -3591,7 +3590,7 @@
 	}
 
 	/*
-	 * Do some sanity checking on the target AP address (not own and not
+	 * Do some validity checking on the target AP address (not own and not
 	 * broadcast. This could be extended to filter based on a list of known
 	 * APs in the MD (if such a list were configured).
 	 */
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index e755018..9e88ea3 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -507,9 +507,9 @@
 }
 
 
-static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
-				       const u8 *data, size_t data_len,
-				       int encrypt)
+int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
+				const u8 *data, size_t data_len,
+				int encrypt)
 {
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta;
@@ -1555,7 +1555,8 @@
 		return -1;
 	}
 
-	hapd->ptksa = ptksa_cache_init();
+	if (!hapd->ptksa)
+		hapd->ptksa = ptksa_cache_init();
 	if (!hapd->ptksa) {
 		wpa_printf(MSG_ERROR, "Failed to allocate PTKSA cache");
 		return -1;
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index d471031..524922e 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -1169,7 +1169,7 @@
 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
 	if (suite == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
 		cipher = 63; /* No cipher suite selected */
-	if ((suite >> 8) == 0x000fac && ((suite & 0xff) <= 13))
+	else if ((suite >> 8) == 0x000fac && ((suite & 0xff) <= 13))
 		cipher = suite & 0xff;
 	else
 		cipher = 62; /* vendor specific */
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index e97dbf9..4f1c76b 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1172,6 +1172,8 @@
 			wps->auth_types |= WPS_AUTH_WPA2PSK;
 		if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
 			wps->auth_types |= WPS_AUTH_WPA2;
+		if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE)
+			wps->auth_types |= WPS_AUTH_WPA2PSK;
 
 		if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
 					  WPA_CIPHER_CCMP_256 |
@@ -1328,6 +1330,11 @@
 
 	hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd);
 
+#ifdef CONFIG_P2P
+	if ((hapd->conf->p2p & P2P_ENABLED) &&
+	    is_6ghz_op_class(hapd->iconf->op_class))
+		wps->use_passphrase = true;
+#endif /* CONFIG_P2P */
 	hapd->wps = wps;
 	bin_clear_free(multi_ap_netw_key, 2 * PMK_LEN);
 
@@ -1957,6 +1964,11 @@
 		cred.key_len = len / 2;
 	}
 
+	if (!hapd->wps) {
+		wpa_printf(MSG_ERROR, "WPS: WPS config does not exist");
+		return -1;
+	}
+
 	return wps_registrar_config_ap(hapd->wps->registrar, &cred);
 }
 
diff --git a/src/common/brcm_vendor.h b/src/common/brcm_vendor.h
index 0a44a6c..d77b007 100644
--- a/src/common/brcm_vendor.h
+++ b/src/common/brcm_vendor.h
@@ -1,6 +1,6 @@
 /*
  * Broadcom Corporation OUI and vendor specific assignments
- * Copyright (c) 2015, Broadcom Corporation.
+ * Copyright (c) 2020, Broadcom Corporation.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -16,21 +16,54 @@
  * hostap.git repository.
  */
 
-#define OUI_BRCM  0x001018
+#define OUI_BRCM    0x001018
 
 /**
  * enum brcm_nl80211_vendor_subcmds - BRCM nl80211 vendor command identifiers
  *
- * @BRCM_VENDOR_SUBCMD_UNSPEC: Reserved value 0
+ * @BRCM_VENDOR_SCMD_UNSPEC: Reserved value 0
  *
- * @BRCM_VENDOR_SUBCMD_PRIV_STR: String command/event
+ * @BRCM_VENDOR_SCMD_PRIV_STR: Provide vendor private cmds to send to FW.
+ *
+ * @BRCM_VENDOR_SCMD_BCM_STR:  Provide vendor cmds to BCMDHD driver.
+ *
+ * @BRCM_VENDOR_SCMD_BCM_PSK: Used to set SAE password.
+ *
+ * @BRCM_VENDOR_SCMD_SET_PMK: Command to check driver support
+ *	for DFS offloading.
+ *
+ * @BRCM_VENDOR_SCMD_GET_FEATURES: Command to get the features
+ *      supported by the driver.
+ *
+ * @BRCM_VENDOR_SCMD_SET_MAC: Set random mac address for P2P interface.
+ *
+ * @BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS: Set some connect parameters.
+ *      Used for the case that FW handle SAE.
+ *
+ * @BRCM_VENDOR_SCMD_SET_START_AP_PARAMS: Set SoftAP paramters.
+ *      Used for the case that FW handle SAE.
+ *
+ * @BRCM_VENDOR_SCMD_ACS: ACS command/event which is used to
+ *	invoke the ACS function in device and pass selected channels to
+ *	hostapd. Uses enum qca_wlan_vendor_attr_acs_offload attributes.
+ *
+ * @BRCM_VENDOR_SCMD_MAX: This acts as a the tail of cmds list.
+ *      Make sure it located at the end of the list.
+ *
  */
 enum brcm_nl80211_vendor_subcmds {
-	BRCM_VENDOR_SUBCMD_UNSPEC		= 0,
-	BRCM_VENDOR_SUBCMD_SET_PMK		= 4,
-	BRCM_VENDOR_SUBCMD_SET_MAC		= 6,
+	BRCM_VENDOR_SCMD_UNSPEC			= 0,
+	BRCM_VENDOR_SCMD_PRIV_STR		= 1,
+	BRCM_VENDOR_SCMD_BCM_STR		= 2,
+	BRCM_VENDOR_SCMD_BCM_PSK		= 3,
+	BRCM_VENDOR_SCMD_SET_PMK		= 4,
+	BRCM_VENDOR_SCMD_GET_FEATURES		= 5,
+	BRCM_VENDOR_SCMD_SET_MAC		= 6,
+	BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS	= 7,
+	BRCM_VENDOR_SCMD_SET_START_AP_PARAMS	= 8,
 	BRCM_VENDOR_SCMD_ACS			= 9,
-	BRCM_VENDOR_SCMD_MAX			= 10
+	BRCM_VENDOR_SCMD_SET_TD_POLICY		= 10,
+	BRCM_VENDOR_SCMD_MAX			= 11
 };
 
 /**
@@ -41,11 +74,67 @@
  * @BRCM_VENDOR_EVENT_PRIV_STR: String command/event
  */
 enum brcm_nl80211_vendor_events {
-        BRCM_VENDOR_EVENT_UNSPEC,
+	BRCM_VENDOR_EVENT_UNSPEC		= 0,
+	BRCM_VENDOR_EVENT_PRIV_STR		= 1,
+	GOOGLE_GSCAN_SIGNIFICANT_EVENT		= 2,
+	GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT	= 3,
+	GOOGLE_GSCAN_BATCH_SCAN_EVENT		= 4,
+	GOOGLE_SCAN_FULL_RESULTS_EVENT		= 5,
+	GOOGLE_RTT_COMPLETE_EVENT		= 6,
+	GOOGLE_SCAN_COMPLETE_EVENT		= 7,
+	GOOGLE_GSCAN_GEOFENCE_LOST_EVENT	= 8,
+	GOOGLE_SCAN_EPNO_EVENT			= 9,
+	GOOGLE_DEBUG_RING_EVENT			= 10,
+	GOOGLE_FW_DUMP_EVENT			= 11,
+	GOOGLE_PNO_HOTSPOT_FOUND_EVENT		= 12,
+	GOOGLE_RSSI_MONITOR_EVENT		= 13,
+	GOOGLE_MKEEP_ALIVE_EVENT		= 14,
+
+	/*
+	 * BRCM specific events should be placed after
+	 * the Generic events so that enums don't mismatch
+	 * between the DHD and HAL
+	 */
+	GOOGLE_NAN_EVENT_ENABLED		= 15,
+	GOOGLE_NAN_EVENT_DISABLED		= 16,
+	GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH	= 17,
+	GOOGLE_NAN_EVENT_REPLIED		= 18,
+	GOOGLE_NAN_EVENT_PUBLISH_TERMINATED	= 19,
+	GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED	= 20,
+	GOOGLE_NAN_EVENT_DE_EVENT		= 21,
+	GOOGLE_NAN_EVENT_FOLLOWUP		= 22,
+	GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND	= 23,
+	GOOGLE_NAN_EVENT_DATA_REQUEST		= 24,
+	GOOGLE_NAN_EVENT_DATA_CONFIRMATION	= 25,
+	GOOGLE_NAN_EVENT_DATA_END		= 26,
+	GOOGLE_NAN_EVENT_BEACON			= 27,
+	GOOGLE_NAN_EVENT_SDF			= 28,
+	GOOGLE_NAN_EVENT_TCA			= 29,
+	GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH	= 30,
+	GOOGLE_NAN_EVENT_UNKNOWN		= 31,
+	GOOGLE_ROAM_EVENT_START			= 32,
+	BRCM_VENDOR_EVENT_HANGED                = 33,
+	BRCM_VENDOR_EVENT_SAE_KEY               = 34,
+	BRCM_VENDOR_EVENT_BEACON_RECV           = 35,
+	BRCM_VENDOR_EVENT_PORT_AUTHORIZED       = 36,
+	GOOGLE_FILE_DUMP_EVENT			= 37,
+	BRCM_VENDOR_EVENT_CU			= 38,
+	BRCM_VENDOR_EVENT_WIPS			= 39,
+	NAN_ASYNC_RESPONSE_DISABLED		= 40,
+	BRCM_VENDOR_EVENT_RCC_INFO		= 41,
 	BRCM_VENDOR_EVENT_ACS			= 42,
-	BRCM_VENDOR_EVENT_LAST			= 44
+	BRCM_VENDOR_EVENT_LAST
+
 };
 
+#ifdef CONFIG_BRCM_SAE
+enum wifi_sae_key_attr {
+	BRCM_SAE_KEY_ATTR_BSSID,
+	BRCM_SAE_KEY_ATTR_PMK,
+	BRCM_SAE_KEY_ATTR_PMKID
+};
+#endif /* CONFIG_BRCM_SAE */
+
 enum wl_vendor_attr_acs_offload {
 	BRCM_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
 	BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ,
@@ -68,7 +157,8 @@
 	BRCM_ATTR_DRIVER_CMD            = 0,
 	BRCM_ATTR_DRIVER_KEY_PMK        = 1,
 	BRCM_ATTR_DRIVER_MAC_ADDR	= 3,
-	BRCM_ATTR_DRIVER_AFTER_LAST     = 5,
+	BRCM_ATTR_DRIVER_TD_POLICY	= 5,
+	BRCM_ATTR_DRIVER_AFTER_LAST     = 6,
 	BRCM_ATTR_DRIVER_MAX            = BRCM_ATTR_DRIVER_AFTER_LAST - 1,
 };
 #endif /* BRCM_VENDOR_H */
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index 50ce192..8aba713 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -256,87 +256,69 @@
 #ifdef CONFIG_SAE
 	struct sae_data sae;
 	int ret = -1;
-	/* IEEE P802.11-REVmd/D2.1, Annex J.10 */
-	const u8 addr1[ETH_ALEN] = { 0x82, 0x7b, 0x91, 0x9d, 0xd4, 0xb9 };
-	const u8 addr2[ETH_ALEN] = { 0x1e, 0xec, 0x49, 0xea, 0x64, 0x88 };
+	/* IEEE Std 802.11-2020, Annex J.10 */
+	const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
+	const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
 	const char *ssid = "byteme";
 	const char *pw = "mekmitasdigoat";
 	const char *pwid = "psk4internet";
 	const u8 local_rand[] = {
-		0xa9, 0x06, 0xf6, 0x1e, 0x4d, 0x3a, 0x5d, 0x4e,
-		0xb2, 0x96, 0x5f, 0xf3, 0x4c, 0xf9, 0x17, 0xdd,
-		0x04, 0x44, 0x45, 0xc8, 0x78, 0xc1, 0x7c, 0xa5,
-		0xd5, 0xb9, 0x37, 0x86, 0xda, 0x9f, 0x83, 0xcf
+		0x99, 0x24, 0x65, 0xfd, 0x3d, 0xaa, 0x3c, 0x60,
+		0xaa, 0x65, 0x65, 0xb7, 0xf6, 0x2a, 0x2a, 0x7f,
+		0x2e, 0x12, 0xdd, 0x12, 0xf1, 0x98, 0xfa, 0xf4,
+		0xfb, 0xed, 0x89, 0xd7, 0xff, 0x1a, 0xce, 0x94
 	};
 	const u8 local_mask[] = {
-		0x42, 0x34, 0xb4, 0xfb, 0x17, 0xaa, 0x43, 0x5c,
-		0x52, 0xfb, 0xfd, 0xeb, 0xe6, 0x40, 0x39, 0xb4,
-		0x34, 0x78, 0x20, 0x0e, 0x54, 0xff, 0x7b, 0x6e,
-		0x07, 0xb6, 0x9c, 0xad, 0x74, 0x15, 0x3c, 0x15
+		0x95, 0x07, 0xa9, 0x0f, 0x77, 0x7a, 0x04, 0x4d,
+		0x6a, 0x08, 0x30, 0xb9, 0x1e, 0xa3, 0xd5, 0xdd,
+		0x70, 0xbe, 0xce, 0x44, 0xe1, 0xac, 0xff, 0xb8,
+		0x69, 0x83, 0xb5, 0xe1, 0xbf, 0x9f, 0xb3, 0x22
 	};
 	const u8 local_commit[] = {
-		0x13, 0x00, 0xeb, 0x3b, 0xab, 0x19, 0x64, 0xe4,
-		0xa0, 0xab, 0x05, 0x92, 0x5d, 0xdf, 0x33, 0x39,
-		0x51, 0x91, 0x38, 0xbc, 0x65, 0xd6, 0xcd, 0xc0,
-		0xf8, 0x13, 0xdd, 0x6f, 0xd4, 0x34, 0x4e, 0xb4,
-		0xbf, 0xe4, 0x4b, 0x5c, 0x21, 0x59, 0x76, 0x58,
-		0xf4, 0xe3, 0xed, 0xdf, 0xb4, 0xb9, 0x9f, 0x25,
-		0xb4, 0xd6, 0x54, 0x0f, 0x32, 0xff, 0x1f, 0xd5,
-		0xc5, 0x30, 0xc6, 0x0a, 0x79, 0x44, 0x48, 0x61,
-		0x0b, 0xc6, 0xde, 0x3d, 0x92, 0xbd, 0xbb, 0xd4,
-		0x7d, 0x93, 0x59, 0x80, 0xca, 0x6c, 0xf8, 0x98,
-		0x8a, 0xb6, 0x63, 0x0b, 0xe6, 0x76, 0x4c, 0x88,
-		0x5c, 0xeb, 0x97, 0x93, 0x97, 0x0f, 0x69, 0x52,
-		0x17, 0xee, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
-		0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
-		0x74
+		0x13, 0x00, 0x2e, 0x2c, 0x0f, 0x0d, 0xb5, 0x24,
+		0x40, 0xad, 0x14, 0x6d, 0x96, 0x71, 0x14, 0xce,
+		0x00, 0x5c, 0xe1, 0xea, 0xb0, 0xaa, 0x2c, 0x2e,
+		0x5c, 0x28, 0x71, 0xb7, 0x74, 0xf6, 0xc2, 0x57,
+		0x5c, 0x65, 0xd5, 0xad, 0x9e, 0x00, 0x82, 0x97,
+		0x07, 0xaa, 0x36, 0xba, 0x8b, 0x85, 0x97, 0x38,
+		0xfc, 0x96, 0x1d, 0x08, 0x24, 0x35, 0x05, 0xf4,
+		0x7c, 0x03, 0x53, 0x76, 0xd7, 0xac, 0x4b, 0xc8,
+		0xd7, 0xb9, 0x50, 0x83, 0xbf, 0x43, 0x82, 0x7d,
+		0x0f, 0xc3, 0x1e, 0xd7, 0x78, 0xdd, 0x36, 0x71,
+		0xfd, 0x21, 0xa4, 0x6d, 0x10, 0x91, 0xd6, 0x4b,
+		0x6f, 0x9a, 0x1e, 0x12, 0x72, 0x62, 0x13, 0x25,
+		0xdb, 0xe1
 	};
 	const u8 peer_commit[] = {
-		0x13, 0x00, 0x55, 0x64, 0xf0, 0x45, 0xb2, 0xea,
-		0x1e, 0x56, 0x6c, 0xf1, 0xdd, 0x74, 0x1f, 0x70,
-		0xd9, 0xbe, 0x35, 0xd2, 0xdf, 0x5b, 0x9a, 0x55,
-		0x02, 0x94, 0x6e, 0xe0, 0x3c, 0xf8, 0xda, 0xe2,
-		0x7e, 0x1e, 0x05, 0xb8, 0x43, 0x0e, 0xb7, 0xa9,
-		0x9e, 0x24, 0x87, 0x7c, 0xe6, 0x9b, 0xaf, 0x3d,
-		0xc5, 0x80, 0xe3, 0x09, 0x63, 0x3d, 0x6b, 0x38,
-		0x5f, 0x83, 0xee, 0x1c, 0x3e, 0xc3, 0x59, 0x1f,
-		0x1a, 0x53, 0x93, 0xc0, 0x6e, 0x80, 0x5d, 0xdc,
-		0xeb, 0x2f, 0xde, 0x50, 0x93, 0x0d, 0xd7, 0xcf,
-		0xeb, 0xb9, 0x87, 0xc6, 0xff, 0x96, 0x66, 0xaf,
-		0x16, 0x4e, 0xb5, 0x18, 0x4d, 0x8e, 0x66, 0x62,
-		0xed, 0x6a, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
-		0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
-		0x74
+		0x13, 0x00, 0x59, 0x1b, 0x96, 0xf3, 0x39, 0x7f,
+		0xb9, 0x45, 0x10, 0x08, 0x48, 0xe7, 0xb5, 0x50,
+		0x54, 0x3b, 0x67, 0x20, 0xd8, 0x83, 0x37, 0xee,
+		0x93, 0xfc, 0x49, 0xfd, 0x6d, 0xf7, 0xe0, 0x8b,
+		0x52, 0x23, 0xe7, 0x1b, 0x9b, 0xb0, 0x48, 0xd3,
+		0x87, 0x3f, 0x20, 0x55, 0x69, 0x53, 0xa9, 0x6c,
+		0x91, 0x53, 0x6f, 0xd8, 0xee, 0x6c, 0xa9, 0xb4,
+		0xa6, 0x8a, 0x14, 0x8b, 0x05, 0x6a, 0x90, 0x9b,
+		0xe0, 0x3e, 0x83, 0xae, 0x20, 0x8f, 0x60, 0xf8,
+		0xef, 0x55, 0x37, 0x85, 0x80, 0x74, 0xdb, 0x06,
+		0x68, 0x70, 0x32, 0x39, 0x98, 0x62, 0x99, 0x9b,
+		0x51, 0x1e, 0x0a, 0x15, 0x52, 0xa5, 0xfe, 0xa3,
+		0x17, 0xc2
 	};
 	const u8 kck[] = {
-		0x59, 0x9d, 0x6f, 0x1e, 0x27, 0x54, 0x8b, 0xe8,
-		0x49, 0x9d, 0xce, 0xed, 0x2f, 0xec, 0xcf, 0x94,
-		0x81, 0x8c, 0xe1, 0xc7, 0x9f, 0x1b, 0x4e, 0xb3,
-		0xd6, 0xa5, 0x32, 0x28, 0xa0, 0x9b, 0xf3, 0xed
+		0x1e, 0x73, 0x3f, 0x6d, 0x9b, 0xd5, 0x32, 0x56,
+		0x28, 0x73, 0x04, 0x33, 0x88, 0x31, 0xb0, 0x9a,
+		0x39, 0x40, 0x6d, 0x12, 0x10, 0x17, 0x07, 0x3a,
+		0x5c, 0x30, 0xdb, 0x36, 0xf3, 0x6c, 0xb8, 0x1a
 	};
 	const u8 pmk[] = {
-		0x7a, 0xea, 0xd8, 0x6f, 0xba, 0x4c, 0x32, 0x21,
-		0xfc, 0x43, 0x7f, 0x5f, 0x14, 0xd7, 0x0d, 0x85,
-		0x4e, 0xa5, 0xd5, 0xaa, 0xc1, 0x69, 0x01, 0x16,
-		0x79, 0x30, 0x81, 0xed, 0xa4, 0xd5, 0x57, 0xc5
+		0x4e, 0x4d, 0xfa, 0xb1, 0xa2, 0xdd, 0x8a, 0xc1,
+		0xa9, 0x17, 0x90, 0xf9, 0x53, 0xfa, 0xaa, 0x45,
+		0x2a, 0xe5, 0xc6, 0x87, 0x3a, 0xb7, 0x5b, 0x63,
+		0x60, 0x5b, 0xa6, 0x63, 0xf8, 0xa7, 0xfe, 0x59
 	};
 	const u8 pmkid[] = {
-		0x40, 0xa0, 0x9b, 0x60, 0x17, 0xce, 0xbf, 0x00,
-		0x72, 0x84, 0x3b, 0x53, 0x52, 0xaa, 0x2b, 0x4f
-	};
-	const u8 local_confirm[] = {
-		0x01, 0x00, 0x12, 0xd9, 0xd5, 0xc7, 0x8c, 0x50,
-		0x05, 0x26, 0xd3, 0x6c, 0x41, 0xdb, 0xc5, 0x6a,
-		0xed, 0xf2, 0x91, 0x4c, 0xed, 0xdd, 0xd7, 0xca,
-		0xd4, 0xa5, 0x8c, 0x48, 0xf8, 0x3d, 0xbd, 0xe9,
-		0xfc, 0x77
-	};
-	const u8 peer_confirm[] = {
-		0x01, 0x00, 0x02, 0x87, 0x1c, 0xf9, 0x06, 0x89,
-		0x8b, 0x80, 0x60, 0xec, 0x18, 0x41, 0x43, 0xbe,
-		0x77, 0xb8, 0xc0, 0x8a, 0x80, 0x19, 0xb1, 0x3e,
-		0xb6, 0xd0, 0xae, 0xf0, 0xd8, 0x38, 0x3d, 0xfa,
-		0xc2, 0xfd
+		0x87, 0x47, 0xa6, 0x00, 0xee, 0xa3, 0xf9, 0xf2,
+		0x24, 0x75, 0xdf, 0x58, 0xca, 0x1e, 0x54, 0x98
 	};
 	struct wpabuf *buf = NULL;
 	struct crypto_bignum *mask = NULL;
@@ -412,7 +394,7 @@
 	if (!buf ||
 	    sae_set_group(&sae, 19) < 0 ||
 	    sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
-			       pwid, &sae) < 0)
+			       &sae) < 0)
 		goto fail;
 
 	/* Override local values based on SAE test vector */
@@ -434,7 +416,7 @@
 		goto fail;
 
 	/* Check that output matches the test vector */
-	if (sae_write_commit(&sae, buf, NULL, pwid) < 0)
+	if (sae_write_commit(&sae, buf, NULL, NULL) < 0)
 		goto fail;
 	wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
 
@@ -465,21 +447,6 @@
 		goto fail;
 	}
 
-	buf->used = 0;
-	sae.send_confirm = 1;
-	sae_write_confirm(&sae, buf);
-	wpa_hexdump_buf(MSG_DEBUG, "SAE: Confirm message", buf);
-
-	if (wpabuf_len(buf) != sizeof(local_confirm) ||
-	    os_memcmp(wpabuf_head(buf), local_confirm,
-		      sizeof(local_confirm)) != 0) {
-		wpa_printf(MSG_ERROR, "SAE: Mismatch in local confirm");
-		goto fail;
-	}
-
-	if (sae_check_confirm(&sae, peer_confirm, sizeof(peer_confirm)) < 0)
-		goto fail;
-
 	pt_info = sae_derive_pt(pt_groups,
 				(const u8 *) ssid, os_strlen(ssid),
 				(const u8 *) pw, os_strlen(pw), pwid);
diff --git a/src/common/dpp.c b/src/common/dpp.c
index e8697c5..42a9302 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -2,14 +2,13 @@
  * DPP functionality shared between hostapd and wpa_supplicant
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
 
 #include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
 
 #include "utils/common.h"
 #include "utils/base64.h"
@@ -27,10 +26,10 @@
 #include "dpp_i.h"
 
 
-static const char * dpp_netrole_str(enum dpp_netrole netrole);
-
 #ifdef CONFIG_TESTING_OPTIONS
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+int dpp_version_override = 3;
+#elif defined(CONFIG_DPP2)
 int dpp_version_override = 2;
 #else
 int dpp_version_override = 1;
@@ -38,22 +37,6 @@
 enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
 #endif /* CONFIG_TESTING_OPTIONS */
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-	(defined(LIBRESSL_VERSION_NUMBER) && \
-	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
-
-#ifdef CONFIG_DPP2
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
-{
-	if (pkey->type != EVP_PKEY_EC)
-		return NULL;
-	return pkey->pkey.ec;
-}
-#endif /* CONFIG_DPP2 */
-
-#endif
-
 
 void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
 {
@@ -180,7 +163,7 @@
 	os_free(info->info);
 	os_free(info->chan);
 	os_free(info->pk);
-	EVP_PKEY_free(info->pubkey);
+	crypto_ec_key_deinit(info->pubkey);
 	str_clear_free(info->configurator_params);
 	os_free(info);
 }
@@ -324,6 +307,8 @@
 		bi->version = 1;
 	else if (*version == '2')
 		bi->version = 2;
+	else if (*version == '3')
+		bi->version = 3;
 	else
 		wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
 
@@ -646,7 +631,8 @@
 		    macstr,
 		    bi->info ? "I:" : "", bi->info ? bi->info : "",
 		    bi->info ? ";" : "",
-		    DPP_VERSION == 2 ? "V:2;" : "",
+		    DPP_VERSION == 3 ? "V:3;" :
+		    (DPP_VERSION == 2 ? "V:2;" : ""),
 		    bi->pk);
 	return 0;
 }
@@ -1223,6 +1209,13 @@
 
 	wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
 
+	if (os_strstr(cmd, " conf=query")) {
+		auth->configurator_set = 0;
+		auth->use_config_query = true;
+		ret = 0;
+		goto fail;
+	}
+
 	pos = os_strstr(cmd, " configurator=");
 	if (!auth->conf && pos) {
 		pos += 14;
@@ -1268,9 +1261,9 @@
 	dpp_configuration_free(auth->conf2_ap);
 	dpp_configuration_free(auth->conf_sta);
 	dpp_configuration_free(auth->conf2_sta);
-	EVP_PKEY_free(auth->own_protocol_key);
-	EVP_PKEY_free(auth->peer_protocol_key);
-	EVP_PKEY_free(auth->reconfig_old_protocol_key);
+	crypto_ec_key_deinit(auth->own_protocol_key);
+	crypto_ec_key_deinit(auth->peer_protocol_key);
+	crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
 	wpabuf_free(auth->req_msg);
 	wpabuf_free(auth->resp_msg);
 	wpabuf_free(auth->conf_req);
@@ -1303,6 +1296,9 @@
 		dl_list_del(&auth->tmp_peer_bi->list);
 		dpp_bootstrap_info_free(auth->tmp_peer_bi);
 	}
+	os_free(auth->e_name);
+	os_free(auth->e_mud_url);
+	os_free(auth->e_band_support);
 #ifdef CONFIG_TESTING_OPTIONS
 	os_free(auth->config_obj_override);
 	os_free(auth->discovery_override);
@@ -1360,14 +1356,15 @@
 }
 
 
-int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
-		  const char *kid, const struct dpp_curve_params *curve)
+int dpp_build_jwk(struct wpabuf *buf, const char *name,
+		  struct crypto_ec_key *key, const char *kid,
+		  const struct dpp_curve_params *curve)
 {
 	struct wpabuf *pub;
 	const u8 *pos;
 	int ret = -1;
 
-	pub = dpp_get_pubkey_point(key, 0);
+	pub = crypto_ec_key_get_pubkey_point(key, 0);
 	if (!pub)
 		goto fail;
 
@@ -1412,7 +1409,7 @@
 }
 
 
-static const char * dpp_netrole_str(enum dpp_netrole netrole)
+const char * dpp_netrole_str(enum dpp_netrole netrole)
 {
 	switch (netrole) {
 	case DPP_NETROLE_STA:
@@ -1516,6 +1513,10 @@
 		json_value_sep(dppcon);
 		json_add_string(dppcon, "expiry", expiry);
 	}
+#ifdef CONFIG_DPP3
+	json_value_sep(dppcon);
+	json_add_int(dppcon, "version", auth->peer_version);
+#endif /* CONFIG_DPP3 */
 	json_end_object(dppcon);
 	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
 		   (const char *) wpabuf_head(dppcon));
@@ -1645,6 +1646,25 @@
 }
 
 
+static int dpp_get_peer_bi_id(struct dpp_authentication *auth)
+{
+	struct dpp_bootstrap_info *bi;
+
+	if (auth->peer_bi)
+		return auth->peer_bi->id;
+	if (auth->tmp_peer_bi)
+		return auth->tmp_peer_bi->id;
+
+	bi = os_zalloc(sizeof(*bi));
+	if (!bi)
+		return -1;
+	bi->id = dpp_next_id(auth->global);
+	dl_list_add(&auth->global->bootstrap, &bi->list);
+	auth->tmp_peer_bi = bi;
+	return bi->id;
+}
+
+
 static struct wpabuf *
 dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
 		   int idx, bool cert_req)
@@ -1673,10 +1693,19 @@
 			conf = auth->conf2_ap;
 	}
 	if (!conf) {
-		if (idx == 0)
+		if (idx == 0) {
+			if (auth->use_config_query) {
+				wpa_printf(MSG_DEBUG,
+					   "DPP: No configuration available for Enrollee(%s) - waiting for configuration",
+					   dpp_netrole_str(netrole));
+				auth->waiting_config = true;
+				dpp_get_peer_bi_id(auth);
+				return NULL;
+			}
 			wpa_printf(MSG_DEBUG,
 				   "DPP: No configuration available for Enrollee(%s) - reject configuration request",
 				   dpp_netrole_str(netrole));
+		}
 		return NULL;
 	}
 
@@ -1730,6 +1759,8 @@
 		}
 	}
 
+	if (!conf && auth->waiting_config)
+		return NULL;
 	if (conf || env_data)
 		status = DPP_STATUS_OK;
 	else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta &&
@@ -1978,6 +2009,8 @@
 		goto fail;
 	}
 	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
+	os_free(auth->e_name);
+	auth->e_name = os_strdup(token->string);
 
 	token = json_get_member(root, "wi-fi_tech");
 	if (!token || token->type != JSON_STRING) {
@@ -2017,6 +2050,8 @@
 		wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string);
 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s",
 			token->string);
+		os_free(auth->e_mud_url);
+		auth->e_mud_url = os_strdup(token->string);
 	}
 
 	token = json_get_member(root, "bandSupport");
@@ -2057,7 +2092,8 @@
 			}
 			pos += res;
 		}
-		os_free(opclass);
+		os_free(auth->e_band_support);
+		auth->e_band_support = opclass;
 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s",
 			txt);
 	}
@@ -2075,21 +2111,9 @@
 			goto cont;
 		}
 
-		if (auth->peer_bi) {
-			id = auth->peer_bi->id;
-		} else if (auth->tmp_peer_bi) {
-			id = auth->tmp_peer_bi->id;
-		} else {
-			struct dpp_bootstrap_info *bi;
-
-			bi = os_zalloc(sizeof(*bi));
-			if (!bi)
-				goto fail;
-			bi->id = dpp_next_id(auth->global);
-			dl_list_add(&auth->global->bootstrap, &bi->list);
-			auth->tmp_peer_bi = bi;
-			id = bi->id;
-		}
+		id = dpp_get_peer_bi_id(auth);
+		if (id < 0)
+			goto fail;
 
 		wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA");
 		txt = base64_encode_no_lf(wpabuf_head(cert_req),
@@ -2165,14 +2189,13 @@
 }
 
 
-EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
-			 const struct dpp_curve_params **key_curve)
+struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk,
+				     const struct dpp_curve_params **key_curve)
 {
 	struct json_token *token;
 	const struct dpp_curve_params *curve;
 	struct wpabuf *x = NULL, *y = NULL;
-	EC_GROUP *group;
-	EVP_PKEY *pkey = NULL;
+	struct crypto_ec_key *key = NULL;
 
 	token = json_get_member(jwk, "kty");
 	if (!token || token->type != JSON_STRING) {
@@ -2225,22 +2248,18 @@
 		goto fail;
 	}
 
-	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
-	if (!group) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
+	key = crypto_ec_key_set_pub(curve->ike_group, wpabuf_head(x),
+				    wpabuf_head(y), wpabuf_len(x));
+	if (!key)
 		goto fail;
-	}
 
-	pkey = dpp_set_pubkey_point_group(group, wpabuf_head(x), wpabuf_head(y),
-					  wpabuf_len(x));
-	EC_GROUP_free(group);
 	*key_curve = curve;
 
 fail:
 	wpabuf_free(x);
 	wpabuf_free(y);
 
-	return pkey;
+	return key;
 }
 
 
@@ -2330,7 +2349,7 @@
 {
 	struct json_token *root, *groups, *netkey, *token;
 	int ret = -1;
-	EVP_PKEY *key = NULL;
+	struct crypto_ec_key *key = NULL;
 	const struct dpp_curve_params *curve;
 	unsigned int rules = 0;
 
@@ -2397,7 +2416,7 @@
 		goto fail;
 	dpp_debug_print_key("DPP: Received netAccessKey", key);
 
-	if (EVP_PKEY_cmp(key, auth->own_protocol_key) != 1) {
+	if (crypto_ec_key_cmp(key, auth->own_protocol_key)) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: netAccessKey in connector does not match own protocol key");
 #ifdef CONFIG_TESTING_OPTIONS
@@ -2414,47 +2433,45 @@
 
 	ret = 0;
 fail:
-	EVP_PKEY_free(key);
+	crypto_ec_key_deinit(key);
 	json_free(root);
 	return ret;
 }
 
 
-static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign)
+static void dpp_copy_csign(struct dpp_config_obj *conf,
+			   struct crypto_ec_key *csign)
 {
-	unsigned char *der = NULL;
-	int der_len;
+	struct wpabuf *c_sign_key;
 
-	der_len = i2d_PUBKEY(csign, &der);
-	if (der_len <= 0)
+	c_sign_key = crypto_ec_key_get_subject_public_key(csign);
+	if (!c_sign_key)
 		return;
+
 	wpabuf_free(conf->c_sign_key);
-	conf->c_sign_key = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
+	conf->c_sign_key = c_sign_key;
 }
 
 
-static void dpp_copy_ppkey(struct dpp_config_obj *conf, EVP_PKEY *ppkey)
+static void dpp_copy_ppkey(struct dpp_config_obj *conf,
+			   struct crypto_ec_key *ppkey)
 {
-	unsigned char *der = NULL;
-	int der_len;
+	struct wpabuf *pp_key;
 
-	der_len = i2d_PUBKEY(ppkey, &der);
-	if (der_len <= 0)
+	pp_key = crypto_ec_key_get_subject_public_key(ppkey);
+	if (!pp_key)
 		return;
+
 	wpabuf_free(conf->pp_key);
-	conf->pp_key = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
+	conf->pp_key = pp_key;
 }
 
 
 static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
 				  struct dpp_config_obj *conf)
 {
-	unsigned char *der = NULL;
-	int der_len;
-	EC_KEY *eckey;
-	EVP_PKEY *own_key;
+	struct wpabuf *net_access_key;
+	struct crypto_ec_key *own_key;
 
 	own_key = auth->own_protocol_key;
 #ifdef CONFIG_DPP2
@@ -2462,19 +2479,13 @@
 	    auth->reconfig_old_protocol_key)
 		own_key = auth->reconfig_old_protocol_key;
 #endif /* CONFIG_DPP2 */
-	eckey = EVP_PKEY_get1_EC_KEY(own_key);
-	if (!eckey)
+
+	net_access_key = crypto_ec_key_get_ecprivate_key(own_key, true);
+	if (!net_access_key)
 		return;
 
-	der_len = i2d_ECPrivateKey(eckey, &der);
-	if (der_len <= 0) {
-		EC_KEY_free(eckey);
-		return;
-	}
 	wpabuf_free(auth->net_access_key);
-	auth->net_access_key = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
-	EC_KEY_free(eckey);
+	auth->net_access_key = net_access_key;
 }
 
 
@@ -2485,7 +2496,7 @@
 	struct dpp_signed_connector_info info;
 	struct json_token *token, *csign, *ppkey;
 	int ret = -1;
-	EVP_PKEY *csign_pub = NULL, *pp_pub = NULL;
+	struct crypto_ec_key *csign_pub = NULL, *pp_pub = NULL;
 	const struct dpp_curve_params *key_curve = NULL, *pp_curve = NULL;
 	const char *signed_connector;
 
@@ -2565,8 +2576,8 @@
 
 	ret = 0;
 fail:
-	EVP_PKEY_free(csign_pub);
-	EVP_PKEY_free(pp_pub);
+	crypto_ec_key_deinit(csign_pub);
+	crypto_ec_key_deinit(pp_pub);
 	os_free(info.payload);
 	return ret;
 }
@@ -2591,7 +2602,7 @@
 		return -1;
 	}
 	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag);
-	conf->certs = dpp_pkcs7_certs(conf->certbag);
+	conf->certs = crypto_pkcs7_get_certificates(conf->certbag);
 	if (!conf->certs) {
 		dpp_auth_fail(auth, "No certificates in certBag");
 		return -1;
@@ -3399,11 +3410,11 @@
 {
 	if (!conf)
 		return;
-	EVP_PKEY_free(conf->csign);
+	crypto_ec_key_deinit(conf->csign);
 	os_free(conf->kid);
 	os_free(conf->connector);
-	EVP_PKEY_free(conf->connector_key);
-	EVP_PKEY_free(conf->pp_key);
+	crypto_ec_key_deinit(conf->connector_key);
+	crypto_ec_key_deinit(conf->pp_key);
 	os_free(conf);
 }
 
@@ -3411,23 +3422,19 @@
 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
 			     size_t buflen)
 {
-	EC_KEY *eckey;
-	int key_len, ret = -1;
-	unsigned char *key = NULL;
+	struct wpabuf *key;
+	int ret = -1;
 
 	if (!conf->csign)
 		return -1;
 
-	eckey = EVP_PKEY_get1_EC_KEY(conf->csign);
-	if (!eckey)
+	key = crypto_ec_key_get_ecprivate_key(conf->csign, true);
+	if (!key)
 		return -1;
 
-	key_len = i2d_ECPrivateKey(eckey, &key);
-	if (key_len > 0)
-		ret = wpa_snprintf_hex(buf, buflen, key, key_len);
+	ret = wpa_snprintf_hex(buf, buflen, wpabuf_head(key), wpabuf_len(key));
 
-	EC_KEY_free(eckey);
-	OPENSSL_free(key);
+	wpabuf_clear_free(key);
 	return ret;
 }
 
@@ -3439,7 +3446,7 @@
 	size_t len[1];
 	int res;
 
-	csign_pub = dpp_get_pubkey_point(conf->csign, 1);
+	csign_pub = crypto_ec_key_get_pubkey_point(conf->csign, 1);
 	if (!csign_pub) {
 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
 		return -1;
@@ -3675,7 +3682,7 @@
 	struct json_token *root = NULL, *netkey, *token;
 	struct json_token *own_root = NULL;
 	enum dpp_status_error ret = 255, res;
-	EVP_PKEY *own_key = NULL, *peer_key = NULL;
+	struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
 	struct wpabuf *own_key_pub = NULL;
 	const struct dpp_curve_params *curve, *own_curve;
 	struct dpp_signed_connector_info info;
@@ -3733,6 +3740,14 @@
 		}
 	}
 
+#ifdef CONFIG_DPP3
+	token = json_get_member(root, "version");
+	if (token && token->type == JSON_NUMBER) {
+		wpa_printf(MSG_DEBUG, "DPP: version = %d", token->number);
+		intro->peer_version = token->number;
+	}
+#endif /* CONFIG_DPP3 */
+
 	netkey = json_get_member(root, "netAccessKey");
 	if (!netkey || netkey->type != JSON_OBJECT) {
 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
@@ -3781,15 +3796,35 @@
 		os_memset(intro, 0, sizeof(*intro));
 	os_memset(Nx, 0, sizeof(Nx));
 	os_free(info.payload);
-	EVP_PKEY_free(own_key);
+	crypto_ec_key_deinit(own_key);
 	wpabuf_free(own_key_pub);
-	EVP_PKEY_free(peer_key);
+	crypto_ec_key_deinit(peer_key);
 	json_free(root);
 	json_free(own_root);
 	return ret;
 }
 
 
+#ifdef CONFIG_DPP3
+int dpp_get_connector_version(const char *connector)
+{
+	struct json_token *root, *token;
+	int ver = -1;
+
+	root = dpp_parse_own_connector(connector);
+	if (!root)
+		return -1;
+
+	token = json_get_member(root, "version");
+	if (token && token->type == JSON_NUMBER)
+		ver = token->number;
+
+	json_free(root);
+	return ver;
+}
+#endif /* CONFIG_DPP3 */
+
+
 unsigned int dpp_next_id(struct dpp_global *dpp)
 {
 	struct dpp_bootstrap_info *bi;
@@ -4134,7 +4169,7 @@
 	wpa_printf(MSG_DEBUG,
 		   "DPP: Update own bootstrapping key to match peer curve from NFC handover");
 
-	EVP_PKEY_free(own_bi->pubkey);
+	crypto_ec_key_deinit(own_bi->pubkey);
 	own_bi->pubkey = NULL;
 
 	if (dpp_keygen(own_bi, peer_bi->curve->name, NULL, 0) < 0 ||
@@ -4280,33 +4315,24 @@
 				 struct dpp_asymmetric_key *key)
 {
 	struct dpp_configurator *conf;
-	const EC_KEY *eckey, *eckey_pp;
-	const EC_GROUP *group, *group_pp;
-	int nid;
-	const struct dpp_curve_params *curve;
+	const struct dpp_curve_params *curve, *curve_pp;
 
 	if (!key->csign || !key->pp_key)
 		return -1;
-	eckey = EVP_PKEY_get0_EC_KEY(key->csign);
-	if (!eckey)
-		return -1;
-	group = EC_KEY_get0_group(eckey);
-	if (!group)
-		return -1;
-	nid = EC_GROUP_get_curve_name(group);
-	curve = dpp_get_curve_nid(nid);
+
+	curve = dpp_get_curve_ike_group(crypto_ec_key_group(key->csign));
 	if (!curve) {
 		wpa_printf(MSG_INFO, "DPP: Unsupported group in c-sign-key");
 		return -1;
 	}
-	eckey_pp = EVP_PKEY_get0_EC_KEY(key->pp_key);
-	if (!eckey_pp)
+
+	curve_pp = dpp_get_curve_ike_group(crypto_ec_key_group(key->pp_key));
+	if (!curve_pp) {
+		wpa_printf(MSG_INFO, "DPP: Unsupported group in ppKey");
 		return -1;
-	group_pp = EC_KEY_get0_group(eckey_pp);
-	if (!group_pp)
-		return -1;
-	if (EC_GROUP_get_curve_name(group) !=
-	    EC_GROUP_get_curve_name(group_pp)) {
+	}
+
+	if (curve != curve_pp) {
 		wpa_printf(MSG_INFO,
 			   "DPP: Mismatch in c-sign-key and ppKey groups");
 		return -1;
diff --git a/src/common/dpp.h b/src/common/dpp.h
index 6e397c3..2f85ebd 100644
--- a/src/common/dpp.h
+++ b/src/common/dpp.h
@@ -2,6 +2,7 @@
  * DPP functionality shared between hostapd and wpa_supplicant
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -11,13 +12,11 @@
 #define DPP_H
 
 #ifdef CONFIG_DPP
-#include <openssl/x509.h>
-
 #include "utils/list.h"
 #include "common/wpa_common.h"
 #include "crypto/sha256.h"
+#include "crypto/crypto.h"
 
-struct crypto_ecdh;
 struct hostapd_ip_addr;
 struct dpp_global;
 struct json_token;
@@ -27,7 +26,9 @@
 #define DPP_VERSION (dpp_version_override)
 extern int dpp_version_override;
 #else /* CONFIG_TESTING_OPTIONS */
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+#define DPP_VERSION 3
+#elif defined(CONFIG_DPP2)
 #define DPP_VERSION 2
 #else
 #define DPP_VERSION 1
@@ -43,7 +44,7 @@
 	DPP_PA_AUTHENTICATION_CONF = 2,
 	DPP_PA_PEER_DISCOVERY_REQ = 5,
 	DPP_PA_PEER_DISCOVERY_RESP = 6,
-	DPP_PA_PKEX_EXCHANGE_REQ = 7,
+	DPP_PA_PKEX_V1_EXCHANGE_REQ = 7,
 	DPP_PA_PKEX_EXCHANGE_RESP = 8,
 	DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9,
 	DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
@@ -54,6 +55,7 @@
 	DPP_PA_RECONFIG_AUTH_REQ = 15,
 	DPP_PA_RECONFIG_AUTH_RESP = 16,
 	DPP_PA_RECONFIG_AUTH_CONF = 17,
+	DPP_PA_PKEX_EXCHANGE_REQ = 18,
 };
 
 enum dpp_attribute_id {
@@ -157,7 +159,7 @@
 	bool channels_listed;
 	u8 version;
 	int own;
-	EVP_PKEY *pubkey;
+	struct crypto_ec_key *pubkey;
 	u8 pubkey_hash[SHA256_MAC_LEN];
 	u8 pubkey_hash_chirp[SHA256_MAC_LEN];
 	const struct dpp_curve_params *curve;
@@ -175,23 +177,26 @@
 	unsigned int initiator:1;
 	unsigned int exchange_done:1;
 	unsigned int failed:1;
+	unsigned int v2:1;
+	unsigned int forced_ver:1;
 	struct dpp_bootstrap_info *own_bi;
 	u8 own_mac[ETH_ALEN];
 	u8 peer_mac[ETH_ALEN];
 	char *identifier;
 	char *code;
-	EVP_PKEY *x;
-	EVP_PKEY *y;
+	struct crypto_ec_key *x;
+	struct crypto_ec_key *y;
 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
 	u8 z[DPP_MAX_HASH_LEN];
-	EVP_PKEY *peer_bootstrap_key;
+	struct crypto_ec_key *peer_bootstrap_key;
 	struct wpabuf *exchange_req;
 	struct wpabuf *exchange_resp;
 	unsigned int t; /* number of failures on code use */
 	unsigned int exch_req_wait_time;
 	unsigned int exch_req_tries;
 	unsigned int freq;
+	u8 peer_version;
 };
 
 enum dpp_akm {
@@ -234,8 +239,8 @@
 
 struct dpp_asymmetric_key {
 	struct dpp_asymmetric_key *next;
-	EVP_PKEY *csign;
-	EVP_PKEY *pp_key;
+	struct crypto_ec_key *csign;
+	struct crypto_ec_key *pp_key;
 	char *config_template;
 	char *connector_template;
 };
@@ -267,9 +272,9 @@
 	u8 i_capab;
 	u8 r_capab;
 	enum dpp_netrole e_netrole;
-	EVP_PKEY *own_protocol_key;
-	EVP_PKEY *peer_protocol_key;
-	EVP_PKEY *reconfig_old_protocol_key;
+	struct crypto_ec_key *own_protocol_key;
+	struct crypto_ec_key *peer_protocol_key;
+	struct crypto_ec_key *reconfig_old_protocol_key;
 	struct wpabuf *req_msg;
 	struct wpabuf *resp_msg;
 	struct wpabuf *reconfig_req_msg;
@@ -348,8 +353,13 @@
 	char *trusted_eap_server_name;
 	struct wpabuf *cacert;
 	struct wpabuf *certbag;
-	void *cert_resp_ctx;
+	void *config_resp_ctx;
 	void *gas_server_ctx;
+	bool use_config_query;
+	bool waiting_config;
+	char *e_name;
+	char *e_mud_url;
+	int *e_band_support;
 #ifdef CONFIG_TESTING_OPTIONS
 	char *config_obj_override;
 	char *discovery_override;
@@ -364,19 +374,20 @@
 	struct dl_list list;
 	unsigned int id;
 	int own;
-	EVP_PKEY *csign;
+	struct crypto_ec_key *csign;
 	u8 kid_hash[SHA256_MAC_LEN];
 	char *kid;
 	const struct dpp_curve_params *curve;
 	char *connector; /* own Connector for reconfiguration */
-	EVP_PKEY *connector_key;
-	EVP_PKEY *pp_key;
+	struct crypto_ec_key *connector_key;
+	struct crypto_ec_key *pp_key;
 };
 
 struct dpp_introduction {
 	u8 pmkid[PMKID_LEN];
 	u8 pmk[PMK_LEN_MAX];
 	size_t pmk_len;
+	int peer_version;
 };
 
 struct dpp_relay_config {
@@ -400,6 +411,7 @@
 	void *msg_ctx;
 	void *cb_ctx;
 	int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+	bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
 };
 
 #ifdef CONFIG_TESTING_OPTIONS
@@ -496,6 +508,10 @@
 	DPP_TEST_STOP_AT_AUTH_CONF = 89,
 	DPP_TEST_STOP_AT_CONF_REQ = 90,
 	DPP_TEST_REJECT_CONFIG = 91,
+	DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ = 92,
+	DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP = 93,
+	DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ = 94,
+	DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP = 95,
 };
 
 extern enum dpp_test_behavior dpp_test;
@@ -517,6 +533,7 @@
 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
 int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
 		      struct dpp_bootstrap_info *peer_bi);
+const char * dpp_netrole_str(enum dpp_netrole netrole);
 struct dpp_authentication *
 dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx);
 struct hostapd_hw_modes;
@@ -546,6 +563,9 @@
 		     const u8 *attr_start, size_t attr_len);
 int dpp_notify_new_qr_code(struct dpp_authentication *auth,
 			   struct dpp_bootstrap_info *peer_bi);
+void dpp_controller_pkex_add(struct dpp_global *dpp,
+			     struct dpp_bootstrap_info *bi,
+			     const char *code, const char *identifier);
 struct dpp_configuration * dpp_configuration_alloc(const char *type);
 int dpp_akm_psk(enum dpp_akm akm);
 int dpp_akm_sae(enum dpp_akm akm);
@@ -598,17 +618,18 @@
 	       const u8 *csign_key, size_t csign_key_len,
 	       const u8 *peer_connector, size_t peer_connector_len,
 	       os_time_t *expiry);
+int dpp_get_connector_version(const char *connector);
 struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
 				const u8 *own_mac,
-				const char *identifier,
-				const char *code);
+				const char *identifier, const char *code,
+				bool v2);
 struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
 					   struct dpp_bootstrap_info *bi,
 					   const u8 *own_mac,
 					   const u8 *peer_mac,
 					   const char *identifier,
 					   const char *code,
-					   const u8 *buf, size_t len);
+					   const u8 *buf, size_t len, bool v2);
 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
 					  const u8 *peer_mac,
 					  const u8 *buf, size_t len);
@@ -636,7 +657,6 @@
 
 struct wpabuf * dpp_build_csr(struct dpp_authentication *auth,
 			      const char *name);
-struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7);
 int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr);
 
 struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
@@ -672,22 +692,43 @@
 			     struct dpp_relay_config *config);
 int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
 			const u8 *buf, size_t len, unsigned int freq,
-			const u8 *i_bootstrap, const u8 *r_bootstrap);
+			const u8 *i_bootstrap, const u8 *r_bootstrap,
+			void *cb_ctx);
 int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
 			 size_t data_len);
 int dpp_controller_start(struct dpp_global *dpp,
 			 struct dpp_controller_config *config);
 void dpp_controller_stop(struct dpp_global *dpp);
+void dpp_controller_stop_for_ctx(struct dpp_global *dpp, void *cb_ctx);
 struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
 						    unsigned int id);
 void dpp_controller_new_qr_code(struct dpp_global *dpp,
 				struct dpp_bootstrap_info *bi);
+int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
+		      const struct hostapd_ip_addr *addr, int port,
+		      void *msg_ctx, void *cb_ctx,
+		      int (*pkex_done)(void *ctx, void *conn,
+				       struct dpp_bootstrap_info *bi));
 int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
 		 const struct hostapd_ip_addr *addr, int port,
 		 const char *name, enum dpp_netrole netrole, void *msg_ctx,
 		 void *cb_ctx,
 		 int (*process_conf_obj)(void *ctx,
-					 struct dpp_authentication *auth));
+					 struct dpp_authentication *auth),
+		 bool (*tcp_msg_sent)(void *ctx,
+				      struct dpp_authentication *auth));
+int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
+		 struct dpp_authentication *auth, const char *name,
+		 enum dpp_netrole netrole,
+		 int (*process_conf_obj)(void *ctx,
+					 struct dpp_authentication *auth),
+		 bool (*tcp_msg_sent)(void *ctx,
+				      struct dpp_authentication *auth));
+bool dpp_tcp_conn_status_requested(struct dpp_global *dpp);
+void dpp_tcp_send_conn_status(struct dpp_global *dpp,
+			      enum dpp_status_error result,
+			      const u8 *ssid, size_t ssid_len,
+			      const char *channel_list);
 
 struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi);
 void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
diff --git a/src/common/dpp_auth.c b/src/common/dpp_auth.c
index 0cabd64..f81f1ee 100644
--- a/src/common/dpp_auth.c
+++ b/src/common/dpp_auth.c
@@ -456,7 +456,7 @@
 #endif /* CONFIG_TESTING_OPTIONS */
 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
 
-	EVP_PKEY_free(auth->own_protocol_key);
+	crypto_ec_key_deinit(auth->own_protocol_key);
 #ifdef CONFIG_TESTING_OPTIONS
 	if (dpp_protocol_key_override_len) {
 		const struct dpp_curve_params *tmp_curve;
@@ -475,7 +475,7 @@
 	if (!auth->own_protocol_key)
 		goto fail;
 
-	pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+	pr = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
 	if (!pr)
 		goto fail;
 
@@ -671,8 +671,7 @@
 		unsigned int freq, const u8 *hdr, const u8 *attr_start,
 		size_t attr_len)
 {
-	EVP_PKEY *pi = NULL;
-	EVP_PKEY_CTX *ctx = NULL;
+	struct crypto_ec_key *pi = NULL;
 	size_t secret_len;
 	const u8 *addr[2];
 	size_t len[2];
@@ -928,8 +927,7 @@
 	return auth;
 fail:
 	bin_clear_free(unwrapped, unwrapped_len);
-	EVP_PKEY_free(pi);
-	EVP_PKEY_CTX_free(ctx);
+	crypto_ec_key_deinit(pi);
 	dpp_auth_deinit(auth);
 	return NULL;
 }
@@ -1235,7 +1233,7 @@
 	if (!auth->own_protocol_key)
 		goto fail;
 
-	pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+	pi = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
 	if (!pi)
 		goto fail;
 
@@ -1405,7 +1403,7 @@
 dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
 		 const u8 *attr_start, size_t attr_len)
 {
-	EVP_PKEY *pr;
+	struct crypto_ec_key *pr;
 	size_t secret_len;
 	const u8 *addr[2];
 	size_t len[2];
@@ -1567,7 +1565,7 @@
 		dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
 		goto fail;
 	}
-	EVP_PKEY_free(auth->peer_protocol_key);
+	crypto_ec_key_deinit(auth->peer_protocol_key);
 	auth->peer_protocol_key = pr;
 	pr = NULL;
 
@@ -1737,7 +1735,7 @@
 fail:
 	bin_clear_free(unwrapped, unwrapped_len);
 	bin_clear_free(unwrapped2, unwrapped2_len);
-	EVP_PKEY_free(pr);
+	crypto_ec_key_deinit(pr);
 	return NULL;
 }
 
diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c
index 3b81f09..fb3f776 100644
--- a/src/common/dpp_backup.c
+++ b/src/common/dpp_backup.c
@@ -7,8 +7,6 @@
  */
 
 #include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
 
 #include "utils/common.h"
 #include "crypto/aes.h"
@@ -19,28 +17,13 @@
 
 #ifdef CONFIG_DPP2
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-	(defined(LIBRESSL_VERSION_NUMBER) && \
-	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
-
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
-{
-	if (pkey->type != EVP_PKEY_EC)
-		return NULL;
-	return pkey->pkey.ec;
-}
-
-#endif
-
-
 void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key)
 {
 	while (key) {
 		struct dpp_asymmetric_key *next = key->next;
 
-		EVP_PKEY_free(key->csign);
-		EVP_PKEY_free(key->pp_key);
+		crypto_ec_key_deinit(key->csign);
+		crypto_ec_key_deinit(key->pp_key);
 		str_clear_free(key->config_template);
 		str_clear_free(key->connector_template);
 		os_free(key);
@@ -56,23 +39,13 @@
 	/* TODO: proper template values */
 	const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}";
 	const char *connector_template = NULL;
-	EC_KEY *eckey;
-	unsigned char *der = NULL;
-	int der_len;
 
 	if (!conf->pp_key)
 		return NULL;
-	eckey = EVP_PKEY_get0_EC_KEY(conf->pp_key);
-	if (!eckey)
-		return NULL;
 
-	EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
-	der_len = i2d_ECPrivateKey(eckey, &der);
-	if (der_len > 0)
-		priv_key = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
+	priv_key = crypto_ec_key_get_ecprivate_key(conf->pp_key, false);
 	if (!priv_key)
-		goto fail;
+		return NULL;
 
 	len = 100 + os_strlen(conf_template);
 	if (connector_template)
@@ -178,20 +151,11 @@
 static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth)
 {
 	struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL;
-	EC_KEY *eckey;
-	unsigned char *der = NULL;
-	int der_len;
 
-	eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign);
-	if (!eckey)
+	priv_key = crypto_ec_key_get_ecprivate_key(auth->conf->csign, false);
+	if (!priv_key)
 		return NULL;
 
-	EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
-	der_len = i2d_ECPrivateKey(eckey, &der);
-	if (der_len > 0)
-		priv_key = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
-
 	alg = dpp_build_key_alg(auth->conf->curve);
 
 	/* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */
@@ -592,11 +556,9 @@
 	 * Shall always use the pwri CHOICE.
 	 */
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 3) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected CHOICE [3] (pwri) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 3)) {
+		asn1_unexpected(&hdr, "DPP: Expected CHOICE [3] (pwri)");
 		return -1;
 	}
 	wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo",
@@ -629,11 +591,10 @@
 	wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version",
 		    pos, end - pos);
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected keyDerivationAlgorithm [0] - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"DPP: Expected keyDerivationAlgorithm [0]");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -672,11 +633,9 @@
 	pos = hdr.payload;
 
 	if (asn1_get_next(pos, e_end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected OCTETSTRING (salt.specified) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"DPP: Expected OCTETSTRING (salt.specified)");
 		return -1;
 	}
 	wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified",
@@ -752,11 +711,9 @@
 	 * EncryptedKey ::= OCTET STRING
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected OCTETSTRING (pwri.encryptedKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"DPP: Expected OCTETSTRING (pwri.encryptedKey)");
 		return -1;
 	}
 	wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey",
@@ -825,11 +782,10 @@
 
 	/* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
 	 * EncryptedContent ::= OCTET STRING */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected [0] IMPLICIT (EncryptedContent) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"DPP: Expected [0] IMPLICIT (EncryptedContent)");
 		return -1;
 	}
 	wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent",
@@ -884,11 +840,9 @@
 		return -1;
 	}
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected SET (RecipientInfos) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+		asn1_unexpected(&hdr,
+				"DPP: Expected SET (RecipientInfos)");
 		return -1;
 	}
 
@@ -910,7 +864,6 @@
 	struct asn1_oid oid;
 	char txt[80];
 	struct dpp_asymmetric_key *key;
-	EC_KEY *eckey;
 
 	wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len);
 
@@ -977,28 +930,17 @@
 	 *    (Contains DER encoding of ECPrivateKey)
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"DPP: Expected OCTETSTRING (PrivateKey)");
 		goto fail;
 	}
 	wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey",
 			hdr.payload, hdr.length);
 	pos = hdr.payload + hdr.length;
-	eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length);
-	if (!eckey) {
-		wpa_printf(MSG_INFO,
-			   "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+	key->csign = crypto_ec_key_parse_priv(hdr.payload, hdr.length);
+	if (!key->csign)
 		goto fail;
-	}
-	key->csign = EVP_PKEY_new();
-	if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) {
-		EC_KEY_free(eckey);
-		goto fail;
-	}
 	if (wpa_debug_show_keys)
 		dpp_debug_print_key("DPP: Received c-sign-key", key->csign);
 
@@ -1007,11 +949,9 @@
 	 *
 	 * Exactly one instance of type Attribute in OneAsymmetricKey.
 	 */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected [0] Attributes - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr, "DPP: Expected [0] Attributes");
 		goto fail;
 	}
 	wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes",
@@ -1025,11 +965,8 @@
 	pos = hdr.payload;
 	end = hdr.payload + hdr.length;
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected SET (Attributes) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+		asn1_unexpected(&hdr, "DPP: Expected SET (Attributes)");
 		goto fail;
 	}
 	if (hdr.payload + hdr.length < end) {
@@ -1075,11 +1012,8 @@
 		goto fail;
 	}
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected SET (Attribute) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+		asn1_unexpected(&hdr, "DPP: Expected SET (Attribute)");
 		goto fail;
 	}
 	pos = hdr.payload;
@@ -1109,38 +1043,24 @@
 	 *    (Contains DER encoding of ECPrivateKey)
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr, "DPP: Expected OCTETSTRING (PrivateKey)");
 		goto fail;
 	}
 	wpa_hexdump_key(MSG_MSGDUMP, "DPP: privacyProtectionKey",
 			hdr.payload, hdr.length);
 	pos = hdr.payload + hdr.length;
-	eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length);
-	if (!eckey) {
-		wpa_printf(MSG_INFO,
-			   "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+	key->pp_key = crypto_ec_key_parse_priv(hdr.payload, hdr.length);
+	if (!key->pp_key)
 		goto fail;
-	}
-	key->pp_key = EVP_PKEY_new();
-	if (!key->pp_key || EVP_PKEY_assign_EC_KEY(key->pp_key, eckey) != 1) {
-		EC_KEY_free(eckey);
-		goto fail;
-	}
 	if (wpa_debug_show_keys)
 		dpp_debug_print_key("DPP: Received privacyProtectionKey",
 				    key->pp_key);
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_UTF8STRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected UTF8STRING (configurationTemplate) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_utf8string(&hdr)) {
+		asn1_unexpected(&hdr,
+				"DPP: Expected UTF8STRING (configurationTemplate)");
 		goto fail;
 	}
 	wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate",
@@ -1154,11 +1074,9 @@
 
 	if (pos < end) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_UTF8STRING) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Expected UTF8STRING (connectorTemplate) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_utf8string(&hdr)) {
+			asn1_unexpected(&hdr,
+					"DPP: Expected UTF8STRING (connectorTemplate)");
 			goto fail;
 		}
 		wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate",
diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c
index c75fc78..4fac7de 100644
--- a/src/common/dpp_crypto.c
+++ b/src/common/dpp_crypto.c
@@ -8,11 +8,6 @@
  */
 
 #include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/pem.h>
 
 #include "utils/common.h"
 #include "utils/base64.h"
@@ -22,42 +17,11 @@
 #include "crypto/random.h"
 #include "crypto/sha384.h"
 #include "crypto/sha512.h"
+#include "tls/asn1.h"
 #include "dpp.h"
 #include "dpp_i.h"
 
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-	(defined(LIBRESSL_VERSION_NUMBER) && \
-	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
-
-static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
-{
-	sig->r = r;
-	sig->s = s;
-	return 1;
-}
-
-
-static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
-			   const BIGNUM **ps)
-{
-	if (pr)
-		*pr = sig->r;
-	if (ps)
-		*ps = sig->s;
-}
-
-
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
-{
-	if (pkey->type != EVP_PKEY_EC)
-		return NULL;
-	return pkey->pkey.ec;
-}
-
-#endif
-
 static const struct dpp_curve_params dpp_curves[] = {
 	/* The mandatory to support and the default NIST P-256 curve needs to
 	 * be the first entry on this list. */
@@ -101,36 +65,6 @@
 }
 
 
-static const struct dpp_curve_params *
-dpp_get_curve_oid(const ASN1_OBJECT *poid)
-{
-	ASN1_OBJECT *oid;
-	int i;
-
-	for (i = 0; dpp_curves[i].name; i++) {
-		oid = OBJ_txt2obj(dpp_curves[i].name, 0);
-		if (oid && OBJ_cmp(poid, oid) == 0)
-			return &dpp_curves[i];
-	}
-	return NULL;
-}
-
-
-const struct dpp_curve_params * dpp_get_curve_nid(int nid)
-{
-	int i, tmp;
-
-	if (!nid)
-		return NULL;
-	for (i = 0; dpp_curves[i].name; i++) {
-		tmp = OBJ_txt2nid(dpp_curves[i].name);
-		if (tmp == nid)
-			return &dpp_curves[i];
-	}
-	return NULL;
-}
-
-
 const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group)
 {
 	int i;
@@ -143,90 +77,22 @@
 }
 
 
-void dpp_debug_print_point(const char *title, const EC_GROUP *group,
-			   const EC_POINT *point)
+void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
 {
-	BIGNUM *x, *y;
-	BN_CTX *ctx;
-	char *x_str = NULL, *y_str = NULL;
+	struct wpabuf *der = NULL;
 
-	if (!wpa_debug_show_keys)
-		return;
+	crypto_ec_key_debug_print(key, title);
 
-	ctx = BN_CTX_new();
-	x = BN_new();
-	y = BN_new();
-	if (!ctx || !x || !y ||
-	    EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1)
-		goto fail;
-
-	x_str = BN_bn2hex(x);
-	y_str = BN_bn2hex(y);
-	if (!x_str || !y_str)
-		goto fail;
-
-	wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str);
-
-fail:
-	OPENSSL_free(x_str);
-	OPENSSL_free(y_str);
-	BN_free(x);
-	BN_free(y);
-	BN_CTX_free(ctx);
-}
-
-
-void dpp_debug_print_key(const char *title, EVP_PKEY *key)
-{
-	EC_KEY *eckey;
-	BIO *out;
-	size_t rlen;
-	char *txt;
-	int res;
-	unsigned char *der = NULL;
-	int der_len;
-	const EC_GROUP *group;
-	const EC_POINT *point;
-
-	out = BIO_new(BIO_s_mem());
-	if (!out)
-		return;
-
-	EVP_PKEY_print_private(out, key, 0, NULL);
-	rlen = BIO_ctrl_pending(out);
-	txt = os_malloc(rlen + 1);
-	if (txt) {
-		res = BIO_read(out, txt, rlen);
-		if (res > 0) {
-			txt[res] = '\0';
-			wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
-		}
-		os_free(txt);
-	}
-	BIO_free(out);
-
-	eckey = EVP_PKEY_get1_EC_KEY(key);
-	if (!eckey)
-		return;
-
-	group = EC_KEY_get0_group(eckey);
-	point = EC_KEY_get0_public_key(eckey);
-	if (group && point)
-		dpp_debug_print_point(title, group, point);
-
-	der_len = i2d_ECPrivateKey(eckey, &der);
-	if (der_len > 0)
-		wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
-	OPENSSL_free(der);
-	if (der_len <= 0) {
-		der = NULL;
-		der_len = i2d_EC_PUBKEY(eckey, &der);
-		if (der_len > 0)
-			wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
-		OPENSSL_free(der);
+	der = crypto_ec_key_get_ecprivate_key(key, true);
+	if (der) {
+		wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
+	} else {
+		der = crypto_ec_key_get_subject_public_key(key);
+		if (der)
+			wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
 	}
 
-	EC_KEY_free(eckey);
+	wpabuf_clear_free(der);
 }
 
 
@@ -363,336 +229,65 @@
 #endif /* CONFIG_DPP2 */
 
 
-int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len)
+struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
+					    const u8 *buf, size_t len)
 {
-	int num_bytes, offset;
-
-	num_bytes = BN_num_bytes(bn);
-	if ((size_t) num_bytes > len)
-		return -1;
-	offset = len - num_bytes;
-	os_memset(pos, 0, offset);
-	BN_bn2bin(bn, pos + offset);
-	return 0;
-}
-
-
-struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix)
-{
-	int len, res;
-	EC_KEY *eckey;
-	struct wpabuf *buf;
-	unsigned char *pos;
-
-	eckey = EVP_PKEY_get1_EC_KEY(pkey);
-	if (!eckey)
-		return NULL;
-	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
-	len = i2o_ECPublicKey(eckey, NULL);
-	if (len <= 0) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to determine public key encoding length");
-		EC_KEY_free(eckey);
-		return NULL;
-	}
-
-	buf = wpabuf_alloc(len);
-	if (!buf) {
-		EC_KEY_free(eckey);
-		return NULL;
-	}
-
-	pos = wpabuf_put(buf, len);
-	res = i2o_ECPublicKey(eckey, &pos);
-	EC_KEY_free(eckey);
-	if (res != len) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to encode public key (res=%d/%d)",
-			   res, len);
-		wpabuf_free(buf);
-		return NULL;
-	}
-
-	if (!prefix) {
-		/* Remove 0x04 prefix to match DPP definition */
-		pos = wpabuf_mhead(buf);
-		os_memmove(pos, pos + 1, len - 1);
-		buf->used--;
-	}
-
-	return buf;
-}
-
-
-EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
-				      const u8 *buf_x, const u8 *buf_y,
-				      size_t len)
-{
-	EC_KEY *eckey = NULL;
-	BN_CTX *ctx;
-	EC_POINT *point = NULL;
-	BIGNUM *x = NULL, *y = NULL;
-	EVP_PKEY *pkey = NULL;
-
-	ctx = BN_CTX_new();
-	if (!ctx) {
-		wpa_printf(MSG_ERROR, "DPP: Out of memory");
-		return NULL;
-	}
-
-	point = EC_POINT_new(group);
-	x = BN_bin2bn(buf_x, len, NULL);
-	y = BN_bin2bn(buf_y, len, NULL);
-	if (!point || !x || !y) {
-		wpa_printf(MSG_ERROR, "DPP: Out of memory");
-		goto fail;
-	}
-
-	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (!EC_POINT_is_on_curve(group, point, ctx) ||
-	    EC_POINT_is_at_infinity(group, point)) {
-		wpa_printf(MSG_ERROR, "DPP: Invalid point");
-		goto fail;
-	}
-	dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point);
-
-	eckey = EC_KEY_new();
-	if (!eckey ||
-	    EC_KEY_set_group(eckey, group) != 1 ||
-	    EC_KEY_set_public_key(eckey, point) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to set EC_KEY: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
-
-	pkey = EVP_PKEY_new();
-	if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
-		goto fail;
-	}
-
-out:
-	BN_free(x);
-	BN_free(y);
-	EC_KEY_free(eckey);
-	EC_POINT_free(point);
-	BN_CTX_free(ctx);
-	return pkey;
-fail:
-	EVP_PKEY_free(pkey);
-	pkey = NULL;
-	goto out;
-}
-
-
-EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len)
-{
-	const EC_KEY *eckey;
-	const EC_GROUP *group;
-	EVP_PKEY *pkey = NULL;
+	int ike_group = crypto_ec_key_group(group_key);
 
 	if (len & 1)
 		return NULL;
 
-	eckey = EVP_PKEY_get0_EC_KEY(group_key);
-	if (!eckey) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Could not get EC_KEY from group_key");
+	if (ike_group < 0) {
+		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
 		return NULL;
 	}
 
-	group = EC_KEY_get0_group(eckey);
-	if (group)
-		pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2,
-						  len / 2);
-	else
-		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
-
-	return pkey;
+	return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2);
 }
 
 
-EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
+struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
 {
-	EVP_PKEY_CTX *kctx = NULL;
-	EC_KEY *ec_params = NULL;
-	EVP_PKEY *params = NULL, *key = NULL;
-	int nid;
+	struct crypto_ec_key *key;
 
 	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
 
-	nid = OBJ_txt2nid(curve->name);
-	if (nid == NID_undef) {
-		wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
-		return NULL;
-	}
+	key = crypto_ec_key_gen(curve->ike_group);
+	if (key && wpa_debug_show_keys)
+	    dpp_debug_print_key("Own generated key", key);
 
-	ec_params = EC_KEY_new_by_curve_name(nid);
-	if (!ec_params) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to generate EC_KEY parameters");
-		goto fail;
-	}
-	EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
-	params = EVP_PKEY_new();
-	if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to generate EVP_PKEY parameters");
-		goto fail;
-	}
-
-	kctx = EVP_PKEY_CTX_new(params, NULL);
-	if (!kctx ||
-	    EVP_PKEY_keygen_init(kctx) != 1 ||
-	    EVP_PKEY_keygen(kctx, &key) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key");
-		key = NULL;
-		goto fail;
-	}
-
-	if (wpa_debug_show_keys)
-		dpp_debug_print_key("Own generated key", key);
-
-fail:
-	EC_KEY_free(ec_params);
-	EVP_PKEY_free(params);
-	EVP_PKEY_CTX_free(kctx);
 	return key;
 }
 
 
-EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
-			   const u8 *privkey, size_t privkey_len)
+struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
+				       const u8 *privkey, size_t privkey_len)
 {
-	EVP_PKEY *pkey;
-	EC_KEY *eckey;
-	const EC_GROUP *group;
-	int nid;
+	struct crypto_ec_key *key;
+	int group;
 
-	pkey = EVP_PKEY_new();
-	if (!pkey)
-		return NULL;
-	eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len);
-	if (!eckey) {
-		wpa_printf(MSG_INFO,
-			   "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		EVP_PKEY_free(pkey);
+	key = crypto_ec_key_parse_priv(privkey, privkey_len);
+	if (!key) {
+		wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
 		return NULL;
 	}
-	group = EC_KEY_get0_group(eckey);
-	if (!group) {
-		EC_KEY_free(eckey);
-		EVP_PKEY_free(pkey);
+
+	group = crypto_ec_key_group(key);
+	if (group < 0) {
+		crypto_ec_key_deinit(key);
 		return NULL;
 	}
-	nid = EC_GROUP_get_curve_name(group);
-	*curve = dpp_get_curve_nid(nid);
+
+	*curve = dpp_get_curve_ike_group(group);
 	if (!*curve) {
 		wpa_printf(MSG_INFO,
-			   "DPP: Unsupported curve (nid=%d) in pre-assigned key",
-			   nid);
-		EC_KEY_free(eckey);
-		EVP_PKEY_free(pkey);
+			   "DPP: Unsupported curve (group=%d) in pre-assigned key",
+			   group);
+		crypto_ec_key_deinit(key);
 		return NULL;
 	}
 
-	if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
-		EC_KEY_free(eckey);
-		EVP_PKEY_free(pkey);
-		return NULL;
-	}
-	return pkey;
-}
-
-
-typedef struct {
-	/* AlgorithmIdentifier ecPublicKey with optional parameters present
-	 * as an OID identifying the curve */
-	X509_ALGOR *alg;
-	/* Compressed format public key per ANSI X9.63 */
-	ASN1_BIT_STRING *pub_key;
-} DPP_BOOTSTRAPPING_KEY;
-
-ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = {
-	ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR),
-	ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY);
-
-IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY);
-
-
-static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key)
-{
-	unsigned char *der = NULL;
-	int der_len;
-	const EC_KEY *eckey;
-	struct wpabuf *ret = NULL;
-	size_t len;
-	const EC_GROUP *group;
-	const EC_POINT *point;
-	BN_CTX *ctx;
-	DPP_BOOTSTRAPPING_KEY *bootstrap = NULL;
-	int nid;
-
-	ctx = BN_CTX_new();
-	eckey = EVP_PKEY_get0_EC_KEY(key);
-	if (!ctx || !eckey)
-		goto fail;
-
-	group = EC_KEY_get0_group(eckey);
-	point = EC_KEY_get0_public_key(eckey);
-	if (!group || !point)
-		goto fail;
-	dpp_debug_print_point("DPP: bootstrap public key", group, point);
-	nid = EC_GROUP_get_curve_name(group);
-
-	bootstrap = DPP_BOOTSTRAPPING_KEY_new();
-	if (!bootstrap ||
-	    X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC),
-			    V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
-		goto fail;
-
-	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
-				 NULL, 0, ctx);
-	if (len == 0)
-		goto fail;
-
-	der = OPENSSL_malloc(len);
-	if (!der)
-		goto fail;
-	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
-				 der, len, ctx);
-
-	OPENSSL_free(bootstrap->pub_key->data);
-	bootstrap->pub_key->data = der;
-	der = NULL;
-	bootstrap->pub_key->length = len;
-	/* No unused bits */
-	bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
-	bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
-	der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der);
-	if (der_len <= 0) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to build DER encoded public key");
-		goto fail;
-	}
-
-	ret = wpabuf_alloc_copy(der, der_len);
-fail:
-	DPP_BOOTSTRAPPING_KEY_free(bootstrap);
-	OPENSSL_free(der);
-	BN_CTX_free(ctx);
-	return ret;
+	return key;
 }
 
 
@@ -701,7 +296,7 @@
 	struct wpabuf *der;
 	int res;
 
-	der = dpp_bootstrap_key_der(bi->pubkey);
+	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
 	if (!der)
 		return -1;
 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
@@ -736,7 +331,7 @@
 		goto fail;
 	bi->own = 1;
 
-	der = dpp_bootstrap_key_der(bi->pubkey);
+	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
 	if (!der)
 		goto fail;
 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
@@ -883,86 +478,48 @@
 }
 
 
-int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len)
+int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
+	     u8 *secret, size_t *secret_len)
 {
-	EVP_PKEY_CTX *ctx;
+	struct crypto_ecdh *ecdh;
+	struct wpabuf *peer_pub, *secret_buf = NULL;
 	int ret = -1;
 
-	ERR_clear_error();
 	*secret_len = 0;
 
-	ctx = EVP_PKEY_CTX_new(own, NULL);
-	if (!ctx) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+	ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
+	if (!ecdh) {
+		wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
 		return -1;
 	}
 
-	if (EVP_PKEY_derive_init(ctx) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) {
+	peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
+	if (!peer_pub) {
 		wpa_printf(MSG_ERROR,
-			   "DPP: EVP_PKEY_derive_set_peet failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+			   "DPP: crypto_ec_key_get_pubkey_point() failed");
 		goto fail;
 	}
 
-	if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+	secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub),
+					     wpabuf_len(peer_pub));
+	if (!secret_buf) {
+		wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed");
 		goto fail;
 	}
 
-	if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
-		u8 buf[200];
-		int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG;
-
-		/* It looks like OpenSSL can return unexpectedly large buffer
-		 * need for shared secret from EVP_PKEY_derive(NULL) in some
-		 * cases. For example, group 19 has shown cases where secret_len
-		 * is set to 72 even though the actual length ends up being
-		 * updated to 32 when EVP_PKEY_derive() is called with a buffer
-		 * for the value. Work around this by trying to fetch the value
-		 * and continue if it is within supported range even when the
-		 * initial buffer need is claimed to be larger. */
-		wpa_printf(level,
-			   "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
-			   (int) *secret_len);
-		if (*secret_len > 200)
-			goto fail;
-		if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) {
-			wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
-				   ERR_error_string(ERR_get_error(), NULL));
-			goto fail;
-		}
-		if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
-			wpa_printf(MSG_ERROR,
-				   "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
-				   (int) *secret_len);
-			goto fail;
-		}
-		wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change",
-				buf, *secret_len);
-		os_memcpy(secret, buf, *secret_len);
-		forced_memzero(buf, sizeof(buf));
-		goto done;
-	}
-
-	if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+	if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
+		wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
 		goto fail;
 	}
 
-done:
+	*secret_len = wpabuf_len(secret_buf);
+	os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
 	ret = 0;
 
 fail:
-	EVP_PKEY_CTX_free(ctx);
+	wpabuf_clear_free(secret_buf);
+	wpabuf_free(peer_pub);
+	crypto_ecdh_deinit(ecdh);
 	return ret;
 }
 
@@ -996,118 +553,32 @@
 int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
 			       const u8 *data, size_t data_len)
 {
-	EVP_PKEY *pkey;
-	const unsigned char *p;
-	int res;
-	X509_PUBKEY *pub = NULL;
-	ASN1_OBJECT *ppkalg;
-	const unsigned char *pk;
-	int ppklen;
-	X509_ALGOR *pa;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-	(defined(LIBRESSL_VERSION_NUMBER) && \
-	 LIBRESSL_VERSION_NUMBER < 0x20800000L)
-	ASN1_OBJECT *pa_oid;
-#else
-	const ASN1_OBJECT *pa_oid;
-#endif
-	const void *pval;
-	int ptype;
-	const ASN1_OBJECT *poid;
-	char buf[100];
+	struct crypto_ec_key *key;
 
 	if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
 		return -1;
 	}
 
-	/* DER encoded ASN.1 SubjectPublicKeyInfo
-	 *
-	 * SubjectPublicKeyInfo  ::=  SEQUENCE  {
-	 *      algorithm            AlgorithmIdentifier,
-	 *      subjectPublicKey     BIT STRING  }
-	 *
-	 * AlgorithmIdentifier  ::=  SEQUENCE  {
-	 *      algorithm               OBJECT IDENTIFIER,
-	 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
-	 *
-	 * subjectPublicKey = compressed format public key per ANSI X9.63
-	 * algorithm = ecPublicKey (1.2.840.10045.2.1)
-	 * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
-	 *       prime256v1 (1.2.840.10045.3.1.7)
-	 */
-
-	p = data;
-	pkey = d2i_PUBKEY(NULL, &p, data_len);
-
-	if (!pkey) {
+	key = crypto_ec_key_parse_pub(data, data_len);
+	if (!key) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
 		return -1;
 	}
 
-	if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: SubjectPublicKeyInfo does not describe an EC key");
-		EVP_PKEY_free(pkey);
-		return -1;
-	}
-
-	res = X509_PUBKEY_set(&pub, pkey);
-	if (res != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey");
-		goto fail;
-	}
-
-	res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub);
-	if (res != 1) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not extract SubjectPublicKeyInfo parameters");
-		goto fail;
-	}
-	res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0);
-	if (res < 0 || (size_t) res >= sizeof(buf)) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not extract SubjectPublicKeyInfo algorithm");
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf);
-	if (os_strcmp(buf, "id-ecPublicKey") != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported SubjectPublicKeyInfo algorithm");
-		goto fail;
-	}
-
-	X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa);
-	if (ptype != V_ASN1_OBJECT) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: SubjectPublicKeyInfo parameters did not contain an OID");
-		goto fail;
-	}
-	poid = pval;
-	res = OBJ_obj2txt(buf, sizeof(buf), poid, 0);
-	if (res < 0 || (size_t) res >= sizeof(buf)) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not extract SubjectPublicKeyInfo parameters OID");
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf);
-	bi->curve = dpp_get_curve_oid(poid);
+	bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
 	if (!bi->curve) {
 		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported SubjectPublicKeyInfo curve: %s",
-			   buf);
+			   "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
+			   crypto_ec_key_group(key));
 		goto fail;
 	}
 
-	wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen);
-
-	X509_PUBKEY_free(pub);
-	bi->pubkey = pkey;
+	bi->pubkey = key;
 	return 0;
 fail:
-	X509_PUBKEY_free(pub);
-	EVP_PKEY_free(pkey);
+	crypto_ec_key_deinit(key);
 	return -1;
 }
 
@@ -1115,7 +586,7 @@
 static struct wpabuf *
 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
 		       const u8 *prot_hdr, u16 prot_hdr_len,
-		       const EVP_MD **ret_md)
+		       int *hash_func)
 {
 	struct json_token *root, *token;
 	struct wpabuf *kid = NULL;
@@ -1161,17 +632,16 @@
 		goto fail;
 	}
 	if (os_strcmp(token->string, "ES256") == 0 ||
-	    os_strcmp(token->string, "BS256") == 0)
-		*ret_md = EVP_sha256();
-	else if (os_strcmp(token->string, "ES384") == 0 ||
-		 os_strcmp(token->string, "BS384") == 0)
-		*ret_md = EVP_sha384();
-	else if (os_strcmp(token->string, "ES512") == 0 ||
-		 os_strcmp(token->string, "BS512") == 0)
-		*ret_md = EVP_sha512();
-	else
-		*ret_md = NULL;
-	if (!*ret_md) {
+	    os_strcmp(token->string, "BS256") == 0) {
+		*hash_func = CRYPTO_HASH_ALG_SHA256;
+	} else if (os_strcmp(token->string, "ES384") == 0 ||
+		   os_strcmp(token->string, "BS384") == 0) {
+		*hash_func = CRYPTO_HASH_ALG_SHA384;
+	} else if (os_strcmp(token->string, "ES512") == 0 ||
+		   os_strcmp(token->string, "BS512") == 0) {
+		*hash_func = CRYPTO_HASH_ALG_SHA512;
+	} else {
+		*hash_func = -1;
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Unsupported JWS Protected Header alg=%s",
 			   token->string);
@@ -1192,7 +662,8 @@
 }
 
 
-static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
+static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
+				  struct wpabuf *r_hash)
 {
 	struct wpabuf *uncomp;
 	int res;
@@ -1202,7 +673,7 @@
 
 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
 		return -1;
-	uncomp = dpp_get_pubkey_point(pub, 1);
+	uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
 	if (!uncomp)
 		return -1;
 	addr[0] = wpabuf_head(uncomp);
@@ -1226,33 +697,19 @@
 
 enum dpp_status_error
 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
-			     EVP_PKEY *csign_pub, const char *connector)
+			     struct crypto_ec_key *csign_pub,
+			     const char *connector)
 {
 	enum dpp_status_error ret = 255;
 	const char *pos, *end, *signed_start, *signed_end;
 	struct wpabuf *kid = NULL;
 	unsigned char *prot_hdr = NULL, *signature = NULL;
-	size_t prot_hdr_len = 0, signature_len = 0;
-	const EVP_MD *sign_md = NULL;
-	unsigned char *der = NULL;
-	int der_len;
-	int res;
-	EVP_MD_CTX *md_ctx = NULL;
-	ECDSA_SIG *sig = NULL;
-	BIGNUM *r = NULL, *s = NULL;
+	size_t prot_hdr_len = 0, signature_len = 0, signed_len;
+	int res, hash_func = -1;
 	const struct dpp_curve_params *curve;
-	const EC_KEY *eckey;
-	const EC_GROUP *group;
-	int nid;
+	u8 *hash = NULL;
 
-	eckey = EVP_PKEY_get0_EC_KEY(csign_pub);
-	if (!eckey)
-		goto fail;
-	group = EC_KEY_get0_group(eckey);
-	if (!group)
-		goto fail;
-	nid = EC_GROUP_get_curve_name(group);
-	curve = dpp_get_curve_nid(nid);
+	curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
 	if (!curve)
 		goto fail;
 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
@@ -1275,7 +732,7 @@
 	wpa_hexdump_ascii(MSG_DEBUG,
 			  "DPP: signedConnector - JWS Protected Header",
 			  prot_hdr, prot_hdr_len);
-	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md);
+	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
 	if (!kid) {
 		ret = DPP_STATUS_INVALID_CONNECTOR;
 		goto fail;
@@ -1331,57 +788,45 @@
 		goto fail;
 	}
 
-	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
-	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
-	r = BN_bin2bn(signature, signature_len / 2, NULL);
-	s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL);
-	sig = ECDSA_SIG_new();
-	if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1)
-		goto fail;
-	r = NULL;
-	s = NULL;
-
-	der_len = i2d_ECDSA_SIG(sig, &der);
-	if (der_len <= 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len);
-	md_ctx = EVP_MD_CTX_create();
-	if (!md_ctx)
+	hash = os_malloc(curve->hash_len);
+	if (!hash)
 		goto fail;
 
-	ERR_clear_error();
-	if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+	signed_len = signed_end - signed_start + 1;
+	if (hash_func == CRYPTO_HASH_ALG_SHA256)
+		res = sha256_vector(1, (const u8 **) &signed_start, &signed_len,
+				    hash);
+	else if (hash_func == CRYPTO_HASH_ALG_SHA384)
+		res = sha384_vector(1, (const u8 **) &signed_start, &signed_len,
+				    hash);
+	else if (hash_func == CRYPTO_HASH_ALG_SHA512)
+		res = sha512_vector(1, (const u8 **) &signed_start, &signed_len,
+				    hash);
+	else
 		goto fail;
-	}
-	if (EVP_DigestVerifyUpdate(md_ctx, signed_start,
-				   signed_end - signed_start + 1) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+
+	if (res)
 		goto fail;
-	}
-	res = EVP_DigestVerifyFinal(md_ctx, der, der_len);
+
+	res = crypto_ec_key_verify_signature_r_s(csign_pub,
+						 hash, curve->hash_len,
+						 signature, signature_len / 2,
+						 signature + signature_len / 2,
+						 signature_len / 2);
 	if (res != 1) {
 		wpa_printf(MSG_DEBUG,
-			   "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
-			   res, ERR_error_string(ERR_get_error(), NULL));
+			   "DPP: signedConnector signature check failed (res=%d)",
+			   res);
 		ret = DPP_STATUS_INVALID_CONNECTOR;
 		goto fail;
 	}
 
 	ret = DPP_STATUS_OK;
 fail:
-	EVP_MD_CTX_destroy(md_ctx);
+	os_free(hash);
 	os_free(prot_hdr);
 	wpabuf_free(kid);
 	os_free(signature);
-	ECDSA_SIG_free(sig);
-	BN_free(r);
-	BN_free(s);
-	OPENSSL_free(der);
 	return ret;
 }
 
@@ -1391,13 +836,11 @@
 			   const u8 *csign_key, size_t csign_key_len,
 			   const u8 *peer_connector, size_t peer_connector_len)
 {
-	const unsigned char *p;
-	EVP_PKEY *csign = NULL;
+	struct crypto_ec_key *csign;
 	char *signed_connector = NULL;
 	enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
 
-	p = csign_key;
-	csign = d2i_PUBKEY(NULL, &p, csign_key_len);
+	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
 	if (!csign) {
 		wpa_printf(MSG_ERROR,
 			   "DPP: Failed to parse local C-sign-key information");
@@ -1414,7 +857,7 @@
 	res = dpp_process_signed_connector(info, csign, signed_connector);
 fail:
 	os_free(signed_connector);
-	EVP_PKEY_free(csign);
+	crypto_ec_key_deinit(csign);
 	return res;
 }
 
@@ -1433,21 +876,25 @@
 	nonce_len = auth->curve->nonce_len;
 
 	if (auth->initiator) {
-		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
+		pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
+		prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+						     0);
 		if (auth->own_bi)
-			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+			bix = crypto_ec_key_get_pubkey_point(
+				auth->own_bi->pubkey, 0);
 		else
 			bix = NULL;
-		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+		brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
 	} else {
-		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+		pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+						     0);
+		prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
 		if (auth->peer_bi)
-			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+			bix = crypto_ec_key_get_pubkey_point(
+				auth->peer_bi->pubkey, 0);
 		else
 			bix = NULL;
-		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+		brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
 	}
 	if (!pix || !prx || !brx)
 		goto fail;
@@ -1512,25 +959,29 @@
 	nonce_len = auth->curve->nonce_len;
 
 	if (auth->initiator) {
-		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
+		pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
+		prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+						     0);
 		if (auth->own_bi)
-			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+			bix = crypto_ec_key_get_pubkey_point(
+				auth->own_bi->pubkey, 0);
 		else
 			bix = NULL;
 		if (!auth->peer_bi)
 			goto fail;
-		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+		brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
 	} else {
-		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+		pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+						     0);
+		prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
 		if (auth->peer_bi)
-			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+			bix = crypto_ec_key_get_pubkey_point(
+				auth->peer_bi->pubkey, 0);
 		else
 			bix = NULL;
 		if (!auth->own_bi)
 			goto fail;
-		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+		brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
 	}
 	if (!pix || !prx || !brx)
 		goto fail;
@@ -1583,122 +1034,83 @@
 
 int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
 {
-	const EC_GROUP *group;
-	EC_POINT *l = NULL;
-	const EC_KEY *BI, *bR, *pR;
-	const EC_POINT *BI_point;
-	BN_CTX *bnctx;
-	BIGNUM *lx, *sum, *q;
-	const BIGNUM *bR_bn, *pR_bn;
+	struct crypto_ec *ec;
+	struct crypto_ec_point *L = NULL;
+	const struct crypto_ec_point *BI;
+	const struct crypto_bignum *bR, *pR, *q;
+	struct crypto_bignum *sum = NULL, *lx = NULL;
 	int ret = -1;
 
 	/* L = ((bR + pR) modulo q) * BI */
 
-	bnctx = BN_CTX_new();
-	sum = BN_new();
-	q = BN_new();
-	lx = BN_new();
-	if (!bnctx || !sum || !q || !lx)
-		goto fail;
-	BI = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey);
-	if (!BI)
-		goto fail;
-	BI_point = EC_KEY_get0_public_key(BI);
-	group = EC_KEY_get0_group(BI);
-	if (!group)
+	ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
+	if (!ec)
 		goto fail;
 
-	bR = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey);
-	pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key);
-	if (!bR || !pR)
+	q = crypto_ec_get_order(ec);
+	BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
+	bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
+	pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
+	sum = crypto_bignum_init();
+	L = crypto_ec_point_init(ec);
+	lx = crypto_bignum_init();
+	if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
+	    crypto_bignum_addmod(bR, pR, q, sum) ||
+	    crypto_ec_point_mul(ec, BI, sum, L) ||
+	    crypto_ec_point_x(ec, L, lx) ||
+	    crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
+				 auth->secret_len) < 0)
 		goto fail;
-	bR_bn = EC_KEY_get0_private_key(bR);
-	pR_bn = EC_KEY_get0_private_key(pR);
-	if (!bR_bn || !pR_bn)
-		goto fail;
-	if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
-	    BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1)
-		goto fail;
-	l = EC_POINT_new(group);
-	if (!l ||
-	    EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
-						bnctx) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "OpenSSL: failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
 
-	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
-		goto fail;
 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
 	auth->Lx_len = auth->secret_len;
 	ret = 0;
 fail:
-	EC_POINT_clear_free(l);
-	BN_clear_free(lx);
-	BN_clear_free(sum);
-	BN_free(q);
-	BN_CTX_free(bnctx);
+	crypto_bignum_deinit(lx, 1);
+	crypto_bignum_deinit(sum, 1);
+	crypto_ec_point_deinit(L, 1);
+	crypto_ec_deinit(ec);
 	return ret;
 }
 
 
 int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
 {
-	const EC_GROUP *group;
-	EC_POINT *l = NULL, *sum = NULL;
-	const EC_KEY *bI, *BR, *PR;
-	const EC_POINT *BR_point, *PR_point;
-	BN_CTX *bnctx;
-	BIGNUM *lx;
-	const BIGNUM *bI_bn;
+	struct crypto_ec *ec;
+	struct crypto_ec_point *L = NULL, *sum = NULL;
+	const struct crypto_ec_point *BR, *PR;
+	const struct crypto_bignum *bI;
+	struct crypto_bignum *lx = NULL;
 	int ret = -1;
 
 	/* L = bI * (BR + PR) */
 
-	bnctx = BN_CTX_new();
-	lx = BN_new();
-	if (!bnctx || !lx)
+	ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
+	if (!ec)
 		goto fail;
-	BR = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey);
-	PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key);
-	if (!BR || !PR)
-		goto fail;
-	BR_point = EC_KEY_get0_public_key(BR);
-	PR_point = EC_KEY_get0_public_key(PR);
 
-	bI = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey);
-	if (!bI)
+	BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
+	PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
+	bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
+	sum = crypto_ec_point_init(ec);
+	L = crypto_ec_point_init(ec);
+	lx = crypto_bignum_init();
+	if (!BR || !PR || !bI || !sum || !L || !lx ||
+	    crypto_ec_point_add(ec, BR, PR, sum) ||
+	    crypto_ec_point_mul(ec, sum, bI, L) ||
+	    crypto_ec_point_x(ec, L, lx) ||
+	    crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
+				 auth->secret_len) < 0)
 		goto fail;
-	group = EC_KEY_get0_group(bI);
-	bI_bn = EC_KEY_get0_private_key(bI);
-	if (!group || !bI_bn)
-		goto fail;
-	sum = EC_POINT_new(group);
-	l = EC_POINT_new(group);
-	if (!sum || !l ||
-	    EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 ||
-	    EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
-						bnctx) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "OpenSSL: failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
 
-	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
-		goto fail;
 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
 	auth->Lx_len = auth->secret_len;
 	ret = 0;
 fail:
-	EC_POINT_clear_free(l);
-	EC_POINT_clear_free(sum);
-	BN_clear_free(lx);
-	BN_CTX_free(bnctx);
+	crypto_bignum_deinit(lx, 1);
+	crypto_ec_point_deinit(sum, 1);
+	crypto_ec_point_deinit(L, 1);
+	crypto_ec_deinit(ec);
 	return ret;
 }
 
@@ -1731,7 +1143,8 @@
 
 
 int dpp_derive_pmkid(const struct dpp_curve_params *curve,
-		     EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid)
+		     struct crypto_ec_key *own_key,
+		     struct crypto_ec_key *peer_key, u8 *pmkid)
 {
 	struct wpabuf *nkx, *pkx;
 	int ret = -1, res;
@@ -1740,8 +1153,8 @@
 	u8 hash[SHA256_MAC_LEN];
 
 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
-	nkx = dpp_get_pubkey_point(own_key, 0);
-	pkx = dpp_get_pubkey_point(peer_key, 0);
+	nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
+	pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
 	if (!nkx || !pkx)
 		goto fail;
 	addr[0] = wpabuf_head(nkx);
@@ -1981,13 +1394,10 @@
 };
 
 
-static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve,
-					 int init)
+static struct crypto_ec_key *
+dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
 {
-	EC_GROUP *group;
-	size_t len = curve->prime_len;
 	const u8 *x, *y;
-	EVP_PKEY *res;
 
 	switch (curve->ike_group) {
 	case 19:
@@ -2018,38 +1428,34 @@
 		return NULL;
 	}
 
-	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
-	if (!group)
-		return NULL;
-	res = dpp_set_pubkey_point_group(group, x, y, len);
-	EC_GROUP_free(group);
-	return res;
+	return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
 }
 
 
-EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
-			      const u8 *mac_init, const char *code,
-			      const char *identifier, BN_CTX *bnctx,
-			      EC_GROUP **ret_group)
+struct crypto_ec_point *
+dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
+		   const char *code, const char *identifier,
+		   struct crypto_ec **ret_ec)
 {
 	u8 hash[DPP_MAX_HASH_LEN];
 	const u8 *addr[3];
 	size_t len[3];
 	unsigned int num_elem = 0;
-	EC_POINT *Qi = NULL;
-	EVP_PKEY *Pi = NULL;
-	const EC_KEY *Pi_ec;
-	const EC_POINT *Pi_point;
-	BIGNUM *hash_bn = NULL;
-	const EC_GROUP *group = NULL;
-	EC_GROUP *group2 = NULL;
+	struct crypto_ec_point *Qi = NULL;
+	struct crypto_ec_key *Pi_key = NULL;
+	const struct crypto_ec_point *Pi = NULL;
+	struct crypto_bignum *hash_bn = NULL;
+	struct crypto_ec *ec = NULL;
 
-	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
+	/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
 
-	wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
-	addr[num_elem] = mac_init;
-	len[num_elem] = ETH_ALEN;
-	num_elem++;
+	if (mac_init) {
+		wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
+			   MAC2STR(mac_init));
+		addr[num_elem] = mac_init;
+		len[num_elem] = ETH_ALEN;
+		num_elem++;
+	}
 	if (identifier) {
 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
 			   identifier);
@@ -2064,75 +1470,67 @@
 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
 		goto fail;
 	wpa_hexdump_key(MSG_DEBUG,
-			"DPP: H(MAC-Initiator | [identifier |] code)",
+			"DPP: H([MAC-Initiator |] [identifier |] code)",
 			hash, curve->hash_len);
-	Pi = dpp_pkex_get_role_elem(curve, 1);
-	if (!Pi)
+	Pi_key = dpp_pkex_get_role_elem(curve, 1);
+	if (!Pi_key)
 		goto fail;
-	dpp_debug_print_key("DPP: Pi", Pi);
-	Pi_ec = EVP_PKEY_get0_EC_KEY(Pi);
-	if (!Pi_ec)
-		goto fail;
-	Pi_point = EC_KEY_get0_public_key(Pi_ec);
+	dpp_debug_print_key("DPP: Pi", Pi_key);
 
-	group = EC_KEY_get0_group(Pi_ec);
-	if (!group)
+	ec = crypto_ec_init(curve->ike_group);
+	if (!ec)
 		goto fail;
-	group2 = EC_GROUP_dup(group);
-	if (!group2)
+
+	Pi = crypto_ec_key_get_public_key(Pi_key);
+	Qi = crypto_ec_point_init(ec);
+	hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
+	if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
 		goto fail;
-	Qi = EC_POINT_new(group2);
-	if (!Qi) {
-		EC_GROUP_free(group2);
-		goto fail;
-	}
-	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
-	if (!hash_bn ||
-	    EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1)
-		goto fail;
-	if (EC_POINT_is_at_infinity(group, Qi)) {
+
+	if (crypto_ec_point_is_at_infinity(ec, Qi)) {
 		wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
 		goto fail;
 	}
-	dpp_debug_print_point("DPP: Qi", group, Qi);
+	crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
 out:
-	EVP_PKEY_free(Pi);
-	BN_clear_free(hash_bn);
-	if (ret_group && Qi)
-		*ret_group = group2;
+	crypto_ec_key_deinit(Pi_key);
+	crypto_bignum_deinit(hash_bn, 1);
+	if (ret_ec && Qi)
+		*ret_ec = ec;
 	else
-		EC_GROUP_free(group2);
+		crypto_ec_deinit(ec);
 	return Qi;
 fail:
-	EC_POINT_free(Qi);
+	crypto_ec_point_deinit(Qi, 1);
 	Qi = NULL;
 	goto out;
 }
 
 
-EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
-			      const u8 *mac_resp, const char *code,
-			      const char *identifier, BN_CTX *bnctx,
-			      EC_GROUP **ret_group)
+struct crypto_ec_point *
+dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
+		   const char *code, const char *identifier,
+		   struct crypto_ec **ret_ec)
 {
 	u8 hash[DPP_MAX_HASH_LEN];
 	const u8 *addr[3];
 	size_t len[3];
 	unsigned int num_elem = 0;
-	EC_POINT *Qr = NULL;
-	EVP_PKEY *Pr = NULL;
-	const EC_KEY *Pr_ec;
-	const EC_POINT *Pr_point;
-	BIGNUM *hash_bn = NULL;
-	const EC_GROUP *group = NULL;
-	EC_GROUP *group2 = NULL;
+	struct crypto_ec_point *Qr = NULL;
+	struct crypto_ec_key *Pr_key = NULL;
+	const struct crypto_ec_point *Pr = NULL;
+	struct crypto_bignum *hash_bn = NULL;
+	struct crypto_ec *ec = NULL;
 
-	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
+	/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
 
-	wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
-	addr[num_elem] = mac_resp;
-	len[num_elem] = ETH_ALEN;
-	num_elem++;
+	if (mac_resp) {
+		wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
+			   MAC2STR(mac_resp));
+		addr[num_elem] = mac_resp;
+		len[num_elem] = ETH_ALEN;
+		num_elem++;
+	}
 	if (identifier) {
 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
 			   identifier);
@@ -2147,53 +1545,46 @@
 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
 		goto fail;
 	wpa_hexdump_key(MSG_DEBUG,
-			"DPP: H(MAC-Responder | [identifier |] code)",
+			"DPP: H([MAC-Responder |] [identifier |] code)",
 			hash, curve->hash_len);
-	Pr = dpp_pkex_get_role_elem(curve, 0);
-	if (!Pr)
+	Pr_key = dpp_pkex_get_role_elem(curve, 0);
+	if (!Pr_key)
 		goto fail;
-	dpp_debug_print_key("DPP: Pr", Pr);
-	Pr_ec = EVP_PKEY_get0_EC_KEY(Pr);
-	if (!Pr_ec)
-		goto fail;
-	Pr_point = EC_KEY_get0_public_key(Pr_ec);
+	dpp_debug_print_key("DPP: Pr", Pr_key);
 
-	group = EC_KEY_get0_group(Pr_ec);
-	if (!group)
+	ec = crypto_ec_init(curve->ike_group);
+	if (!ec)
 		goto fail;
-	group2 = EC_GROUP_dup(group);
-	if (!group2)
+
+	Pr = crypto_ec_key_get_public_key(Pr_key);
+	Qr = crypto_ec_point_init(ec);
+	hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
+	if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
 		goto fail;
-	Qr = EC_POINT_new(group2);
-	if (!Qr) {
-		EC_GROUP_free(group2);
-		goto fail;
-	}
-	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
-	if (!hash_bn ||
-	    EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1)
-		goto fail;
-	if (EC_POINT_is_at_infinity(group, Qr)) {
+
+	if (crypto_ec_point_is_at_infinity(ec, Qr)) {
 		wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
 		goto fail;
 	}
-	dpp_debug_print_point("DPP: Qr", group, Qr);
+	crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
+
 out:
-	EVP_PKEY_free(Pr);
-	BN_clear_free(hash_bn);
-	if (ret_group && Qr)
-		*ret_group = group2;
+	crypto_ec_key_deinit(Pr_key);
+	crypto_bignum_deinit(hash_bn, 1);
+	if (ret_ec && Qr)
+		*ret_ec = ec;
 	else
-		EC_GROUP_free(group2);
+		crypto_ec_deinit(ec);
 	return Qr;
 fail:
-	EC_POINT_free(Qr);
+	crypto_ec_point_deinit(Qr, 1);
 	Qr = NULL;
 	goto out;
 }
 
 
 int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
+		      u8 ver_init, u8 ver_resp,
 		      const u8 *Mx, size_t Mx_len,
 		      const u8 *Nx, size_t Nx_len,
 		      const char *code,
@@ -2205,7 +1596,10 @@
 	u8 *info, *pos;
 	size_t info_len;
 
-	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
+	/*
+	 * v1: info = MAC-Initiator | MAC-Responder
+	 * v2: info = Protocol Version-Initiator | Protocol Version-Responder
+	 * z = HKDF(<>, info | M.x | N.x | code, K.x)
 	 */
 
 	/* HKDF-Extract(<>, IKM=K.x) */
@@ -2214,15 +1608,24 @@
 		return -1;
 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
 			prk, hash_len);
-	info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
+	if (mac_init && mac_resp)
+		info_len = 2 * ETH_ALEN;
+	else
+		info_len = 2;
+	info_len += Mx_len + Nx_len + os_strlen(code);
 	info = os_malloc(info_len);
 	if (!info)
 		return -1;
 	pos = info;
-	os_memcpy(pos, mac_init, ETH_ALEN);
-	pos += ETH_ALEN;
-	os_memcpy(pos, mac_resp, ETH_ALEN);
-	pos += ETH_ALEN;
+	if (mac_init && mac_resp) {
+		os_memcpy(pos, mac_init, ETH_ALEN);
+		pos += ETH_ALEN;
+		os_memcpy(pos, mac_resp, ETH_ALEN);
+		pos += ETH_ALEN;
+	} else {
+		*pos++ = ver_init;
+		*pos++ = ver_resp;
+	}
 	os_memcpy(pos, Mx, Mx_len);
 	pos += Mx_len;
 	os_memcpy(pos, Nx, Nx_len);
@@ -2257,15 +1660,12 @@
 				     size_t net_access_key_len,
 				     struct json_token *peer_net_access_key)
 {
-	BN_CTX *bnctx = NULL;
-	EVP_PKEY *own_key = NULL, *peer_key = NULL;
-	BIGNUM *sum = NULL, *q = NULL, *mx = NULL;
-	EC_POINT *m = NULL;
-	const EC_KEY *cR, *pR;
-	const EC_GROUP *group;
-	const BIGNUM *cR_bn, *pR_bn;
-	const EC_POINT *CI_point;
-	const EC_KEY *CI;
+	struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
+	struct crypto_bignum *sum = NULL;
+	const struct crypto_bignum *q, *cR, *pR;
+	struct crypto_ec *ec = NULL;
+	struct crypto_ec_point *M = NULL;
+	const struct crypto_ec_point *CI;
 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
 	u8 prk[DPP_MAX_HASH_LEN];
 	const struct dpp_curve_params *curve;
@@ -2303,37 +1703,23 @@
 			auth->e_nonce, auth->curve->nonce_len);
 
 	/* M = { cR + pR } * CI */
-	cR = EVP_PKEY_get0_EC_KEY(own_key);
-	pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key);
-	if (!pR)
+	ec = crypto_ec_init(curve->ike_group);
+	if (!ec)
 		goto fail;
-	group = EC_KEY_get0_group(pR);
-	bnctx = BN_CTX_new();
-	sum = BN_new();
-	mx = BN_new();
-	q = BN_new();
-	m = EC_POINT_new(group);
-	if (!cR || !bnctx || !sum || !mx || !q || !m)
-		goto fail;
-	cR_bn = EC_KEY_get0_private_key(cR);
-	pR_bn = EC_KEY_get0_private_key(pR);
-	if (!cR_bn || !pR_bn)
-		goto fail;
-	CI = EVP_PKEY_get0_EC_KEY(peer_key);
-	CI_point = EC_KEY_get0_public_key(CI);
-	if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
-	    BN_mod_add(sum, cR_bn, pR_bn, q, bnctx) != 1 ||
-	    EC_POINT_mul(group, m, NULL, CI_point, sum, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL,
-						bnctx) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "OpenSSL: failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
+
+	sum = crypto_bignum_init();
+	q = crypto_ec_get_order(ec);
+	M = crypto_ec_point_init(ec);
+	cR = crypto_ec_key_get_private_key(own_key);
+	pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
+	CI = crypto_ec_key_get_public_key(peer_key);
+	if (!sum || !q || !M || !cR || !pR || !CI ||
+	    crypto_bignum_addmod(cR, pR, q, sum) ||
+	    crypto_ec_point_mul(ec, CI, sum, M) ||
+	    crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
+		wpa_printf(MSG_ERROR, "DPP: Error during M computation");
 		goto fail;
 	}
-
-	if (dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0)
-		goto fail;
 	wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
 
 	/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
@@ -2355,19 +1741,17 @@
 			auth->ke, curve->hash_len);
 
 	res = 0;
-	EVP_PKEY_free(auth->reconfig_old_protocol_key);
+	crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
 	auth->reconfig_old_protocol_key = own_key;
 	own_key = NULL;
 fail:
 	forced_memzero(prk, sizeof(prk));
 	forced_memzero(Mx, sizeof(Mx));
-	EC_POINT_clear_free(m);
-	BN_free(q);
-	BN_clear_free(mx);
-	BN_clear_free(sum);
-	EVP_PKEY_free(own_key);
-	EVP_PKEY_free(peer_key);
-	BN_CTX_free(bnctx);
+	crypto_ec_point_deinit(M, 1);
+	crypto_bignum_deinit(sum, 1);
+	crypto_ec_key_deinit(own_key);
+	crypto_ec_key_deinit(peer_key);
+	crypto_ec_deinit(ec);
 	return res;
 }
 
@@ -2376,14 +1760,11 @@
 				     const u8 *r_proto, u16 r_proto_len,
 				     struct json_token *net_access_key)
 {
-	BN_CTX *bnctx = NULL;
-	EVP_PKEY *pr = NULL, *peer_key = NULL;
-	EC_POINT *sum = NULL, *m = NULL;
-	BIGNUM *mx = NULL;
-	const EC_KEY *cI, *CR, *PR;
-	const EC_GROUP *group;
-	const EC_POINT *CR_point, *PR_point;
-	const BIGNUM *cI_bn;
+	struct crypto_ec_key *pr = NULL, *peer_key = NULL;
+	const struct crypto_ec_point *CR, *PR;
+	const struct crypto_bignum *cI;
+	struct crypto_ec *ec = NULL;
+	struct crypto_ec_point *sum = NULL, *M = NULL;
 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
 	u8 prk[DPP_MAX_HASH_LEN];
 	int res = -1;
@@ -2397,7 +1778,7 @@
 		goto fail;
 	}
 	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
-	EVP_PKEY_free(auth->peer_protocol_key);
+	crypto_ec_key_deinit(auth->peer_protocol_key);
 	auth->peer_protocol_key = pr;
 	pr = NULL;
 
@@ -2413,25 +1794,23 @@
 	}
 
 	/* M = cI * { CR + PR } */
-	cI = EVP_PKEY_get0_EC_KEY(auth->conf->connector_key);
-	cI_bn = EC_KEY_get0_private_key(cI);
-	group = EC_KEY_get0_group(cI);
-	bnctx = BN_CTX_new();
-	sum = EC_POINT_new(group);
-	m = EC_POINT_new(group);
-	mx = BN_new();
-	CR = EVP_PKEY_get0_EC_KEY(peer_key);
-	PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key);
-	CR_point = EC_KEY_get0_public_key(CR);
-	PR_point = EC_KEY_get0_public_key(PR);
-	if (!bnctx || !sum || !m || !mx ||
-	    EC_POINT_add(group, sum, CR_point, PR_point, bnctx) != 1 ||
-	    EC_POINT_mul(group, m, NULL, sum, cI_bn, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL,
-						bnctx) != 1 ||
-	    dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0)
+	ec = crypto_ec_init(curve->ike_group);
+	if (!ec)
 		goto fail;
 
+	cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
+	sum = crypto_ec_point_init(ec);
+	M = crypto_ec_point_init(ec);
+	CR = crypto_ec_key_get_public_key(peer_key);
+	PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
+	if (!cI || !sum || !M || !CR || !PR ||
+	    crypto_ec_point_add(ec, CR, PR, sum) ||
+	    crypto_ec_point_mul(ec, sum, cI, M) ||
+	    crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
+		wpa_printf(MSG_ERROR, "DPP: Error during M computation");
+		goto fail;
+	}
+
 	wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
 
 	/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
@@ -2456,12 +1835,11 @@
 fail:
 	forced_memzero(prk, sizeof(prk));
 	forced_memzero(Mx, sizeof(Mx));
-	EVP_PKEY_free(pr);
-	EVP_PKEY_free(peer_key);
-	EC_POINT_clear_free(sum);
-	EC_POINT_clear_free(m);
-	BN_clear_free(mx);
-	BN_CTX_free(bnctx);
+	crypto_ec_key_deinit(pr);
+	crypto_ec_key_deinit(peer_key);
+	crypto_ec_point_deinit(sum, 1);
+	crypto_ec_point_deinit(M, 1);
+	crypto_ec_deinit(ec);
 	return res;
 }
 
@@ -2497,78 +1875,56 @@
 			 size_t *signed3_len)
 {
 	const struct dpp_curve_params *curve;
+	struct wpabuf *sig = NULL;
 	char *signed3 = NULL;
-	unsigned char *signature = NULL;
-	const unsigned char *p;
-	size_t signature_len;
-	EVP_MD_CTX *md_ctx = NULL;
-	ECDSA_SIG *sig = NULL;
 	char *dot = ".";
-	const EVP_MD *sign_md;
-	const BIGNUM *r, *s;
+	const u8 *vector[3];
+	size_t vector_len[3];
+	u8 *hash;
+	int ret;
+
+	vector[0] = (const u8 *) signed1;
+	vector[1] = (const u8 *) dot;
+	vector[2] = (const u8 *) signed2;
+	vector_len[0] = signed1_len;
+	vector_len[1] = 1;
+	vector_len[2] = signed2_len;
 
 	curve = conf->curve;
+	hash = os_malloc(curve->hash_len);
+	if (!hash)
+		goto fail;
 	if (curve->hash_len == SHA256_MAC_LEN) {
-		sign_md = EVP_sha256();
+		ret = sha256_vector(3, vector, vector_len, hash);
 	} else if (curve->hash_len == SHA384_MAC_LEN) {
-		sign_md = EVP_sha384();
+		ret = sha384_vector(3, vector, vector_len, hash);
 	} else if (curve->hash_len == SHA512_MAC_LEN) {
-		sign_md = EVP_sha512();
+		ret = sha512_vector(3, vector, vector_len, hash);
 	} else {
 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
 		goto fail;
 	}
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
+		goto fail;
+	}
+	wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
+		    hash, curve->hash_len);
 
-	md_ctx = EVP_MD_CTX_create();
-	if (!md_ctx)
+	sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
+	if (!sig) {
+		wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
 		goto fail;
+	}
 
-	ERR_clear_error();
-	if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
-	    EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
-	    EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	signature = os_malloc(signature_len);
-	if (!signature)
-		goto fail;
-	if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
-		    signature, signature_len);
-	/* Convert to raw coordinates r,s */
-	p = signature;
-	sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
-	if (!sig)
-		goto fail;
-	ECDSA_SIG_get0(sig, &r, &s);
-	if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(s, signature + curve->prime_len,
-			   curve->prime_len) < 0)
-		goto fail;
-	signature_len = 2 * curve->prime_len;
 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
-		    signature, signature_len);
-	signed3 = base64_url_encode(signature, signature_len, signed3_len);
+		    wpabuf_head(sig), wpabuf_len(sig));
+	signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
+				    signed3_len);
+
 fail:
-	EVP_MD_CTX_destroy(md_ctx);
-	ECDSA_SIG_free(sig);
-	os_free(signature);
+	os_free(hash);
+	wpabuf_free(sig);
 	return signed3;
 }
 
@@ -2618,7 +1974,7 @@
 			      size_t net_access_key_len)
 {
 	struct wpabuf *pub = NULL;
-	EVP_PKEY *own_key;
+	struct crypto_ec_key *own_key;
 	struct dpp_pfs *pfs;
 
 	pfs = os_zalloc(sizeof(*pfs));
@@ -2631,7 +1987,7 @@
 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
 		goto fail;
 	}
-	EVP_PKEY_free(own_key);
+	crypto_ec_key_deinit(own_key);
 
 	pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
 	if (!pfs->ecdh)
@@ -2696,19 +2052,15 @@
 
 struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
 {
-	X509_REQ *req = NULL;
+	struct crypto_csr *csr = NULL;
 	struct wpabuf *buf = NULL;
-	unsigned char *der;
-	int der_len;
-	EVP_PKEY *key;
-	const EVP_MD *sign_md;
+	struct crypto_ec_key *key;
 	unsigned int hash_len = auth->curve->hash_len;
-	EC_KEY *eckey;
-	BIO *out = NULL;
+	struct wpabuf *priv_key;
 	u8 cp[DPP_CP_LEN];
-	char *password;
-	size_t password_len;
-	int res;
+	char *password = NULL;
+	size_t password_len = 0;
+	int hash_sign_algo;
 
 	/* TODO: use auth->csrattrs */
 
@@ -2716,36 +2068,19 @@
 	 * a specific group to be used */
 	key = auth->own_protocol_key;
 
-	eckey = EVP_PKEY_get1_EC_KEY(key);
-	if (!eckey)
-		goto fail;
-	der = NULL;
-	der_len = i2d_ECPrivateKey(eckey, &der);
-	if (der_len <= 0)
+	priv_key = crypto_ec_key_get_ecprivate_key(key, true);
+	if (!priv_key)
 		goto fail;
 	wpabuf_free(auth->priv_key);
-	auth->priv_key = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
-	if (!auth->priv_key)
+	auth->priv_key = priv_key;
+
+	csr = crypto_csr_init();
+	if (!csr || crypto_csr_set_ec_public_key(csr, key))
 		goto fail;
 
-	req = X509_REQ_new();
-	if (!req || !X509_REQ_set_pubkey(req, key))
+	if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
 		goto fail;
 
-	if (name) {
-		X509_NAME *n;
-
-		n = X509_REQ_get_subject_name(req);
-		if (!n)
-			goto fail;
-
-		if (X509_NAME_add_entry_by_txt(
-			    n, "CN", MBSTRING_UTF8,
-			    (const unsigned char *) name, -1, -1, 0) != 1)
-			goto fail;
-	}
-
 	/* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
 	if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
 			    "CSR challengePassword", cp, DPP_CP_LEN) < 0)
@@ -2755,222 +2090,75 @@
 			cp, DPP_CP_LEN);
 	password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
 	forced_memzero(cp, DPP_CP_LEN);
-	if (!password)
+	if (!password ||
+	    crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
+				     ASN1_TAG_UTF8STRING, (const u8 *) password,
+				     password_len))
 		goto fail;
 
-	res = X509_REQ_add1_attr_by_NID(req, NID_pkcs9_challengePassword,
-					V_ASN1_UTF8STRING,
-					(const unsigned char *) password,
-					password_len);
-	bin_clear_free(password, password_len);
-	if (!res)
-		goto fail;
-
-	/* TODO */
-
 	/* TODO: hash func selection based on csrAttrs */
 	if (hash_len == SHA256_MAC_LEN) {
-		sign_md = EVP_sha256();
+		hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
 	} else if (hash_len == SHA384_MAC_LEN) {
-		sign_md = EVP_sha384();
+		hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
 	} else if (hash_len == SHA512_MAC_LEN) {
-		sign_md = EVP_sha512();
+		hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
 	} else {
 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
 		goto fail;
 	}
 
-	if (!X509_REQ_sign(req, key, sign_md))
+	buf = crypto_csr_sign(csr, key, hash_sign_algo);
+	if (!buf)
 		goto fail;
-
-	der = NULL;
-	der_len = i2d_X509_REQ(req, &der);
-	if (der_len < 0)
-		goto fail;
-	buf = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
-
 	wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
 
 fail:
-	BIO_free_all(out);
-	X509_REQ_free(req);
+	bin_clear_free(password, password_len);
+	crypto_csr_deinit(csr);
 	return buf;
 }
 
 
-struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7)
+int dpp_validate_csr(struct dpp_authentication *auth,
+		     const struct wpabuf *csrbuf)
 {
-#ifdef OPENSSL_IS_BORINGSSL
-	CBS pkcs7_cbs;
-#else /* OPENSSL_IS_BORINGSSL */
-	PKCS7 *p7 = NULL;
-	const unsigned char *p = wpabuf_head(pkcs7);
-#endif /* OPENSSL_IS_BORINGSSL */
-	STACK_OF(X509) *certs;
-	int i, num;
-	BIO *out = NULL;
-	size_t rlen;
-	struct wpabuf *pem = NULL;
-	int res;
-
-#ifdef OPENSSL_IS_BORINGSSL
-	certs = sk_X509_new_null();
-	if (!certs)
-		goto fail;
-	CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7));
-	if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
-		wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-#else /* OPENSSL_IS_BORINGSSL */
-	p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7));
-	if (!p7) {
-		wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	switch (OBJ_obj2nid(p7->type)) {
-	case NID_pkcs7_signed:
-		certs = p7->d.sign->cert;
-		break;
-	case NID_pkcs7_signedAndEnveloped:
-		certs = p7->d.signed_and_enveloped->cert;
-		break;
-	default:
-		certs = NULL;
-		break;
-	}
-#endif /* OPENSSL_IS_BORINGSSL */
-
-	if (!certs || ((num = sk_X509_num(certs)) == 0)) {
-		wpa_printf(MSG_INFO,
-			   "DPP: No certificates found in PKCS#7 object");
-		goto fail;
-	}
-
-	out = BIO_new(BIO_s_mem());
-	if (!out)
-		goto fail;
-
-	for (i = 0; i < num; i++) {
-		X509 *cert = sk_X509_value(certs, i);
-
-		PEM_write_bio_X509(out, cert);
-	}
-
-	rlen = BIO_ctrl_pending(out);
-	pem = wpabuf_alloc(rlen);
-	if (!pem)
-		goto fail;
-	res = BIO_read(out, wpabuf_put(pem, 0), rlen);
-	if (res <= 0) {
-		wpabuf_free(pem);
-		pem = NULL;
-		goto fail;
-	}
-	wpabuf_put(pem, res);
-
-fail:
-#ifdef OPENSSL_IS_BORINGSSL
-	if (certs)
-		sk_X509_pop_free(certs, X509_free);
-#else /* OPENSSL_IS_BORINGSSL */
-	PKCS7_free(p7);
-#endif /* OPENSSL_IS_BORINGSSL */
-	if (out)
-		BIO_free_all(out);
-
-	return pem;
-}
-
-
-int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr)
-{
-	X509_REQ *req;
-	const unsigned char *pos;
-	EVP_PKEY *pkey;
-	int res, loc, ret = -1;
-	X509_ATTRIBUTE *attr;
-	ASN1_TYPE *type;
-	ASN1_STRING *str;
-	unsigned char *utf8 = NULL;
+	struct crypto_csr *csr;
+	const u8 *attr;
+	size_t attr_len;
+	int attr_type;
 	unsigned char *cp = NULL;
 	size_t cp_len;
 	u8 exp_cp[DPP_CP_LEN];
 	unsigned int hash_len = auth->curve->hash_len;
+	int ret = -1;
 
-	pos = wpabuf_head(csr);
-	req = d2i_X509_REQ(NULL, &pos, wpabuf_len(csr));
-	if (!req) {
-		wpa_printf(MSG_DEBUG, "DPP: Failed to parse CSR");
-		return -1;
-	}
-
-	pkey = X509_REQ_get_pubkey(req);
-	if (!pkey) {
-		wpa_printf(MSG_DEBUG, "DPP: Failed to get public key from CSR");
-		goto fail;
-	}
-
-	res = X509_REQ_verify(req, pkey);
-	EVP_PKEY_free(pkey);
-	if (res != 1) {
+	csr = crypto_csr_verify(csrbuf);
+	if (!csr) {
 		wpa_printf(MSG_DEBUG,
-			   "DPP: CSR does not have a valid signature");
+			   "DPP: CSR invalid or invalid signature");
 		goto fail;
 	}
 
-	loc = X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1);
-	if (loc < 0) {
+	attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
+					&attr_len, &attr_type);
+	if (!attr) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: CSR does not include challengePassword");
 		goto fail;
 	}
-
-	attr = X509_REQ_get_attr(req, loc);
-	if (!attr) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not get challengePassword attribute");
-		goto fail;
-	}
-
-	type = X509_ATTRIBUTE_get0_type(attr, 0);
-	if (!type) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not get challengePassword attribute type");
-		goto fail;
-	}
-
-	res = ASN1_TYPE_get(type);
 	/* This is supposed to be UTF8String, but allow other strings as well
 	 * since challengePassword is using ASCII (base64 encoded). */
-	if (res != V_ASN1_UTF8STRING && res != V_ASN1_PRINTABLESTRING &&
-	    res != V_ASN1_IA5STRING) {
+	if (attr_type != ASN1_TAG_UTF8STRING &&
+	    attr_type != ASN1_TAG_PRINTABLESTRING &&
+	    attr_type != ASN1_TAG_IA5STRING) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Unexpected challengePassword attribute type %d",
-			   res);
+			   attr_type);
 		goto fail;
 	}
 
-	str = X509_ATTRIBUTE_get0_data(attr, 0, res, NULL);
-	if (!str) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not get ASN.1 string for challengePassword");
-		goto fail;
-	}
-
-	res = ASN1_STRING_to_UTF8(&utf8, str);
-	if (res < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not get UTF8 version of challengePassword");
-		goto fail;
-	}
-
-	cp = base64_decode((const char *) utf8, res, &cp_len);
-	OPENSSL_free(utf8);
+	cp = base64_decode((const char *) attr, attr_len, &cp_len);
 	if (!cp) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Could not base64 decode challengePassword");
@@ -3001,7 +2189,7 @@
 	ret = 0;
 fail:
 	os_free(cp);
-	X509_REQ_free(req);
+	crypto_csr_deinit(csr);
 	return ret;
 }
 
@@ -3011,50 +2199,46 @@
 					     const u8 *pp_key,
 					     size_t pp_key_len)
 {
-	const unsigned char *p;
-	EVP_PKEY *csign = NULL, *ppkey = NULL;
+	struct crypto_ec_key *csign = NULL, *ppkey = NULL;
 	struct dpp_reconfig_id *id = NULL;
-	BN_CTX *ctx = NULL;
-	BIGNUM *bn = NULL, *q = NULL;
-	const EC_KEY *eckey;
-	const EC_GROUP *group;
-	EC_POINT *e_id = NULL;
+	struct crypto_ec *ec = NULL;
+	const struct crypto_bignum *q;
+	struct crypto_bignum *bn = NULL;
+	struct crypto_ec_point *e_id = NULL;
+	const struct crypto_ec_point *generator;
 
-	p = csign_key;
-	csign = d2i_PUBKEY(NULL, &p, csign_key_len);
+	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
 	if (!csign)
 		goto fail;
 
 	if (!pp_key)
 		goto fail;
-	p = pp_key;
-	ppkey = d2i_PUBKEY(NULL, &p, pp_key_len);
+	ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
 	if (!ppkey)
 		goto fail;
 
-	eckey = EVP_PKEY_get0_EC_KEY(csign);
-	if (!eckey)
-		goto fail;
-	group = EC_KEY_get0_group(eckey);
-	if (!group)
+	ec = crypto_ec_init(crypto_ec_key_group(csign));
+	if (!ec)
 		goto fail;
 
-	e_id = EC_POINT_new(group);
-	ctx = BN_CTX_new();
-	bn = BN_new();
-	q = BN_new();
-	if (!e_id || !ctx || !bn || !q ||
-	    !EC_GROUP_get_order(group, q, ctx) ||
-	    !BN_rand_range(bn, q) ||
-	    !EC_POINT_mul(group, e_id, bn, NULL, NULL, ctx))
+	e_id = crypto_ec_point_init(ec);
+	bn = crypto_bignum_init();
+	q = crypto_ec_get_order(ec);
+	generator = crypto_ec_get_generator(ec);
+	if (!e_id || !bn || !q || !generator ||
+	    crypto_bignum_rand(bn, q) ||
+	    crypto_ec_point_mul(ec, generator, bn, e_id))
 		goto fail;
 
-	dpp_debug_print_point("DPP: Generated random point E-id", group, e_id);
+	crypto_ec_point_debug_print(ec, e_id,
+				    "DPP: Generated random point E-id");
 
 	id = os_zalloc(sizeof(*id));
 	if (!id)
 		goto fail;
-	id->group = group;
+
+	id->ec = ec;
+	ec = NULL;
 	id->e_id = e_id;
 	e_id = NULL;
 	id->csign = csign;
@@ -3062,93 +2246,58 @@
 	id->pp_key = ppkey;
 	ppkey = NULL;
 fail:
-	EC_POINT_free(e_id);
-	EVP_PKEY_free(csign);
-	EVP_PKEY_free(ppkey);
-	BN_clear_free(bn);
-	BN_CTX_free(ctx);
+	crypto_ec_point_deinit(e_id, 1);
+	crypto_ec_key_deinit(csign);
+	crypto_ec_key_deinit(ppkey);
+	crypto_bignum_deinit(bn, 1);
+	crypto_ec_deinit(ec);
 	return id;
 }
 
 
-static EVP_PKEY * dpp_pkey_from_point(const EC_GROUP *group,
-				      const EC_POINT *point)
-{
-	EC_KEY *eckey;
-	EVP_PKEY *pkey = NULL;
-
-	eckey = EC_KEY_new();
-	if (!eckey ||
-	    EC_KEY_set_group(eckey, group) != 1 ||
-	    EC_KEY_set_public_key(eckey, point) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to set EC_KEY: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
-
-	pkey = EVP_PKEY_new();
-	if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
-		EVP_PKEY_free(pkey);
-		pkey = NULL;
-		goto fail;
-	}
-
-fail:
-	EC_KEY_free(eckey);
-	return pkey;
-}
-
-
 int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
 {
-	BN_CTX *ctx = NULL;
-	BIGNUM *bn = NULL, *q = NULL;
-	EC_POINT *e_prime_id = NULL, *a_nonce = NULL;
+	const struct crypto_bignum *q;
+	struct crypto_bignum *bn;
+	const struct crypto_ec_point *pp, *generator;
+	struct crypto_ec_point *e_prime_id, *a_nonce;
 	int ret = -1;
-	const EC_KEY *pp;
-	const EC_POINT *pp_point;
 
-	pp = EVP_PKEY_get0_EC_KEY(id->pp_key);
-	if (!pp)
-		goto fail;
-	pp_point = EC_KEY_get0_public_key(pp);
-	e_prime_id = EC_POINT_new(id->group);
-	a_nonce = EC_POINT_new(id->group);
-	ctx = BN_CTX_new();
-	bn = BN_new();
-	q = BN_new();
+	pp = crypto_ec_key_get_public_key(id->pp_key);
+	e_prime_id = crypto_ec_point_init(id->ec);
+	a_nonce = crypto_ec_point_init(id->ec);
+	bn = crypto_bignum_init();
+	q = crypto_ec_get_order(id->ec);
+	generator = crypto_ec_get_generator(id->ec);
+
 	/* Generate random 0 <= a-nonce < q
 	 * A-NONCE = a-nonce * G
 	 * E'-id = E-id + a-nonce * P_pk */
-	if (!pp_point || !e_prime_id || !a_nonce || !ctx || !bn || !q ||
-	    !EC_GROUP_get_order(id->group, q, ctx) ||
-	    !BN_rand_range(bn, q) || /* bn = a-nonce */
-	    !EC_POINT_mul(id->group, a_nonce, bn, NULL, NULL, ctx) ||
-	    !EC_POINT_mul(id->group, e_prime_id, NULL, pp_point, bn, ctx) ||
-	    !EC_POINT_add(id->group, e_prime_id, id->e_id, e_prime_id, ctx))
+	if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
+	    crypto_bignum_rand(bn, q) || /* bn = a-nonce */
+	    crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
+	    crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
+	    crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
 		goto fail;
 
-	dpp_debug_print_point("DPP: Generated A-NONCE", id->group, a_nonce);
-	dpp_debug_print_point("DPP: Encrypted E-id to E'-id",
-			      id->group, e_prime_id);
+	crypto_ec_point_debug_print(id->ec, a_nonce,
+				    "DPP: Generated A-NONCE");
+	crypto_ec_point_debug_print(id->ec, e_prime_id,
+				    "DPP: Encrypted E-id to E'-id");
 
-	EVP_PKEY_free(id->a_nonce);
-	EVP_PKEY_free(id->e_prime_id);
-	id->a_nonce = dpp_pkey_from_point(id->group, a_nonce);
-	id->e_prime_id = dpp_pkey_from_point(id->group, e_prime_id);
+	crypto_ec_key_deinit(id->a_nonce);
+	crypto_ec_key_deinit(id->e_prime_id);
+	id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
+	id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
 	if (!id->a_nonce || !id->e_prime_id)
 		goto fail;
 
 	ret = 0;
 
 fail:
-	EC_POINT_free(e_prime_id);
-	EC_POINT_free(a_nonce);
-	BN_clear_free(bn);
-	BN_CTX_free(ctx);
+	crypto_ec_point_deinit(e_prime_id, 1);
+	crypto_ec_point_deinit(a_nonce, 1);
+	crypto_bignum_deinit(bn, 1);
 	return ret;
 }
 
@@ -3156,55 +2305,50 @@
 void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
 {
 	if (id) {
-		EC_POINT_clear_free(id->e_id);
-		EVP_PKEY_free(id->csign);
-		EVP_PKEY_free(id->a_nonce);
-		EVP_PKEY_free(id->e_prime_id);
-		EVP_PKEY_free(id->pp_key);
+		crypto_ec_point_deinit(id->e_id, 1);
+		crypto_ec_key_deinit(id->csign);
+		crypto_ec_key_deinit(id->a_nonce);
+		crypto_ec_key_deinit(id->e_prime_id);
+		crypto_ec_key_deinit(id->pp_key);
+		crypto_ec_deinit(id->ec);
 		os_free(id);
 	}
 }
 
 
-EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce,
-			    EVP_PKEY *e_prime_id)
+struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
+					  struct crypto_ec_key *a_nonce,
+					  struct crypto_ec_key *e_prime_id)
 {
-	const EC_KEY *pp_ec, *a_nonce_ec, *e_prime_id_ec;
-	const BIGNUM *pp_bn;
-	const EC_GROUP *group;
-	EC_POINT *e_id = NULL;
-	const EC_POINT *a_nonce_point, *e_prime_id_point;
-	BN_CTX *ctx = NULL;
+	struct crypto_ec *ec;
+	const struct crypto_bignum *pp;
+	struct crypto_ec_point *e_id = NULL;
+	const struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
 
 	if (!ppkey)
 		return NULL;
 
 	/* E-id = E'-id - s_C * A-NONCE */
-	pp_ec = EVP_PKEY_get0_EC_KEY(ppkey);
-	a_nonce_ec = EVP_PKEY_get0_EC_KEY(a_nonce);
-	e_prime_id_ec = EVP_PKEY_get0_EC_KEY(e_prime_id);
-	if (!pp_ec || !a_nonce_ec || !e_prime_id_ec)
+	ec = crypto_ec_init(crypto_ec_key_group(ppkey));
+	if (!ec)
 		return NULL;
-	pp_bn = EC_KEY_get0_private_key(pp_ec);
-	group = EC_KEY_get0_group(pp_ec);
-	a_nonce_point = EC_KEY_get0_public_key(a_nonce_ec);
-	e_prime_id_point = EC_KEY_get0_public_key(e_prime_id_ec);
-	ctx = BN_CTX_new();
-	if (!pp_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx)
-		goto fail;
-	e_id = EC_POINT_new(group);
-	if (!e_id ||
-	    !EC_POINT_mul(group, e_id, NULL, a_nonce_point, pp_bn, ctx) ||
-	    !EC_POINT_invert(group, e_id, ctx) ||
-	    !EC_POINT_add(group, e_id, e_prime_id_point, e_id, ctx)) {
-		EC_POINT_clear_free(e_id);
+
+	pp = crypto_ec_key_get_private_key(ppkey);
+	a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
+	e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
+	e_id = crypto_ec_point_init(ec);
+	if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
+	    crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
+	    crypto_ec_point_invert(ec, e_id) ||
+	    crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
+		crypto_ec_point_deinit(e_id, 1);
 		goto fail;
 	}
 
-	dpp_debug_print_point("DPP: Decrypted E-id", group, e_id);
+	crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
 
 fail:
-	BN_CTX_free(ctx);
+	crypto_ec_deinit(ec);
 	return e_id;
 }
 
@@ -3216,64 +2360,46 @@
 int dpp_test_gen_invalid_key(struct wpabuf *msg,
 			     const struct dpp_curve_params *curve)
 {
-	BN_CTX *ctx;
-	BIGNUM *x, *y;
+	struct crypto_ec *ec;
+	struct crypto_ec_key *key = NULL;
+	const struct crypto_ec_point *pub_key;
+	struct crypto_ec_point *p = NULL;
+	u8 *x, *y;
 	int ret = -1;
-	EC_GROUP *group;
-	EC_POINT *point;
 
-	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
-	if (!group)
-		return -1;
-
-	ctx = BN_CTX_new();
-	point = EC_POINT_new(group);
-	x = BN_new();
-	y = BN_new();
-	if (!ctx || !point || !x || !y)
+	ec = crypto_ec_init(curve->ike_group);
+	x = wpabuf_put(msg, curve->prime_len);
+	y = wpabuf_put(msg, curve->prime_len);
+	if (!ec)
 		goto fail;
 
-	if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1)
+retry:
+	/* Generate valid key pair */
+	key = crypto_ec_key_gen(curve->ike_group);
+	if (!key)
 		goto fail;
 
-	/* Generate a random y coordinate that results in a point that is not
-	 * on the curve. */
-	for (;;) {
-		if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1)
-			goto fail;
+	/* Retrieve public key coordinates */
+	pub_key = crypto_ec_key_get_public_key(key);
+	if (!pub_key)
+		goto fail;
 
-		if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y,
-							ctx) != 1) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
-		/* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL
-		 * return an error from EC_POINT_set_affine_coordinates_GFp()
-		 * when the point is not on the curve. */
-			break;
-#else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */
-			goto fail;
-#endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */
-		}
+	crypto_ec_point_to_bin(ec, pub_key, x, y);
 
-		if (!EC_POINT_is_on_curve(group, point, ctx))
-			break;
+	/* And corrupt them */
+	y[curve->prime_len - 1] ^= 0x01;
+	p = crypto_ec_point_from_bin(ec, x);
+	if (p && crypto_ec_point_is_on_curve(ec, p)) {
+		crypto_ec_point_deinit(p, 0);
+		p = NULL;
+		goto retry;
 	}
 
-	if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0)
-		goto fail;
-
 	ret = 0;
 fail:
-	if (ret < 0)
-		wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key");
-	BN_free(x);
-	BN_free(y);
-	EC_POINT_free(point);
-	BN_CTX_free(ctx);
-	EC_GROUP_free(group);
-
+	crypto_ec_point_deinit(p, 0);
+	crypto_ec_key_deinit(key);
+	crypto_ec_deinit(ec);
 	return ret;
 }
 
diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h
index af12467..0f31ae5 100644
--- a/src/common/dpp_i.h
+++ b/src/common/dpp_i.h
@@ -2,6 +2,7 @@
  * DPP module internal definitions
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -22,6 +23,7 @@
 	struct dl_list tcp_init; /* struct dpp_connection */
 	void *cb_ctx;
 	int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+	bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
 	void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi);
 #endif /* CONFIG_DPP2 */
 };
@@ -37,10 +39,11 @@
 struct json_token * dpp_parse_own_connector(const char *own_connector);
 int dpp_connector_match_groups(struct json_token *own_root,
 			       struct json_token *peer_root, bool reconfig);
-int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
-		  const char *kid, const struct dpp_curve_params *curve);
-EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
-			 const struct dpp_curve_params **key_curve);
+int dpp_build_jwk(struct wpabuf *buf, const char *name,
+		  struct crypto_ec_key *key, const char *kid,
+		  const struct dpp_curve_params *curve);
+struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk,
+				     const struct dpp_curve_params **key_curve);
 int dpp_prepare_channel_list(struct dpp_authentication *auth,
 			     unsigned int neg_freq,
 			     struct hostapd_hw_modes *own_modes, u16 num_modes);
@@ -65,32 +68,27 @@
 
 enum dpp_status_error
 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
-			     EVP_PKEY *csign_pub, const char *connector);
+			     struct crypto_ec_key *csign_pub,
+			     const char *connector);
 enum dpp_status_error
 dpp_check_signed_connector(struct dpp_signed_connector_info *info,
 			   const u8 *csign_key, size_t csign_key_len,
 			   const u8 *peer_connector, size_t peer_connector_len);
 const struct dpp_curve_params * dpp_get_curve_name(const char *name);
 const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name);
-const struct dpp_curve_params * dpp_get_curve_nid(int nid);
 const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group);
 int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
 		       const u8 *data, size_t data_len);
-struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix);
-EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
-				      const u8 *buf_x, const u8 *buf_y,
-				      size_t len);
-EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len);
-int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len);
+struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
+					    const u8 *buf, size_t len);
 int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
 		    const char *label, u8 *out, size_t outlen);
 int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
 		    size_t num_elem, const u8 *addr[], const size_t *len,
 		    u8 *mac);
-int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len);
-void dpp_debug_print_point(const char *title, const EC_GROUP *group,
-			   const EC_POINT *point);
-void dpp_debug_print_key(const char *title, EVP_PKEY *key);
+int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
+	     u8 *secret, size_t *secret_len);
+void dpp_debug_print_key(const char *title, struct crypto_ec_key *key);
 int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len,
 	       const u8 *salt, size_t salt_len, unsigned int iterations,
 	       u8 *buf, size_t buflen);
@@ -99,9 +97,9 @@
 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
 int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
 	       const u8 *privkey, size_t privkey_len);
-EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
-			   const u8 *privkey, size_t privkey_len);
-EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve);
+struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
+				       const u8 *privkey, size_t privkey_len);
+struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve);
 int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len);
 int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len);
 int dpp_derive_bk_ke(struct dpp_authentication *auth);
@@ -111,16 +109,18 @@
 int dpp_auth_derive_l_initiator(struct dpp_authentication *auth);
 int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len);
 int dpp_derive_pmkid(const struct dpp_curve_params *curve,
-		     EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid);
-EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
-			      const u8 *mac_init, const char *code,
-			      const char *identifier, BN_CTX *bnctx,
-			      EC_GROUP **ret_group);
-EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
-			      const u8 *mac_resp, const char *code,
-			      const char *identifier, BN_CTX *bnctx,
-			      EC_GROUP **ret_group);
+		     struct crypto_ec_key *own_key,
+		     struct crypto_ec_key *peer_key, u8 *pmkid);
+struct crypto_ec_point *
+dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
+		   const char *code, const char *identifier,
+		   struct crypto_ec **ret_ec);
+struct crypto_ec_point *
+dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
+		   const char *code, const char *identifier,
+		   struct crypto_ec **ret_ec);
 int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
+		      u8 ver_init, u8 ver_resp,
 		      const u8 *Mx, size_t Mx_len,
 		      const u8 *Nx, size_t Nx_len,
 		      const char *code,
@@ -133,20 +133,21 @@
 int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
 				     const u8 *r_proto, u16 r_proto_len,
 				     struct json_token *net_access_key);
-EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce,
-			    EVP_PKEY *e_prime_id);
+struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
+					  struct crypto_ec_key *a_nonce,
+					  struct crypto_ec_key *e_prime_id);
 char * dpp_sign_connector(struct dpp_configurator *conf,
 			  const struct wpabuf *dppcon);
 int dpp_test_gen_invalid_key(struct wpabuf *msg,
 			     const struct dpp_curve_params *curve);
 
 struct dpp_reconfig_id {
-	const EC_GROUP *group;
-	EC_POINT *e_id; /* E-id */
-	EVP_PKEY *csign;
-	EVP_PKEY *a_nonce; /* A-NONCE */
-	EVP_PKEY *e_prime_id; /* E'-id */
-	EVP_PKEY *pp_key;
+	struct crypto_ec *ec;
+	struct crypto_ec_point *e_id; /* E-id */
+	struct crypto_ec_key *csign;
+	struct crypto_ec_key *a_nonce; /* A-NONCE */
+	struct crypto_ec_key *e_prime_id; /* E'-id */
+	struct crypto_ec_key *pp_key;
 };
 
 /* dpp_tcp.c */
diff --git a/src/common/dpp_pkex.c b/src/common/dpp_pkex.c
index 807ab7d..72084d9 100644
--- a/src/common/dpp_pkex.c
+++ b/src/common/dpp_pkex.c
@@ -8,8 +8,6 @@
  */
 
 #include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
 
 #include "utils/common.h"
 #include "common/wpa_ctrl.h"
@@ -27,42 +25,24 @@
 size_t dpp_pkex_ephemeral_key_override_len = 0;
 #endif /* CONFIG_TESTING_OPTIONS */
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-	(defined(LIBRESSL_VERSION_NUMBER) && \
-	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
 
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
+static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex,
+						   bool v2)
 {
-	if (pkey->type != EVP_PKEY_EC)
-		return NULL;
-	return pkey->pkey.ec;
-}
-
-#endif
-
-
-static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
-{
-	const EC_KEY *X_ec;
-	const EC_POINT *X_point;
-	BN_CTX *bnctx = NULL;
-	EC_GROUP *group = NULL;
-	EC_POINT *Qi = NULL, *M = NULL;
-	struct wpabuf *M_buf = NULL;
-	BIGNUM *Mx = NULL, *My = NULL;
+	struct crypto_ec *ec = NULL;
+	const struct crypto_ec_point *X;
+	struct crypto_ec_point *Qi = NULL, *M = NULL;
+	u8 *Mx, *My;
 	struct wpabuf *msg = NULL;
 	size_t attr_len;
 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
 
-	wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
+	wpa_printf(MSG_DEBUG, "DPP: Build PKEX %sExchange Request",
+		   v2 ? "" : "Version 1 ");
 
-	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
-	bnctx = BN_CTX_new();
-	if (!bnctx)
-		goto fail;
-	Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
-				pkex->identifier, bnctx, &group);
+	/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
+	Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : pkex->own_mac, pkex->code,
+				pkex->identifier, &ec);
 	if (!Qi)
 		goto fail;
 
@@ -86,31 +66,39 @@
 		goto fail;
 
 	/* M = X + Qi */
-	X_ec = EVP_PKEY_get0_EC_KEY(pkex->x);
-	if (!X_ec)
+	X = crypto_ec_key_get_public_key(pkex->x);
+	M = crypto_ec_point_init(ec);
+	if (!X || !M)
 		goto fail;
-	X_point = EC_KEY_get0_public_key(X_ec);
-	if (!X_point)
+	crypto_ec_point_debug_print(ec, X, "DPP: X");
+
+	if (crypto_ec_point_add(ec, X, Qi, M))
 		goto fail;
-	dpp_debug_print_point("DPP: X", group, X_point);
-	M = EC_POINT_new(group);
-	Mx = BN_new();
-	My = BN_new();
-	if (!M || !Mx || !My ||
-	    EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1)
-		goto fail;
-	dpp_debug_print_point("DPP: M", group, M);
+	crypto_ec_point_debug_print(ec, M, "DPP: M");
 
 	/* Initiator -> Responder: group, [identifier,] M */
 	attr_len = 4 + 2;
+#ifdef CONFIG_DPP2
+	if (v2)
+		attr_len += 4 + 1;
+#endif /* CONFIG_DPP2 */
 	if (pkex->identifier)
 		attr_len += 4 + os_strlen(pkex->identifier);
 	attr_len += 4 + 2 * curve->prime_len;
-	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
+	msg = dpp_alloc_msg(v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
+			    DPP_PA_PKEX_V1_EXCHANGE_REQ, attr_len);
 	if (!msg)
 		goto fail;
 
+#ifdef CONFIG_DPP2
+	if (v2) {
+		/* Protocol Version */
+		wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
+		wpabuf_put_le16(msg, 1);
+		wpabuf_put_u8(msg, DPP_VERSION);
+	}
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_TESTING_OPTIONS
 	if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
 		wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group");
@@ -154,21 +142,17 @@
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 
-	if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0)
+	Mx = wpabuf_put(msg, curve->prime_len);
+	My = wpabuf_put(msg, curve->prime_len);
+	if (crypto_ec_point_to_bin(ec, M, Mx, My))
 		goto fail;
 
+	os_memcpy(pkex->Mx, Mx, curve->prime_len);
+
 out:
-	wpabuf_free(M_buf);
-	EC_POINT_free(M);
-	EC_POINT_free(Qi);
-	BN_clear_free(Mx);
-	BN_clear_free(My);
-	BN_CTX_free(bnctx);
-	EC_GROUP_free(group);
+	crypto_ec_point_deinit(M, 1);
+	crypto_ec_point_deinit(Qi, 1);
+	crypto_ec_deinit(ec);
 	return msg;
 fail:
 	wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
@@ -186,8 +170,8 @@
 
 struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
 				const u8 *own_mac,
-				const char *identifier,
-				const char *code)
+				const char *identifier, const char *code,
+				bool v2)
 {
 	struct dpp_pkex *pkex;
 
@@ -204,6 +188,7 @@
 		return NULL;
 	pkex->msg_ctx = msg_ctx;
 	pkex->initiator = 1;
+	pkex->v2 = v2;
 	pkex->own_bi = bi;
 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
 	if (identifier) {
@@ -214,7 +199,7 @@
 	pkex->code = os_strdup(code);
 	if (!pkex->code)
 		goto fail;
-	pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
+	pkex->exchange_req = dpp_pkex_build_exchange_req(pkex, v2);
 	if (!pkex->exchange_req)
 		goto fail;
 	return pkex;
@@ -227,14 +212,19 @@
 static struct wpabuf *
 dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
 			     enum dpp_status_error status,
-			     const BIGNUM *Nx, const BIGNUM *Ny)
+			     const u8 *Nx, const u8 *Ny)
 {
 	struct wpabuf *msg = NULL;
 	size_t attr_len;
 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
 
-	/* Initiator -> Responder: DPP Status, [identifier,] N */
+	/* Initiator -> Responder: DPP Status, [Protocol Version,] [identifier,]
+	 * N */
 	attr_len = 4 + 1;
+#ifdef CONFIG_DPP2
+	if (pkex->v2)
+		attr_len += 4 + 1;
+#endif /* CONFIG_DPP2 */
 	if (pkex->identifier)
 		attr_len += 4 + os_strlen(pkex->identifier);
 	attr_len += 4 + 2 * curve->prime_len;
@@ -261,6 +251,15 @@
 skip_status:
 #endif /* CONFIG_TESTING_OPTIONS */
 
+#ifdef CONFIG_DPP2
+	if (pkex->v2) {
+		/* Protocol Version */
+		wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
+		wpabuf_put_le16(msg, 1);
+		wpabuf_put_u8(msg, DPP_VERSION);
+	}
+#endif /* CONFIG_DPP2 */
+
 	/* Code Identifier attribute */
 	if (pkex->identifier) {
 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
@@ -291,12 +290,9 @@
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 
-	if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0)
-		goto fail;
+	wpabuf_put_data(msg, Nx, curve->prime_len);
+	wpabuf_put_data(msg, Ny, curve->prime_len);
+	os_memcpy(pkex->Nx, Nx, curve->prime_len);
 
 skip_encrypted_key:
 	if (status == DPP_STATUS_BAD_GROUP) {
@@ -345,24 +341,22 @@
 					   const u8 *peer_mac,
 					   const char *identifier,
 					   const char *code,
-					   const u8 *buf, size_t len)
+					   const u8 *buf, size_t len, bool v2)
 {
 	const u8 *attr_group, *attr_id, *attr_key;
 	u16 attr_group_len, attr_id_len, attr_key_len;
 	const struct dpp_curve_params *curve = bi->curve;
 	u16 ike_group;
 	struct dpp_pkex *pkex = NULL;
-	EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL;
-	BN_CTX *bnctx = NULL;
-	EC_GROUP *group = NULL;
-	BIGNUM *Mx = NULL, *My = NULL;
-	const EC_KEY *Y_ec;
-	EC_KEY *X_ec = NULL;
-	const EC_POINT *Y_point;
-	BIGNUM *Nx = NULL, *Ny = NULL;
+	struct crypto_ec_point *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL,
+		*N = NULL;
+	struct crypto_ec *ec = NULL;
+	const struct crypto_ec_point *Y;
+	u8 *x_coord = NULL, *y_coord = NULL;
 	u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
 	size_t Kx_len;
 	int res;
+	u8 peer_version = 0;
 
 	if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
@@ -370,6 +364,24 @@
 		return NULL;
 	}
 
+#ifdef CONFIG_DPP2
+	if (v2) {
+		const u8 *version;
+		u16 version_len;
+
+		version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
+				       &version_len);
+		if (!version || version_len < 1 || version[0] == 0) {
+			wpa_msg(msg_ctx, MSG_INFO,
+				"Missing or invalid Protocol Version attribute");
+			return NULL;
+		}
+		peer_version = version[0];
+		wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
+			   peer_version);
+	}
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_TESTING_OPTIONS
 	if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
 		wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
@@ -404,6 +416,8 @@
 		pkex = os_zalloc(sizeof(*pkex));
 		if (!pkex)
 			goto fail;
+		pkex->v2 = v2;
+		pkex->peer_version = peer_version;
 		pkex->own_bi = bi;
 		pkex->failed = 1;
 		pkex->exchange_resp = dpp_pkex_build_exchange_resp(
@@ -423,44 +437,42 @@
 		return NULL;
 	}
 
-	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
-	bnctx = BN_CTX_new();
-	if (!bnctx)
-		goto fail;
-	Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx,
-				&group);
+	/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
+	Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : peer_mac, code, identifier,
+				&ec);
 	if (!Qi)
 		goto fail;
 
 	/* X' = M - Qi */
-	X = EC_POINT_new(group);
-	M = EC_POINT_new(group);
-	Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
-	My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
-	if (!X || !M || !Mx || !My ||
-	    EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, M) ||
-	    !EC_POINT_is_on_curve(group, M, bnctx) ||
-	    EC_POINT_invert(group, Qi, bnctx) != 1 ||
-	    EC_POINT_add(group, X, M, Qi, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, X) ||
-	    !EC_POINT_is_on_curve(group, X, bnctx)) {
+	X = crypto_ec_point_init(ec);
+	M = crypto_ec_point_from_bin(ec, attr_key);
+	if (!X || !M ||
+	    crypto_ec_point_is_at_infinity(ec, M) ||
+	    !crypto_ec_point_is_on_curve(ec, M) ||
+	    crypto_ec_point_invert(ec, Qi) ||
+	    crypto_ec_point_add(ec, M, Qi, X) ||
+	    crypto_ec_point_is_at_infinity(ec, X) ||
+	    !crypto_ec_point_is_on_curve(ec, X)) {
 		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
 			"Invalid Encrypted Key value");
 		bi->pkex_t++;
 		goto fail;
 	}
-	dpp_debug_print_point("DPP: M", group, M);
-	dpp_debug_print_point("DPP: X'", group, X);
+	crypto_ec_point_debug_print(ec, M, "DPP: M");
+	crypto_ec_point_debug_print(ec, X, "DPP: X'");
 
 	pkex = os_zalloc(sizeof(*pkex));
 	if (!pkex)
 		goto fail;
+	pkex->v2 = v2;
+	pkex->peer_version = peer_version;
 	pkex->t = bi->pkex_t;
 	pkex->msg_ctx = msg_ctx;
 	pkex->own_bi = bi;
-	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
-	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
+	if (own_mac)
+		os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
+	if (peer_mac)
+		os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
 	if (identifier) {
 		pkex->identifier = os_strdup(identifier);
 		if (!pkex->identifier)
@@ -472,18 +484,20 @@
 
 	os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
 
-	X_ec = EC_KEY_new();
-	if (!X_ec ||
-	    EC_KEY_set_group(X_ec, group) != 1 ||
-	    EC_KEY_set_public_key(X_ec, X) != 1)
-		goto fail;
-	pkex->x = EVP_PKEY_new();
-	if (!pkex->x ||
-	    EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1)
+	x_coord = os_malloc(curve->prime_len);
+	y_coord = os_malloc(curve->prime_len);
+	if (!x_coord || !y_coord ||
+	    crypto_ec_point_to_bin(ec, X, x_coord, y_coord))
 		goto fail;
 
-	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
-	Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL);
+	pkex->x = crypto_ec_key_set_pub(curve->ike_group, x_coord,
+					y_coord, crypto_ec_prime_len(ec));
+	if (!pkex->x)
+		goto fail;
+
+	/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
+	Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, identifier,
+				NULL);
 	if (!Qr)
 		goto fail;
 
@@ -507,24 +521,20 @@
 		goto fail;
 
 	/* N = Y + Qr */
-	Y_ec = EVP_PKEY_get0_EC_KEY(pkex->y);
-	if (!Y_ec)
+	Y = crypto_ec_key_get_public_key(pkex->y);
+	if (!Y)
 		goto fail;
-	Y_point = EC_KEY_get0_public_key(Y_ec);
-	if (!Y_point)
+	crypto_ec_point_debug_print(ec, Y, "DPP: Y");
+
+	N = crypto_ec_point_init(ec);
+	if (!N ||
+	    crypto_ec_point_add(ec, Y, Qr, N) ||
+	    crypto_ec_point_to_bin(ec, N, x_coord, y_coord))
 		goto fail;
-	dpp_debug_print_point("DPP: Y", group, Y_point);
-	N = EC_POINT_new(group);
-	Nx = BN_new();
-	Ny = BN_new();
-	if (!N || !Nx || !Ny ||
-	    EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1)
-		goto fail;
-	dpp_debug_print_point("DPP: N", group, N);
+	crypto_ec_point_debug_print(ec, N, "DPP: N");
 
 	pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK,
-							   Nx, Ny);
+							   x_coord, y_coord);
 	if (!pkex->exchange_resp)
 		goto fail;
 
@@ -535,9 +545,10 @@
 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
 			Kx, Kx_len);
 
-	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
-	 */
-	res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
+	/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
+	res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->peer_mac,
+				pkex->v2 ? NULL : pkex->own_mac,
+				pkex->peer_version, DPP_VERSION,
 				pkex->Mx, curve->prime_len,
 				pkex->Nx, curve->prime_len, pkex->code,
 				Kx, Kx_len, pkex->z, curve->hash_len);
@@ -548,18 +559,14 @@
 	pkex->exchange_done = 1;
 
 out:
-	BN_CTX_free(bnctx);
-	EC_POINT_free(Qi);
-	EC_POINT_free(Qr);
-	BN_free(Mx);
-	BN_free(My);
-	BN_free(Nx);
-	BN_free(Ny);
-	EC_POINT_free(M);
-	EC_POINT_free(N);
-	EC_POINT_free(X);
-	EC_KEY_free(X_ec);
-	EC_GROUP_free(group);
+	os_free(x_coord);
+	os_free(y_coord);
+	crypto_ec_point_deinit(Qi, 1);
+	crypto_ec_point_deinit(Qr, 1);
+	crypto_ec_point_deinit(M, 1);
+	crypto_ec_point_deinit(N, 1);
+	crypto_ec_point_deinit(X, 1);
+	crypto_ec_deinit(ec);
 	return pkex;
 fail:
 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed");
@@ -688,17 +695,16 @@
 {
 	const u8 *attr_status, *attr_id, *attr_key, *attr_group;
 	u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len;
-	EC_GROUP *group = NULL;
-	BN_CTX *bnctx = NULL;
+	struct crypto_ec *ec = NULL;
 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
-	BIGNUM *Nx = NULL, *Ny = NULL;
-	EC_KEY *Y_ec = NULL;
+	struct crypto_ec_point *Qr = NULL, *Y = NULL, *N = NULL;
+	u8 *x_coord = NULL, *y_coord = NULL;
 	size_t Jx_len, Kx_len;
 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
 	const u8 *addr[4];
 	size_t len[4];
+	size_t num_elem;
 	u8 u[DPP_MAX_HASH_LEN];
 	int res;
 
@@ -720,7 +726,26 @@
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 
-	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
+#ifdef CONFIG_DPP2
+	if (pkex->v2) {
+		const u8 *version;
+		u16 version_len;
+
+		version = dpp_get_attr(buf, buflen, DPP_ATTR_PROTOCOL_VERSION,
+				       &version_len);
+		if (!version || version_len < 1 || version[0] == 0) {
+		dpp_pkex_fail(pkex,
+			      "Missing or invalid Protocol Version attribute");
+			return NULL;
+		}
+		pkex->peer_version = version[0];
+		wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
+			   pkex->peer_version);
+	}
+#endif /* CONFIG_DPP2 */
+
+	if (peer_mac)
+		os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
 
 	attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
 				   &attr_status_len);
@@ -764,46 +789,40 @@
 		return NULL;
 	}
 
-	/* Qr = H(MAC-Responder | [identifier |] code) * Pr */
-	bnctx = BN_CTX_new();
-	if (!bnctx)
-		goto fail;
-	Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
-				pkex->identifier, bnctx, &group);
+	/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
+	Qr = dpp_pkex_derive_Qr(curve, pkex->v2 ? NULL : pkex->peer_mac,
+				pkex->code, pkex->identifier, &ec);
 	if (!Qr)
 		goto fail;
 
 	/* Y' = N - Qr */
-	Y = EC_POINT_new(group);
-	N = EC_POINT_new(group);
-	Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
-	Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
-	if (!Y || !N || !Nx || !Ny ||
-	    EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, N) ||
-	    !EC_POINT_is_on_curve(group, N, bnctx) ||
-	    EC_POINT_invert(group, Qr, bnctx) != 1 ||
-	    EC_POINT_add(group, Y, N, Qr, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, Y) ||
-	    !EC_POINT_is_on_curve(group, Y, bnctx)) {
+	Y = crypto_ec_point_init(ec);
+	N = crypto_ec_point_from_bin(ec, attr_key);
+	if (!Y || !N ||
+	    crypto_ec_point_is_at_infinity(ec, N) ||
+	    !crypto_ec_point_is_on_curve(ec, N) ||
+	    crypto_ec_point_invert(ec, Qr) ||
+	    crypto_ec_point_add(ec, N, Qr, Y) ||
+	    crypto_ec_point_is_at_infinity(ec, Y) ||
+	    !crypto_ec_point_is_on_curve(ec, Y)) {
 		dpp_pkex_fail(pkex, "Invalid Encrypted Key value");
 		pkex->t++;
 		goto fail;
 	}
-	dpp_debug_print_point("DPP: N", group, N);
-	dpp_debug_print_point("DPP: Y'", group, Y);
+	crypto_ec_point_debug_print(ec, N, "DPP: N");
+	crypto_ec_point_debug_print(ec, Y, "DPP: Y'");
 
 	pkex->exchange_done = 1;
 
 	/* ECDH: J = a * Y' */
-	Y_ec = EC_KEY_new();
-	if (!Y_ec ||
-	    EC_KEY_set_group(Y_ec, group) != 1 ||
-	    EC_KEY_set_public_key(Y_ec, Y) != 1)
+	x_coord = os_malloc(curve->prime_len);
+	y_coord = os_malloc(curve->prime_len);
+	if (!x_coord || !y_coord ||
+	    crypto_ec_point_to_bin(ec, Y, x_coord, y_coord))
 		goto fail;
-	pkex->y = EVP_PKEY_new();
-	if (!pkex->y ||
-	    EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
+	pkex->y = crypto_ec_key_set_pub(curve->ike_group, x_coord, y_coord,
+					curve->prime_len);
+	if (!pkex->y)
 		goto fail;
 	if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0)
 		goto fail;
@@ -811,21 +830,29 @@
 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
 			Jx, Jx_len);
 
-	/* u = HMAC(J.x, MAC-Initiator | A.x | Y'.x | X.x) */
-	A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
-	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
-	X_pub = dpp_get_pubkey_point(pkex->x, 0);
+	/* u = HMAC(J.x, [MAC-Initiator |] A.x | Y'.x | X.x) */
+	A_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
+	Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
+	X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
 	if (!A_pub || !Y_pub || !X_pub)
 		goto fail;
-	addr[0] = pkex->own_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(A_pub);
-	len[1] = wpabuf_len(A_pub) / 2;
-	addr[2] = wpabuf_head(Y_pub);
-	len[2] = wpabuf_len(Y_pub) / 2;
-	addr[3] = wpabuf_head(X_pub);
-	len[3] = wpabuf_len(X_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
+	num_elem = 0;
+	if (!pkex->v2) {
+		addr[num_elem] = pkex->own_mac;
+		len[num_elem] = ETH_ALEN;
+		num_elem++;
+	}
+	addr[num_elem] = wpabuf_head(A_pub);
+	len[num_elem] = wpabuf_len(A_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(Y_pub);
+	len[num_elem] = wpabuf_len(Y_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(X_pub);
+	len[num_elem] = wpabuf_len(X_pub) / 2;
+	num_elem++;
+	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
+	    < 0)
 		goto fail;
 	wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
 
@@ -836,9 +863,10 @@
 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
 			Kx, Kx_len);
 
-	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
-	 */
-	res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
+	/* z = HKDF(<>, info | M.x | N.x | code, K.x) */
+	res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->own_mac,
+				pkex->v2 ? NULL : pkex->peer_mac,
+				DPP_VERSION, pkex->peer_version,
 				pkex->Mx, curve->prime_len,
 				attr_key /* N.x */, attr_key_len / 2,
 				pkex->code, Kx, Kx_len,
@@ -855,14 +883,12 @@
 	wpabuf_free(A_pub);
 	wpabuf_free(X_pub);
 	wpabuf_free(Y_pub);
-	EC_POINT_free(Qr);
-	EC_POINT_free(Y);
-	EC_POINT_free(N);
-	BN_free(Nx);
-	BN_free(Ny);
-	EC_KEY_free(Y_ec);
-	BN_CTX_free(bnctx);
-	EC_GROUP_free(group);
+	os_free(x_coord);
+	os_free(y_coord);
+	crypto_ec_point_deinit(Qr, 1);
+	crypto_ec_point_deinit(Y, 1);
+	crypto_ec_point_deinit(N, 1);
+	crypto_ec_deinit(ec);
 	return msg;
 fail:
 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed");
@@ -995,6 +1021,7 @@
 	u16 wrapped_data_len, b_key_len, peer_u_len = 0;
 	const u8 *addr[4];
 	size_t len[4];
+	size_t num_elem;
 	u8 octet;
 	u8 *unwrapped = NULL;
 	size_t unwrapped_len = 0;
@@ -1077,21 +1104,29 @@
 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
 			Jx, Jx_len);
 
-	/* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
-	A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
-	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
-	X_pub = dpp_get_pubkey_point(pkex->x, 0);
+	/* u' = HMAC(J'.x, [MAC-Initiator |] A'.x | Y.x | X'.x) */
+	A_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
+	Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
+	X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
 	if (!A_pub || !Y_pub || !X_pub)
 		goto fail;
-	addr[0] = pkex->peer_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(A_pub);
-	len[1] = wpabuf_len(A_pub) / 2;
-	addr[2] = wpabuf_head(Y_pub);
-	len[2] = wpabuf_len(Y_pub) / 2;
-	addr[3] = wpabuf_head(X_pub);
-	len[3] = wpabuf_len(X_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
+	num_elem = 0;
+	if (!pkex->v2) {
+		addr[num_elem] = pkex->peer_mac;
+		len[num_elem] = ETH_ALEN;
+		num_elem++;
+	}
+	addr[num_elem] = wpabuf_head(A_pub);
+	len[num_elem] = wpabuf_len(A_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(Y_pub);
+	len[num_elem] = wpabuf_len(Y_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(X_pub);
+	len[num_elem] = wpabuf_len(X_pub) / 2;
+	num_elem++;
+	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
+	    < 0)
 		goto fail;
 
 	peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
@@ -1114,19 +1149,27 @@
 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
 			Lx, Lx_len);
 
-	/* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
-	B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
+	/* v = HMAC(L.x, [MAC-Responder |] B.x | X'.x | Y.x) */
+	B_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
 	if (!B_pub)
 		goto fail;
-	addr[0] = pkex->own_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(B_pub);
-	len[1] = wpabuf_len(B_pub) / 2;
-	addr[2] = wpabuf_head(X_pub);
-	len[2] = wpabuf_len(X_pub) / 2;
-	addr[3] = wpabuf_head(Y_pub);
-	len[3] = wpabuf_len(Y_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
+	num_elem = 0;
+	if (!pkex->v2) {
+		addr[num_elem] = pkex->own_mac;
+		len[num_elem] = ETH_ALEN;
+		num_elem++;
+	}
+	addr[num_elem] = wpabuf_head(B_pub);
+	len[num_elem] = wpabuf_len(B_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(X_pub);
+	len[num_elem] = wpabuf_len(X_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(Y_pub);
+	len[num_elem] = wpabuf_len(Y_pub) / 2;
+	num_elem++;
+	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
+	    < 0)
 		goto fail;
 	wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
 
@@ -1156,6 +1199,7 @@
 	u16 wrapped_data_len, b_key_len, peer_v_len = 0;
 	const u8 *addr[4];
 	size_t len[4];
+	size_t num_elem;
 	u8 octet;
 	u8 *unwrapped = NULL;
 	size_t unwrapped_len = 0;
@@ -1239,21 +1283,29 @@
 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
 			Lx, Lx_len);
 
-	/* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
-	B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
-	X_pub = dpp_get_pubkey_point(pkex->x, 0);
-	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
+	/* v' = HMAC(L.x, [MAC-Responder |] B'.x | X.x | Y'.x) */
+	B_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
+	X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
+	Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
 	if (!B_pub || !X_pub || !Y_pub)
 		goto fail;
-	addr[0] = pkex->peer_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(B_pub);
-	len[1] = wpabuf_len(B_pub) / 2;
-	addr[2] = wpabuf_head(X_pub);
-	len[2] = wpabuf_len(X_pub) / 2;
-	addr[3] = wpabuf_head(Y_pub);
-	len[3] = wpabuf_len(Y_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
+	num_elem = 0;
+	if (!pkex->v2) {
+		addr[num_elem] = pkex->peer_mac;
+		len[num_elem] = ETH_ALEN;
+		num_elem++;
+	}
+	addr[num_elem] = wpabuf_head(B_pub);
+	len[num_elem] = wpabuf_len(B_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(X_pub);
+	len[num_elem] = wpabuf_len(X_pub) / 2;
+	num_elem++;
+	addr[num_elem] = wpabuf_head(Y_pub);
+	len[num_elem] = wpabuf_len(Y_pub) / 2;
+	num_elem++;
+	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
+	    < 0)
 		goto fail;
 
 	peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
@@ -1292,9 +1344,12 @@
 		return NULL;
 	bi->id = dpp_next_id(dpp);
 	bi->type = DPP_BOOTSTRAP_PKEX;
-	os_memcpy(bi->mac_addr, peer, ETH_ALEN);
-	bi->num_freq = 1;
-	bi->freq[0] = freq;
+	if (peer)
+		os_memcpy(bi->mac_addr, peer, ETH_ALEN);
+	if (freq) {
+		bi->num_freq = 1;
+		bi->freq[0] = freq;
+	}
 	bi->curve = pkex->own_bi->curve;
 	bi->pubkey = pkex->peer_bootstrap_key;
 	pkex->peer_bootstrap_key = NULL;
@@ -1315,9 +1370,9 @@
 
 	os_free(pkex->identifier);
 	os_free(pkex->code);
-	EVP_PKEY_free(pkex->x);
-	EVP_PKEY_free(pkex->y);
-	EVP_PKEY_free(pkex->peer_bootstrap_key);
+	crypto_ec_key_deinit(pkex->x);
+	crypto_ec_key_deinit(pkex->y);
+	crypto_ec_key_deinit(pkex->peer_bootstrap_key);
 	wpabuf_free(pkex->exchange_req);
 	wpabuf_free(pkex->exchange_resp);
 	os_free(pkex);
diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c
index c4a0273..7137bc5 100644
--- a/src/common/dpp_reconfig.c
+++ b/src/common/dpp_reconfig.c
@@ -7,8 +7,6 @@
  */
 
 #include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
 
 #include "utils/common.h"
 #include "utils/json.h"
@@ -40,8 +38,7 @@
 						struct dpp_reconfig_id *id)
 {
 	struct wpabuf *msg = NULL;
-	EVP_PKEY *csign = NULL;
-	const unsigned char *p;
+	struct crypto_ec_key *csign = NULL;
 	struct wpabuf *uncomp;
 	u8 hash[SHA256_MAC_LEN];
 	const u8 *addr[1];
@@ -49,7 +46,7 @@
 	int res;
 	size_t attr_len;
 	const struct dpp_curve_params *own_curve;
-	EVP_PKEY *own_key;
+	struct crypto_ec_key *own_key;
 	struct wpabuf *a_nonce = NULL, *e_id = NULL;
 
 	wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame");
@@ -61,16 +58,15 @@
 		goto fail;
 	}
 
-	p = csign_key;
-	csign = d2i_PUBKEY(NULL, &p, csign_key_len);
+	csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
 	if (!csign) {
 		wpa_printf(MSG_ERROR,
 			   "DPP: Failed to parse local C-sign-key information");
 		goto fail;
 	}
 
-	uncomp = dpp_get_pubkey_point(csign, 1);
-	EVP_PKEY_free(csign);
+	uncomp = crypto_ec_key_get_pubkey_point(csign, 1);
+	crypto_ec_key_deinit(csign);
 	if (!uncomp)
 		goto fail;
 	addr[0] = wpabuf_head(uncomp);
@@ -88,8 +84,8 @@
 		goto fail;
 	}
 
-	a_nonce = dpp_get_pubkey_point(id->a_nonce, 0);
-	e_id = dpp_get_pubkey_point(id->e_prime_id, 0);
+	a_nonce = crypto_ec_key_get_pubkey_point(id->a_nonce, 0);
+	e_id = crypto_ec_key_get_pubkey_point(id->e_prime_id, 0);
 	if (!a_nonce || !e_id)
 		goto fail;
 
@@ -126,7 +122,7 @@
 fail:
 	wpabuf_free(a_nonce);
 	wpabuf_free(e_id);
-	EVP_PKEY_free(own_key);
+	crypto_ec_key_deinit(own_key);
 	return msg;
 }
 
@@ -230,8 +226,8 @@
 {
 	struct dpp_authentication *auth;
 	const struct dpp_curve_params *curve;
-	EVP_PKEY *a_nonce, *e_prime_id;
-	EC_POINT *e_id;
+	struct crypto_ec_key *a_nonce, *e_prime_id;
+	struct crypto_ec_point *e_id;
 
 	curve = dpp_get_curve_ike_group(group);
 	if (!curve) {
@@ -260,13 +256,13 @@
 	e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len);
 	if (!e_prime_id) {
 		wpa_printf(MSG_INFO, "DPP: Invalid E'-id");
-		EVP_PKEY_free(a_nonce);
+		crypto_ec_key_deinit(a_nonce);
 		return NULL;
 	}
 	dpp_debug_print_key("E'-id", e_prime_id);
 	e_id = dpp_decrypt_e_id(conf->pp_key, a_nonce, e_prime_id);
-	EVP_PKEY_free(a_nonce);
-	EVP_PKEY_free(e_prime_id);
+	crypto_ec_key_deinit(a_nonce);
+	crypto_ec_key_deinit(e_prime_id);
 	if (!e_id) {
 		wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id");
 		return NULL;
@@ -275,7 +271,7 @@
 	 * Enrollee has already been started and is waiting for updated
 	 * configuration instead of replying again before such configuration
 	 * becomes available */
-	EC_POINT_clear_free(e_id);
+	crypto_ec_point_deinit(e_id, 1);
 
 	auth = dpp_alloc_auth(dpp, msg_ctx);
 	if (!auth)
@@ -341,7 +337,7 @@
 	wpabuf_put_le16(clear, wpabuf_len(conn_status));
 	wpabuf_put_buf(clear, conn_status);
 
-	pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+	pr = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
 	if (!pr)
 		goto fail;
 
diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c
index 609c243..e88c6de 100644
--- a/src/common/dpp_tcp.c
+++ b/src/common/dpp_tcp.c
@@ -1,6 +1,7 @@
 /*
  * DPP over TCP
  * Copyright (c) 2019-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -24,10 +25,13 @@
 	struct dpp_controller *ctrl;
 	struct dpp_relay_controller *relay;
 	struct dpp_global *global;
+	struct dpp_pkex *pkex;
 	struct dpp_authentication *auth;
 	void *msg_ctx;
 	void *cb_ctx;
 	int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+	int (*pkex_done)(void *ctx, void *conn, struct dpp_bootstrap_info *bi);
+	bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
 	int sock;
 	u8 mac_addr[ETH_ALEN];
 	unsigned int freq;
@@ -71,9 +75,13 @@
 	struct dl_list conn; /* struct dpp_connection */
 	char *configurator_params;
 	enum dpp_netrole netrole;
+	struct dpp_bootstrap_info *pkex_bi;
+	char *pkex_code;
+	char *pkex_identifier;
 	void *msg_ctx;
 	void *cb_ctx;
 	int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+	bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
 };
 
 static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
@@ -82,6 +90,7 @@
 					int initiator);
 static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx);
 static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx);
+static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx);
 
 
 static void dpp_connection_free(struct dpp_connection *conn)
@@ -97,9 +106,11 @@
 			     conn, NULL);
 	eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL);
 	eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
+	eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
 	wpabuf_free(conn->msg);
 	wpabuf_free(conn->msg_out);
 	dpp_auth_deinit(conn->auth);
+	dpp_pkex_free(conn->pkex);
 	os_free(conn->name);
 	os_free(conn);
 }
@@ -154,6 +165,24 @@
 }
 
 
+static struct dpp_relay_controller *
+dpp_relay_controller_get_ctx(struct dpp_global *dpp, void *cb_ctx)
+{
+	struct dpp_relay_controller *ctrl;
+
+	if (!dpp)
+		return NULL;
+
+	dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
+			 list) {
+		if (cb_ctx == ctrl->cb_ctx)
+			return ctrl;
+	}
+
+	return NULL;
+}
+
+
 static void dpp_controller_gas_done(struct dpp_connection *conn)
 {
 	struct dpp_authentication *auth = conn->auth;
@@ -219,6 +248,10 @@
 				dpp_controller_rx, conn, NULL) == 0)
 		conn->read_eloop = 1;
 	if (conn->on_tcp_tx_complete_remove) {
+		if (conn->auth && conn->auth->connect_on_tx_status &&
+		    conn->tcp_msg_sent &&
+		    conn->tcp_msg_sent(conn->cb_ctx, conn->auth))
+			return 0;
 		dpp_connection_remove(conn);
 	} else if (conn->auth && (conn->ctrl || conn->auth->configurator) &&
 		   conn->on_tcp_tx_complete_gas_done) {
@@ -352,6 +385,16 @@
 }
 
 
+static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct dpp_connection *conn = eloop_ctx;
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP: Timeout while waiting for relayed connection to complete");
+	dpp_connection_remove(conn);
+}
+
+
 static struct dpp_connection *
 dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
 		   unsigned int freq)
@@ -412,8 +455,8 @@
 		goto fail;
 	conn->write_eloop = 1;
 
-	/* TODO: eloop timeout to clear a connection if it does not complete
-	 * properly */
+	eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
+	eloop_register_timeout(20, 0, dpp_relay_conn_timeout, conn, NULL);
 
 	dl_list_add(&ctrl->conn, &conn->list);
 	return conn;
@@ -465,7 +508,8 @@
 
 int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
 			const u8 *buf, size_t len, unsigned int freq,
-			const u8 *i_bootstrap, const u8 *r_bootstrap)
+			const u8 *i_bootstrap, const u8 *r_bootstrap,
+			void *cb_ctx)
 {
 	struct dpp_relay_controller *ctrl;
 	struct dpp_connection *conn;
@@ -493,8 +537,9 @@
 	    type == DPP_PA_RECONFIG_ANNOUNCEMENT) {
 		/* TODO: Could send this to all configured Controllers. For now,
 		 * only the first Controller is supported. */
-		ctrl = dl_list_first(&dpp->controllers,
-				     struct dpp_relay_controller, list);
+		ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
+	} else if (type == DPP_PA_PKEX_EXCHANGE_REQ) {
+		ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
 	} else {
 		if (!r_bootstrap)
 			return -1;
@@ -579,6 +624,8 @@
 		eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
 	}
 	os_free(ctrl->configurator_params);
+	os_free(ctrl->pkex_code);
+	os_free(ctrl->pkex_identifier);
 	os_free(ctrl);
 }
 
@@ -641,10 +688,8 @@
 	}
 
 	if (dpp_set_configurator(conn->auth,
-				 conn->ctrl->configurator_params) < 0) {
-		dpp_connection_remove(conn);
+				 conn->ctrl->configurator_params) < 0)
 		return -1;
-	}
 
 	return dpp_tcp_send_msg(conn, conn->auth->resp_msg);
 }
@@ -670,7 +715,6 @@
 			return 0;
 		}
 		wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
-		dpp_connection_remove(conn);
 		return -1;
 	}
 
@@ -744,6 +788,7 @@
 		wpa_msg(msg_ctx, MSG_INFO,
 			DPP_EVENT_CONF_SENT "wait_conn_status=1");
 		wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
+		auth->waiting_conn_status_result = 1;
 		eloop_cancel_timeout(
 			dpp_controller_conn_status_result_wait_timeout,
 			conn, NULL);
@@ -832,7 +877,6 @@
 		return -1;
 	if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
 		dpp_auth_deinit(auth);
-		dpp_connection_remove(conn);
 		return -1;
 	}
 
@@ -929,6 +973,143 @@
 }
 
 
+static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn,
+					       const u8 *hdr, const u8 *buf,
+					       size_t len)
+{
+	struct dpp_controller *ctrl = conn->ctrl;
+
+	if (!ctrl)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request");
+
+	/* TODO: Support multiple PKEX codes by iterating over all the enabled
+	 * values here */
+
+	if (!ctrl->pkex_code || !ctrl->pkex_bi) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: No PKEX code configured - ignore request");
+		return 0;
+	}
+
+	if (conn->pkex || conn->auth) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Already in PKEX/Authentication session - ignore new PKEX request");
+		return 0;
+	}
+
+	conn->pkex = dpp_pkex_rx_exchange_req(conn->ctrl->global, ctrl->pkex_bi,
+					      NULL, NULL,
+					      ctrl->pkex_identifier,
+					      ctrl->pkex_code,
+					      buf, len, true);
+	if (!conn->pkex) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Failed to process the request");
+		return -1;
+	}
+
+	return dpp_tcp_send_msg(conn, conn->pkex->exchange_resp);
+}
+
+
+static int dpp_controller_rx_pkex_exchange_resp(struct dpp_connection *conn,
+						const u8 *hdr, const u8 *buf,
+						size_t len)
+{
+	struct dpp_pkex *pkex = conn->pkex;
+	struct wpabuf *msg;
+	int res;
+
+	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response");
+
+	if (!pkex || !pkex->initiator || pkex->exchange_done) {
+		wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+		return 0;
+	}
+
+	msg = dpp_pkex_rx_exchange_resp(pkex, NULL, buf, len);
+	if (!msg) {
+		wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request");
+	res = dpp_tcp_send_msg(conn, msg);
+	wpabuf_free(msg);
+	return res;
+}
+
+
+static int dpp_controller_rx_pkex_commit_reveal_req(struct dpp_connection *conn,
+						    const u8 *hdr,
+						    const u8 *buf, size_t len)
+{
+	struct dpp_pkex *pkex = conn->pkex;
+	struct wpabuf *msg;
+	int res;
+	struct dpp_bootstrap_info *bi;
+
+	wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request");
+
+	if (!pkex || pkex->initiator || !pkex->exchange_done) {
+		wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+		return 0;
+	}
+
+	msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
+	if (!msg) {
+		wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response");
+	res = dpp_tcp_send_msg(conn, msg);
+	wpabuf_free(msg);
+	if (res < 0)
+		return res;
+	bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
+	if (!bi)
+		return -1;
+	conn->pkex = NULL;
+	return 0;
+}
+
+
+static int
+dpp_controller_rx_pkex_commit_reveal_resp(struct dpp_connection *conn,
+					  const u8 *hdr,
+					  const u8 *buf, size_t len)
+{
+	struct dpp_pkex *pkex = conn->pkex;
+	int res;
+	struct dpp_bootstrap_info *bi;
+
+	wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response");
+
+	if (!pkex || !pkex->initiator || !pkex->exchange_done) {
+		wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+		return 0;
+	}
+
+	res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
+	if (res < 0) {
+		wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
+		return res;
+	}
+
+	bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
+	if (!bi)
+		return -1;
+	conn->pkex = NULL;
+
+	if (!conn->pkex_done)
+		return -1;
+	return conn->pkex_done(conn->cb_ctx, conn, bi);
+}
+
+
 static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
 				    size_t len)
 {
@@ -988,6 +1169,22 @@
 	case DPP_PA_RECONFIG_AUTH_RESP:
 		return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos,
 							    end - pos);
+	case DPP_PA_PKEX_V1_EXCHANGE_REQ:
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Ignore PKEXv1 Exchange Request - not supported over TCP");
+		return -1;
+	case DPP_PA_PKEX_EXCHANGE_REQ:
+		return dpp_controller_rx_pkex_exchange_req(conn, msg, pos,
+							   end - pos);
+	case DPP_PA_PKEX_EXCHANGE_RESP:
+		return dpp_controller_rx_pkex_exchange_resp(conn, msg, pos,
+							    end - pos);
+	case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
+		return dpp_controller_rx_pkex_commit_reveal_req(conn, msg, pos,
+								end - pos);
+	case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
+		return dpp_controller_rx_pkex_commit_reveal_resp(conn, msg, pos,
+								 end - pos);
 	default:
 		/* TODO: missing messages types */
 		wpa_printf(MSG_DEBUG,
@@ -1131,6 +1328,52 @@
 						   WLAN_PA_GAS_INITIAL_RESP);
 	}
 
+	if (!resp && auth->waiting_config && auth->peer_bi) {
+		char *buf = NULL, *name = "";
+		char band[200], *b_pos, *b_end;
+		int i, res, *opclass = auth->e_band_support;
+		char *mud_url = "N/A";
+
+		wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
+		if (auth->e_name) {
+			size_t e_len = os_strlen(auth->e_name);
+
+			buf = os_malloc(e_len * 4 + 1);
+			if (buf) {
+				printf_encode(buf, len * 4 + 1,
+					      (const u8 *) auth->e_name, e_len);
+				name = buf;
+			}
+		}
+		band[0] = '\0';
+		b_pos = band;
+		b_end = band + sizeof(band);
+		for (i = 0; opclass && opclass[i]; i++) {
+			res = os_snprintf(b_pos, b_end - b_pos, "%s%d",
+					  b_pos == band ? "" : ",", opclass[i]);
+			if (os_snprintf_error(b_end - b_pos, res)) {
+				*b_pos = '\0';
+				break;
+			}
+			b_pos += res;
+		}
+		if (auth->e_mud_url) {
+			size_t e_len = os_strlen(auth->e_mud_url);
+
+			if (!has_ctrl_char((const u8 *) auth->e_mud_url, e_len))
+				mud_url = auth->e_mud_url;
+		}
+		wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_NEEDED
+			"peer=%d net_role=%s name=\"%s\" opclass=%s mud_url=%s",
+			auth->peer_bi->id, dpp_netrole_str(auth->e_netrole),
+			name, band, mud_url);
+		os_free(buf);
+
+		conn->gas_comeback_in_progress = 1;
+		return dpp_tcp_send_comeback_delay(conn,
+						   WLAN_PA_GAS_INITIAL_RESP);
+	}
+
 	return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp);
 }
 
@@ -1508,6 +1751,7 @@
 	conn->msg_ctx = ctrl->msg_ctx;
 	conn->cb_ctx = ctrl->cb_ctx;
 	conn->process_conf_obj = ctrl->process_conf_obj;
+	conn->tcp_msg_sent = ctrl->tcp_msg_sent;
 	conn->sock = fd;
 	conn->netrole = ctrl->netrole;
 
@@ -1533,11 +1777,11 @@
 }
 
 
-int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
-		 const struct hostapd_ip_addr *addr, int port, const char *name,
-		 enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx,
-		 int (*process_conf_obj)(void *ctx,
-					 struct dpp_authentication *auth))
+int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
+		      const struct hostapd_ip_addr *addr, int port,
+		      void *msg_ctx, void *cb_ctx,
+		      int (*pkex_done)(void *ctx, void *conn,
+				       struct dpp_bootstrap_info *bi))
 {
 	struct dpp_connection *conn;
 	struct sockaddr_storage saddr;
@@ -1549,6 +1793,102 @@
 		   hostapd_ip_txt(addr, txt, sizeof(txt)), port);
 	if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
 				   addr, port) < 0) {
+		dpp_pkex_free(pkex);
+		return -1;
+	}
+
+	conn = os_zalloc(sizeof(*conn));
+	if (!conn) {
+		dpp_pkex_free(pkex);
+		return -1;
+	}
+
+	conn->msg_ctx = msg_ctx;
+	conn->cb_ctx = cb_ctx;
+	conn->pkex_done = pkex_done;
+	conn->global = dpp;
+	conn->pkex = pkex;
+	conn->sock = socket(AF_INET, SOCK_STREAM, 0);
+	if (conn->sock < 0)
+		goto fail;
+
+	if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
+		wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
+			   strerror(errno));
+		goto fail;
+	}
+
+	if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
+		if (errno != EINPROGRESS) {
+			wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
+				   strerror(errno));
+			goto fail;
+		}
+
+		/*
+		 * Continue connecting in the background; eloop will call us
+		 * once the connection is ready (or failed).
+		 */
+	}
+
+	if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
+				dpp_conn_tx_ready, conn, NULL) < 0)
+		goto fail;
+	conn->write_eloop = 1;
+
+	hdr = wpabuf_head(pkex->exchange_req);
+	end = hdr + wpabuf_len(pkex->exchange_req);
+	hdr += 2; /* skip Category and Actiom */
+	pos = hdr + DPP_HDR_LEN;
+	conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
+	if (!conn->msg_out)
+		goto fail;
+	/* Message will be sent in dpp_conn_tx_ready() */
+
+	/* TODO: eloop timeout to clear a connection if it does not complete
+	 * properly */
+	dl_list_add(&dpp->tcp_init, &conn->list);
+	return 0;
+fail:
+	dpp_connection_free(conn);
+	return -1;
+}
+
+
+static int dpp_tcp_auth_start(struct dpp_connection *conn,
+			      struct dpp_authentication *auth)
+{
+	const u8 *hdr, *pos, *end;
+
+	hdr = wpabuf_head(auth->req_msg);
+	end = hdr + wpabuf_len(auth->req_msg);
+	hdr += 2; /* skip Category and Actiom */
+	pos = hdr + DPP_HDR_LEN;
+	conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
+	if (!conn->msg_out)
+		return -1;
+	/* Message will be sent in dpp_conn_tx_ready() */
+	return 0;
+}
+
+
+int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
+		 const struct hostapd_ip_addr *addr, int port, const char *name,
+		 enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx,
+		 int (*process_conf_obj)(void *ctx,
+					 struct dpp_authentication *auth),
+		 bool (*tcp_msg_sent)(void *ctx,
+				      struct dpp_authentication *auth))
+{
+	struct dpp_connection *conn;
+	struct sockaddr_storage saddr;
+	socklen_t addrlen;
+	char txt[100];
+
+	wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
+		   hostapd_ip_txt(addr, txt, sizeof(txt)), port);
+	if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
+				   addr, port) < 0) {
 		dpp_auth_deinit(auth);
 		return -1;
 	}
@@ -1562,6 +1902,7 @@
 	conn->msg_ctx = msg_ctx;
 	conn->cb_ctx = cb_ctx;
 	conn->process_conf_obj = process_conf_obj;
+	conn->tcp_msg_sent = tcp_msg_sent;
 	conn->name = os_strdup(name ? name : "Test");
 	conn->netrole = netrole;
 	conn->global = dpp;
@@ -1594,14 +1935,8 @@
 		goto fail;
 	conn->write_eloop = 1;
 
-	hdr = wpabuf_head(auth->req_msg);
-	end = hdr + wpabuf_len(auth->req_msg);
-	hdr += 2; /* skip Category and Actiom */
-	pos = hdr + DPP_HDR_LEN;
-	conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
-	if (!conn->msg_out)
+	if (dpp_tcp_auth_start(conn, auth) < 0)
 		goto fail;
-	/* Message will be sent in dpp_conn_tx_ready() */
 
 	/* TODO: eloop timeout to clear a connection if it does not complete
 	 * properly */
@@ -1613,6 +1948,33 @@
 }
 
 
+int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
+		 struct dpp_authentication *auth, const char *name,
+		 enum dpp_netrole netrole,
+		 int (*process_conf_obj)(void *ctx,
+					 struct dpp_authentication *auth),
+		 bool (*tcp_msg_sent)(void *ctx,
+				      struct dpp_authentication *auth))
+{
+	struct dpp_connection *conn = _conn;
+
+	/* Continue with Authentication exchange on an existing TCP connection.
+	 */
+	conn->process_conf_obj = process_conf_obj;
+	conn->tcp_msg_sent = tcp_msg_sent;
+	os_free(conn->name);
+	conn->name = os_strdup(name ? name : "Test");
+	conn->netrole = netrole;
+	conn->auth = auth;
+
+	if (dpp_tcp_auth_start(conn, auth) < 0)
+		return -1;
+
+	dpp_conn_tx_ready(conn->sock, conn, NULL);
+	return 0;
+}
+
+
 int dpp_controller_start(struct dpp_global *dpp,
 			 struct dpp_controller_config *config)
 {
@@ -1638,6 +2000,7 @@
 	ctrl->msg_ctx = config->msg_ctx;
 	ctrl->cb_ctx = config->cb_ctx;
 	ctrl->process_conf_obj = config->process_conf_obj;
+	ctrl->tcp_msg_sent = config->tcp_msg_sent;
 
 	ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
 	if (ctrl->sock < 0)
@@ -1693,6 +2056,13 @@
 }
 
 
+void dpp_controller_stop_for_ctx(struct dpp_global *dpp, void *cb_ctx)
+{
+	if (dpp && dpp->controller && dpp->controller->cb_ctx == cb_ctx)
+		dpp_controller_stop(dpp);
+}
+
+
 static bool dpp_tcp_peer_id_match(struct dpp_authentication *auth,
 				  unsigned int id)
 {
@@ -1756,6 +2126,23 @@
 }
 
 
+void dpp_controller_pkex_add(struct dpp_global *dpp,
+			     struct dpp_bootstrap_info *bi,
+			     const char *code, const char *identifier)
+{
+	struct dpp_controller *ctrl = dpp->controller;
+
+	if (!ctrl)
+		return;
+
+	ctrl->pkex_bi = bi;
+	os_free(ctrl->pkex_code);
+	ctrl->pkex_code = code ? os_strdup(code) : NULL;
+	os_free(ctrl->pkex_identifier);
+	ctrl->pkex_identifier = identifier ? os_strdup(identifier) : NULL;
+}
+
+
 void dpp_tcp_init_flush(struct dpp_global *dpp)
 {
 	struct dpp_connection *conn, *tmp;
@@ -1791,4 +2178,65 @@
 	}
 }
 
+
+bool dpp_tcp_conn_status_requested(struct dpp_global *dpp)
+{
+	struct dpp_connection *conn;
+
+	dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
+		if (conn->auth && conn->auth->conn_status_requested)
+			return true;
+	}
+
+	return false;
+}
+
+
+static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn,
+					 enum dpp_status_error result,
+					 const u8 *ssid, size_t ssid_len,
+					 const char *channel_list)
+{
+	struct dpp_authentication *auth = conn->auth;
+	int res;
+	struct wpabuf *msg;
+
+	auth->conn_status_requested = 0;
+
+	msg = dpp_build_conn_status_result(auth, result, ssid, ssid_len,
+					   channel_list);
+	if (!msg) {
+		dpp_connection_remove(conn);
+		return;
+	}
+
+	res = dpp_tcp_send_msg(conn, msg);
+	wpabuf_free(msg);
+
+	if (res < 0) {
+		dpp_connection_remove(conn);
+		return;
+	}
+
+	/* This exchange will be terminated in the TX status handler */
+	conn->on_tcp_tx_complete_remove = 1;
+}
+
+
+void dpp_tcp_send_conn_status(struct dpp_global *dpp,
+			      enum dpp_status_error result,
+			      const u8 *ssid, size_t ssid_len,
+			      const char *channel_list)
+{
+	struct dpp_connection *conn;
+
+	dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
+		if (conn->auth && conn->auth->conn_status_requested) {
+			dpp_tcp_send_conn_status_msg(conn, result, ssid,
+						     ssid_len, channel_list);
+			break;
+		}
+	}
+}
+
 #endif /* CONFIG_DPP2 */
diff --git a/src/common/dragonfly.c b/src/common/dragonfly.c
index 547be66..1e84271 100644
--- a/src/common/dragonfly.c
+++ b/src/common/dragonfly.c
@@ -213,3 +213,37 @@
 		   "dragonfly: Unable to get randomness for own scalar");
 	return -1;
 }
+
+
+/* res = sqrt(val) */
+int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
+		   struct crypto_bignum *res)
+{
+	const struct crypto_bignum *prime;
+	struct crypto_bignum *tmp, *one;
+	int ret = 0;
+	u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN];
+	size_t prime_len;
+
+	/* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */
+
+	prime = crypto_ec_get_prime(ec);
+	prime_len = crypto_ec_prime_len(ec);
+	tmp = crypto_bignum_init();
+	one = crypto_bignum_init_uint(1);
+
+	if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
+				 prime_len) < 0 ||
+	    (prime_bin[prime_len - 1] & 0x03) != 3 ||
+	    !tmp || !one ||
+	    /* tmp = (p+1)/4 */
+	    crypto_bignum_add(prime, one, tmp) < 0 ||
+	    crypto_bignum_rshift(tmp, 2, tmp) < 0 ||
+	    /* res = sqrt(val) */
+	    crypto_bignum_exptmod(val, tmp, prime, res) < 0)
+		ret = -1;
+
+	crypto_bignum_deinit(tmp, 0);
+	crypto_bignum_deinit(one, 0);
+	return ret;
+}
diff --git a/src/common/dragonfly.h b/src/common/dragonfly.h
index ec3dd59..84d67f5 100644
--- a/src/common/dragonfly.h
+++ b/src/common/dragonfly.h
@@ -27,5 +27,7 @@
 			      struct crypto_bignum *_rand,
 			      struct crypto_bignum *_mask,
 			      struct crypto_bignum *scalar);
+int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
+		   struct crypto_bignum *res);
 
 #endif /* DRAGONFLY_H */
diff --git a/src/common/gas_server.c b/src/common/gas_server.c
index 5f44ffe..745a13f 100644
--- a/src/common/gas_server.c
+++ b/src/common/gas_server.c
@@ -2,6 +2,7 @@
  * Generic advertisement service (GAS) server
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2020, The Linux Foundation
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -18,7 +19,7 @@
 
 
 #define MAX_ADV_PROTO_ID_LEN 10
-#define GAS_QUERY_TIMEOUT 10
+#define GAS_QUERY_TIMEOUT 60
 
 struct gas_server_handler {
 	struct dl_list list;
@@ -26,7 +27,7 @@
 	u8 adv_proto_id_len;
 	struct wpabuf * (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
 				  const u8 *query, size_t query_len,
-				  u16 *comeback_delay);
+				  int *comeback_delay);
 	void (*status_cb)(void *ctx, struct wpabuf *resp, int ok);
 	void *ctx;
 	struct gas_server *gas;
@@ -42,6 +43,7 @@
 	u8 dialog_token;
 	struct gas_server_handler *handler;
 	u16 comeback_delay;
+	bool initial_resp_sent;
 };
 
 struct gas_server {
@@ -86,25 +88,22 @@
 
 
 static void
-gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler,
+gas_server_send_resp(struct gas_server *gas,
 		     struct gas_server_response *response,
-		     const u8 *da, int freq, u8 dialog_token,
 		     struct wpabuf *query_resp, u16 comeback_delay)
 {
-	size_t max_len = (freq > 56160) ? 928 : 1400;
+	struct gas_server_handler *handler = response->handler;
+	size_t max_len = (response->freq > 56160) ? 928 : 1400;
 	size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2;
 	size_t resp_frag_len;
 	struct wpabuf *resp;
 
 	if (comeback_delay == 0 && !query_resp) {
+		dl_list_del(&response->list);
 		gas_server_free_response(response);
 		return;
 	}
 
-	response->freq = freq;
-	response->handler = handler;
-	os_memcpy(response->dst, da, ETH_ALEN);
-	response->dialog_token = dialog_token;
 	if (comeback_delay) {
 		/* Need more time to prepare the response */
 		resp_frag_len = 0;
@@ -119,12 +118,14 @@
 		resp_frag_len = wpabuf_len(query_resp);
 	}
 
-	resp = gas_build_initial_resp(dialog_token, WLAN_STATUS_SUCCESS,
+	resp = gas_build_initial_resp(response->dialog_token,
+				      WLAN_STATUS_SUCCESS,
 				      comeback_delay,
 				      handler->adv_proto_id_len +
 				      resp_frag_len);
 	if (!resp) {
 		wpabuf_free(query_resp);
+		dl_list_del(&response->list);
 		gas_server_free_response(response);
 		return;
 	}
@@ -152,8 +153,9 @@
 	}
 	response->offset = resp_frag_len;
 	response->resp = query_resp;
-	dl_list_add(&gas->responses, &response->list);
-	gas->tx(gas->ctx, freq, da, resp, comeback_delay ? 2000 : 0);
+	response->initial_resp_sent = true;
+	gas->tx(gas->ctx, response->freq, response->dst, resp,
+		comeback_delay ? 2000 : 0);
 	wpabuf_free(resp);
 	eloop_register_timeout(GAS_QUERY_TIMEOUT, 0,
 			       gas_server_response_timeout, response, NULL);
@@ -223,25 +225,35 @@
 	wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response);
 	dl_list_for_each(handler, &gas->handlers, struct gas_server_handler,
 			 list) {
-		u16 comeback_delay = 0;
+		int comeback_delay = 0;
 
 		if (adv_proto_len < 1 + handler->adv_proto_id_len ||
 		    os_memcmp(adv_proto + 1, handler->adv_proto_id,
 			      handler->adv_proto_id_len) != 0)
 			continue;
 
+		response->freq = freq;
+		response->handler = handler;
+		os_memcpy(response->dst, sa, ETH_ALEN);
+		response->dialog_token = dialog_token;
+		dl_list_add(&gas->responses, &response->list);
+
 		wpa_printf(MSG_DEBUG,
 			   "GAS: Calling handler for the requested Advertisement Protocol ID");
 		resp = handler->req_cb(handler->ctx, response, sa, query_req,
 				       query_req_len, &comeback_delay);
 		wpa_hexdump_buf(MSG_MSGDUMP, "GAS: Response from the handler",
 				resp);
+		if (comeback_delay < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "GAS: Handler requested short delay before sending out the initial response");
+			return 0;
+		}
 		if (comeback_delay)
 			wpa_printf(MSG_DEBUG,
 				   "GAS: Handler requested comeback delay: %u TU",
 				   comeback_delay);
-		gas_server_send_resp(gas, handler, response, sa, freq,
-				     dialog_token, resp, comeback_delay);
+		gas_server_send_resp(gas, response, resp, comeback_delay);
 		return 0;
 	}
 
@@ -484,11 +496,42 @@
 	if (!response || response->resp)
 		return -1;
 
+	if (!response->initial_resp_sent) {
+		wpa_printf(MSG_DEBUG, "GAS: Send the delayed initial response");
+		gas_server_send_resp(gas, response, resp, 0);
+		return 0;
+	}
+
 	response->resp = resp;
 	return 0;
 }
 
 
+int gas_server_set_comeback_delay(struct gas_server *gas, void *resp_ctx,
+				  u16 comeback_delay)
+{
+	struct gas_server_response *tmp, *response = NULL;
+
+	dl_list_for_each(tmp, &gas->responses, struct gas_server_response,
+			 list) {
+		if (tmp == resp_ctx) {
+			response = tmp;
+			break;
+		}
+	}
+
+	if (!response || response->initial_resp_sent)
+		return -1;
+
+	wpa_printf(MSG_DEBUG,
+		   "GAS: Send the delayed initial response with comeback delay %u",
+		   comeback_delay);
+	gas_server_send_resp(gas, response, NULL, comeback_delay);
+
+	return 0;
+}
+
+
 bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx)
 {
 	struct gas_server_response *tmp;
@@ -552,7 +595,7 @@
 			struct wpabuf *
 			(*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
 				  const u8 *query, size_t query_len,
-				  u16 *comeback_delay),
+				  int *comeback_delay),
 			void (*status_cb)(void *ctx, struct wpabuf *resp,
 					  int ok),
 			void *ctx)
diff --git a/src/common/gas_server.h b/src/common/gas_server.h
index db00f87..8d5eaa2 100644
--- a/src/common/gas_server.h
+++ b/src/common/gas_server.h
@@ -2,6 +2,7 @@
  * Generic advertisement service (GAS) server
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2020, The Linux Foundation
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -25,7 +26,7 @@
 			struct wpabuf *
 			(*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
 				  const u8 *query, size_t query_len,
-				  u16 *comeback_delay),
+				  int *comeback_delay),
 			void (*status_cb)(void *ctx, struct wpabuf *resp,
 					  int ok),
 			void *ctx);
@@ -34,6 +35,8 @@
 		  int freq);
 void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
 			  size_t data_len, int ack);
+int gas_server_set_comeback_delay(struct gas_server *gas, void *resp_ctx,
+				  u16 comeback_delay);
 int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
 			struct wpabuf *resp);
 bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx);
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index b8b886f..f168d4e 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -114,7 +114,7 @@
 {
 	int ok, first;
 	int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
-			  149, 157, 165, 184, 192 };
+			  149, 157, 165, 173, 184, 192 };
 	size_t k;
 	int ht40_plus, pri_chan, sec_chan;
 
@@ -293,87 +293,12 @@
 }
 
 
-/*
- * Returns:
- * 0: no impact
- * 1: overlapping BSS
- * 2: overlapping BSS with 40 MHz intolerant advertisement
- */
-int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq)
-{
-	int affected_start, affected_end;
-	struct ieee802_11_elems elems;
-	int pri_chan, sec_chan;
-	int pri = bss->freq;
-	int sec = pri;
-
-	if (pri_freq == sec_freq)
-		return 1;
-
-	affected_start = (pri_freq + sec_freq) / 2 - 25;
-	affected_end = (pri_freq + sec_freq) / 2 + 25;
-
-	/* Check for overlapping 20 MHz BSS */
-	if (check_20mhz_bss(bss, pri_freq, affected_start, affected_end)) {
-		wpa_printf(MSG_DEBUG, "Overlapping 20 MHz BSS is found");
-		return 1;
-	}
-
-	get_pri_sec_chan(bss, &pri_chan, &sec_chan);
-
-	if (sec_chan) {
-		if (sec_chan < pri_chan)
-			sec = pri - 20;
-		else
-			sec = pri + 20;
-	}
-
-	if ((pri < affected_start || pri > affected_end) &&
-	    (sec < affected_start || sec > affected_end))
-		return 0; /* not within affected channel range */
-
-	wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
-		   " freq=%d pri=%d sec=%d",
-		   MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
-
-	if (sec_chan) {
-		if (pri_freq != pri || sec_freq != sec) {
-			wpa_printf(MSG_DEBUG,
-				   "40 MHz pri/sec mismatch with BSS "
-				   MACSTR
-				   " <%d,%d> (chan=%d%c) vs. <%d,%d>",
-				   MAC2STR(bss->bssid),
-				   pri, sec, pri_chan,
-				   sec > pri ? '+' : '-',
-				   pri_freq, sec_freq);
-			return 1;
-		}
-	}
-
-	ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
-	if (elems.ht_capabilities) {
-		struct ieee80211_ht_capabilities *ht_cap =
-			(struct ieee80211_ht_capabilities *)
-			elems.ht_capabilities;
-
-		if (le_to_host16(ht_cap->ht_capabilities_info) &
-		    HT_CAP_INFO_40MHZ_INTOLERANT) {
-			wpa_printf(MSG_DEBUG,
-				   "40 MHz Intolerant is set on channel %d in BSS "
-				   MACSTR, pri, MAC2STR(bss->bssid));
-			return 2;
-		}
-	}
-
-	return 0;
-}
-
-
 int check_40mhz_2g4(struct hostapd_hw_modes *mode,
 		    struct wpa_scan_results *scan_res, int pri_chan,
 		    int sec_chan)
 {
 	int pri_freq, sec_freq;
+	int affected_start, affected_end;
 	size_t i;
 
 	if (!mode || !scan_res || !pri_chan || !sec_chan ||
@@ -383,12 +308,70 @@
 	pri_freq = hw_get_freq(mode, pri_chan);
 	sec_freq = hw_get_freq(mode, sec_chan);
 
+	affected_start = (pri_freq + sec_freq) / 2 - 25;
+	affected_end = (pri_freq + sec_freq) / 2 + 25;
 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
-		   (pri_freq + sec_freq) / 2 - 25,
-		   (pri_freq + sec_freq) / 2 + 25);
+		   affected_start, affected_end);
 	for (i = 0; i < scan_res->num; i++) {
-		if (check_bss_coex_40mhz(scan_res->res[i], pri_freq, sec_freq))
+		struct wpa_scan_res *bss = scan_res->res[i];
+		int pri = bss->freq;
+		int sec = pri;
+		struct ieee802_11_elems elems;
+
+		/* Check for overlapping 20 MHz BSS */
+		if (check_20mhz_bss(bss, pri_freq, affected_start,
+				    affected_end)) {
+			wpa_printf(MSG_DEBUG,
+				   "Overlapping 20 MHz BSS is found");
 			return 0;
+		}
+
+		get_pri_sec_chan(bss, &pri_chan, &sec_chan);
+
+		if (sec_chan) {
+			if (sec_chan < pri_chan)
+				sec = pri - 20;
+			else
+				sec = pri + 20;
+		}
+
+		if ((pri < affected_start || pri > affected_end) &&
+		    (sec < affected_start || sec > affected_end))
+			continue; /* not within affected channel range */
+
+		wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
+			   " freq=%d pri=%d sec=%d",
+			   MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
+
+		if (sec_chan) {
+			if (pri_freq != pri || sec_freq != sec) {
+				wpa_printf(MSG_DEBUG,
+					   "40 MHz pri/sec mismatch with BSS "
+					   MACSTR
+					   " <%d,%d> (chan=%d%c) vs. <%d,%d>",
+					   MAC2STR(bss->bssid),
+					   pri, sec, pri_chan,
+					   sec > pri ? '+' : '-',
+					   pri_freq, sec_freq);
+				return 0;
+			}
+		}
+
+		ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems,
+				       0);
+		if (elems.ht_capabilities) {
+			struct ieee80211_ht_capabilities *ht_cap =
+				(struct ieee80211_ht_capabilities *)
+				elems.ht_capabilities;
+
+			if (le_to_host16(ht_cap->ht_capabilities_info) &
+			    HT_CAP_INFO_40MHZ_INTOLERANT) {
+				wpa_printf(MSG_DEBUG,
+					   "40 MHz Intolerant is set on channel %d in BSS "
+					   MACSTR, pri, MAC2STR(bss->bssid));
+				return 0;
+			}
+		}
 	}
 
 	return 1;
@@ -405,7 +388,7 @@
 			    int center_segment1, u32 vht_caps,
 			    struct he_capabilities *he_cap)
 {
-	if (!he_cap)
+	if (!he_cap || !he_cap->he_supported)
 		he_enabled = 0;
 	os_memset(data, 0, sizeof(*data));
 	data->mode = mode;
@@ -417,7 +400,16 @@
 	data->sec_channel_offset = sec_channel_offset;
 	data->center_freq1 = freq + sec_channel_offset * 10;
 	data->center_freq2 = 0;
-	data->bandwidth = sec_channel_offset ? 40 : 20;
+	if (oper_chwidth == CHANWIDTH_80MHZ)
+		data->bandwidth = 80;
+	else if (oper_chwidth == CHANWIDTH_160MHZ ||
+		 oper_chwidth == CHANWIDTH_80P80MHZ)
+		data->bandwidth = 160;
+	else if (sec_channel_offset)
+		data->bandwidth = 40;
+	else
+		data->bandwidth = 20;
+
 
 	hostapd_encode_edmg_chan(enable_edmg, edmg_channel, channel,
 				 &data->edmg);
@@ -441,9 +433,8 @@
 					   "Segment 0 center frequency isn't set");
 				return -1;
 			}
-
-			data->center_freq1 = data->freq;
-			data->bandwidth = 20;
+			if (!sec_channel_offset)
+				data->center_freq1 = data->freq;
 		} else {
 			int freq1, freq2 = 0;
 			int bw = center_idx_to_bw_6ghz(center_segment0);
@@ -491,7 +482,10 @@
 
 	if (data->he_enabled) switch (oper_chwidth) {
 	case CHANWIDTH_USE_HT:
-		if (mode == HOSTAPD_MODE_IEEE80211G && sec_channel_offset) {
+		if (sec_channel_offset == 0)
+			break;
+
+		if (mode == HOSTAPD_MODE_IEEE80211G) {
 			if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
 			      HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) {
 				wpa_printf(MSG_ERROR,
@@ -572,13 +566,19 @@
 		/* fall through */
 	case CHANWIDTH_80MHZ:
 		data->bandwidth = 80;
-		if ((oper_chwidth == CHANWIDTH_80MHZ &&
-		     center_segment1) ||
-		    (oper_chwidth == CHANWIDTH_80P80MHZ &&
-		     !center_segment1) ||
-		    !sec_channel_offset) {
+		if (!sec_channel_offset) {
 			wpa_printf(MSG_ERROR,
-				   "80/80+80 MHz: center segment 1 wrong or no second channel offset");
+				   "80/80+80 MHz: no second channel offset");
+			return -1;
+		}
+		if (oper_chwidth == CHANWIDTH_80MHZ && center_segment1) {
+			wpa_printf(MSG_ERROR,
+				   "80 MHz: center segment 1 configured");
+			return -1;
+		}
+		if (oper_chwidth == CHANWIDTH_80P80MHZ && !center_segment1) {
+			wpa_printf(MSG_ERROR,
+				   "80+80 MHz: center segment 1 not configured");
 			return -1;
 		}
 		if (!center_segment0) {
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index ddde36b..0e92aa0 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -32,7 +32,6 @@
 int check_40mhz_5g(struct wpa_scan_results *scan_res,
 		   struct hostapd_channel_data *pri_chan,
 		   struct hostapd_channel_data *sec_chan);
-int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq);
 int check_40mhz_2g4(struct hostapd_hw_modes *mode,
 		    struct wpa_scan_results *scan_res, int pri_chan,
 		    int sec_chan);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index fa39761..adc6f59 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1017,8 +1017,8 @@
 		return HOSTAPD_MODE_IEEE80211A;
 	}
 
-	/* 5 GHz, channels 100..140 */
-	if (freq >= 5000 && freq <= 5700) {
+	/* 5 GHz, channels 100..144 */
+	if (freq >= 5500 && freq <= 5720) {
 		if ((freq - 5000) % 5)
 			return NUM_HOSTAPD_MODES;
 
@@ -1537,6 +1537,16 @@
 }
 
 
+/*
+ * 802.11-2020: Table E-4 - Global operating classes
+ * DFS_50_100_Behavior: 118, 119, 120, 121, 122, 123
+ */
+int is_dfs_global_op_class(u8 op_class)
+{
+    return (op_class >= 118) && (op_class <= 123);
+}
+
+
 static int is_11b(u8 rate)
 {
 	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16
@@ -1901,10 +1911,10 @@
 	 */
 	{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
-	{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, NO_P2P_SUPP },
-	{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP },
-	{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP },
-	{ HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP },
+	{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
+	{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
+	{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
+	{ HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
 	{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
 
@@ -2239,6 +2249,9 @@
 
 int center_idx_to_bw_6ghz(u8 idx)
 {
+	/* Channel: 2 */
+	if (idx == 2)
+		return 0; /* 20 MHz */
 	/* channels: 1, 5, 9, 13... */
 	if ((idx & 0x3) == 0x1)
 		return 0; /* 20 MHz */
@@ -2297,6 +2310,30 @@
 }
 
 
+/**
+ * get_6ghz_sec_channel - Get the relative position of the secondary channel
+ * to the primary channel in 6 GHz
+ * @channel: Primary channel to be checked for (in global op class 131)
+ * Returns: 1 = secondary channel above, -1 = secondary channel below
+ */
+
+int get_6ghz_sec_channel(int channel)
+{
+	/*
+	 * In the 6 GHz band, primary channels are numbered as 1, 5, 9, 13.., so
+	 * the 40 MHz channels are formed with the channel pairs as (1,5),
+	 * (9,13), (17,21)..
+	 * The secondary channel for a given primary channel is below the
+	 * primary channel for the channels 5, 13, 21.. and it is above the
+	 * primary channel for the channels 1, 9, 17..
+	 */
+
+	if (((channel - 1) / 4) % 2)
+		return -1;
+	return 1;
+}
+
+
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len)
 {
@@ -2407,6 +2444,35 @@
 }
 
 
+bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
+			       unsigned int capab)
+{
+	const u8 *end;
+	size_t flen, i;
+	u32 capabs = 0;
+
+	if (!rsnxe || rsnxe_len == 0)
+		return false;
+	end = rsnxe + rsnxe_len;
+	flen = (rsnxe[0] & 0x0f) + 1;
+	if (rsnxe + flen > end)
+		return false;
+	if (flen > 4)
+		flen = 4;
+	for (i = 0; i < flen; i++)
+		capabs |= rsnxe[i] << (8 * i);
+
+	return capabs & BIT(capab);
+}
+
+
+bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
+{
+	return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
+					 rsnxe ? rsnxe[1] : 0, capab);
+}
+
+
 void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
 			      int primary_channel,
 			      struct ieee80211_edmg_config *edmg)
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index e4992b3..ec6556f 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -218,6 +218,7 @@
 				  int sec_channel, u8 *op_class, u8 *channel);
 int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
 		     u16 num_modes);
+int is_dfs_global_op_class(u8 op_class);
 enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
 
 int supp_rates_11b_only(struct ieee802_11_elems *elems);
@@ -264,11 +265,15 @@
 bool is_6ghz_freq(int freq);
 bool is_6ghz_op_class(u8 op_class);
 bool is_6ghz_psc_frequency(int freq);
+int get_6ghz_sec_channel(int channel);
 
 int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
 				    size_t nei_rep_len);
 
 int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
+bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
+			       unsigned int capab);
+bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
 int op_class_to_bandwidth(u8 op_class);
 int op_class_to_ch_width(u8 op_class);
 
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index c385923..4300ae5 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -22,7 +22,7 @@
 #define WLAN_FC_PWRMGT		0x1000
 #define WLAN_FC_MOREDATA	0x2000
 #define WLAN_FC_ISWEP		0x4000
-#define WLAN_FC_ORDER		0x8000
+#define WLAN_FC_HTC		0x8000
 
 #define WLAN_FC_GET_TYPE(fc)	(((fc) & 0x000c) >> 2)
 #define WLAN_FC_GET_STYPE(fc)	(((fc) & 0x00f0) >> 4)
@@ -446,6 +446,7 @@
 #define WLAN_EID_WHITE_SPACE_MAP 205
 #define WLAN_EID_FTM_PARAMETERS 206
 #define WLAN_EID_S1G_BCN_COMPAT 213
+#define WLAN_EID_TWT 216
 #define WLAN_EID_S1G_CAPABILITIES 217
 #define WLAN_EID_VENDOR_SPECIFIC 221
 #define WLAN_EID_S1G_OPERATION 232
@@ -603,6 +604,10 @@
 #define WLAN_ACTION_ROBUST_AV_STREAMING 19
 #define WLAN_ACTION_UNPROTECTED_DMG 20
 #define WLAN_ACTION_VHT 21
+#define WLAN_ACTION_S1G 22
+#define WLAN_ACTION_S1G_RELAY 23
+#define WLAN_ACTION_FLOW_CONTROL 24
+#define WLAN_ACTION_CTRL_RESP_MCS_NEG 25
 #define WLAN_ACTION_FILS 26
 #define WLAN_ACTION_PROTECTED_FTM 34
 #define WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED 126
@@ -820,6 +825,19 @@
 	NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10
 };
 
+/* Unprotected S1G Action field values for WLAN_ACTION_S1G */
+#define S1G_ACT_AID_SWITCH_REQUEST   0
+#define S1G_ACT_AID_SWITCH_RESPONSE  1
+#define S1G_ACT_SYNC_CONTROL         2
+#define S1G_ACT_STA_INFO_ANNOUNCE    3
+#define S1G_ACT_EDCA_PARAM_SET       4
+#define S1G_ACT_EL_OPERATION         5
+#define S1G_ACT_TWT_SETUP            6
+#define S1G_ACT_TWT_TEARDOWN         7
+#define S1G_ACT_SECT_GROUP_ID_LIST   8
+#define S1G_ACT_SECT_ID_FEEDBACK     9
+#define S1G_ACT_TWT_INFORMATION      11
+
 /*
  * IEEE P802.11-REVmc/D5.0 Table 9-81 - Measurement type definitions for
  * measurement requests
@@ -1325,6 +1343,7 @@
 #define CHANWIDTH_4320MHZ	5
 #define CHANWIDTH_6480MHZ	6
 #define CHANWIDTH_8640MHZ	7
+#define CHANWIDTH_40MHZ_6GHZ	8
 
 #define HE_NSS_MAX_STREAMS			    8
 
@@ -1348,6 +1367,10 @@
 #define DPP_CC_OUI_TYPE 0x1e
 #define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f
 #define SAE_PK_OUI_TYPE 0x1f
+#define QM_IE_VENDOR_TYPE 0x506f9a22
+#define QM_IE_OUI_TYPE 0x22
+#define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
+#define WFA_CAPA_OUI_TYPE 0x23
 
 #define MULTI_AP_SUB_ELEM_TYPE 0x06
 #define MULTI_AP_TEAR_DOWN BIT(4)
@@ -1645,6 +1668,7 @@
 #define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
 #define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
 #define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
+#define P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE BIT(6)
 
 /* P2P Capability - Group Capability bitmap */
 #define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
@@ -2174,6 +2198,7 @@
 	* and optional variable length PPE Thresholds field. */
 	u8 optional[33];
 } STRUCT_PACKED;
+#define IEEE80211_HE_CAPAB_MIN_LEN (6 + 11)
 
 struct ieee80211_he_operation {
 	le32 he_oper_params; /* HE Operation Parameters[3] and
@@ -2349,6 +2374,26 @@
 /* B7: Reserved if sent by an AP; More Data Ack if sent by a non-AP STA */
 #define HE_QOS_INFO_MORE_DATA_ACK ((u8) (BIT(7)))
 
+/*
+ * IEEE Std 802.11-2020 and IEEE Std 802.11ax-2021
+ * 9.4.2.170 Reduced Neighbor Report element
+ */
+#define RNR_HEADER_LEN                              2
+#define RNR_TBTT_HEADER_LEN                         4
+#define RNR_TBTT_INFO_COUNT(x)                      (((x) & 0xf) << 4)
+#define RNR_TBTT_INFO_COUNT_MAX                     16
+#define RNR_TBTT_INFO_LEN                           13
+#define RNR_NEIGHBOR_AP_OFFSET_UNKNOWN              255
+/* Figure 9-632a - BSS Parameters subfield format */
+#define RNR_BSS_PARAM_OCT_RECOMMENDED               BIT(0)
+#define RNR_BSS_PARAM_SAME_SSID                     BIT(1)
+#define RNR_BSS_PARAM_MULTIPLE_BSSID                BIT(2)
+#define RNR_BSS_PARAM_TRANSMITTED_BSSID             BIT(3)
+#define RNR_BSS_PARAM_MEMBER_CO_LOCATED_ESS         BIT(4)
+#define RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE     BIT(5)
+#define RNR_BSS_PARAM_CO_LOCATED                    BIT(6)
+#define RNR_20_MHZ_PSD_MAX_TXPOWER                  255 /* dBm */
+
 /* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */
 #define EDMG_BSS_OPERATING_CHANNELS_OFFSET	6
 #define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET	7
@@ -2453,4 +2498,40 @@
  */
 #define FD_MAX_INTERVAL_6GHZ                  20 /* TUs */
 
+/* Protected Vendor-specific QoS Management Action frame identifiers - WFA */
+#define QM_ACTION_VENDOR_TYPE 0x506f9a1a
+#define QM_ACTION_OUI_TYPE 0x1a
+
+/* QoS Management Action frame OUI subtypes */
+#define QM_DSCP_POLICY_QUERY 0
+#define QM_DSCP_POLICY_REQ 1
+#define QM_DSCP_POLICY_RESP 2
+
+/* QoS Management attributes */
+enum qm_attr_id {
+	QM_ATTR_PORT_RANGE = 1,
+	QM_ATTR_DSCP_POLICY = 2,
+	QM_ATTR_TCLAS = 3,
+	QM_ATTR_DOMAIN_NAME = 4,
+};
+
+/* DSCP Policy attribute - Request Type */
+enum dscp_policy_request_type {
+	DSCP_POLICY_REQ_ADD = 0, /* ADD/UPDATE */
+	DSCP_POLICY_REQ_REMOVE = 1,
+};
+
+/* Request/Response Control field of DSCP Policy Request/Response frame */
+#define DSCP_POLICY_CTRL_MORE	BIT(0)
+#define DSCP_POLICY_CTRL_RESET	BIT(1)
+
+/* Wi-Fi Alliance Capabilities element - Capabilities field */
+#define WFA_CAPA_QM_DSCP_POLICY BIT(0)
+#define WFA_CAPA_QM_UNSOLIC_DSCP BIT(1)
+
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+#define WPA_KEY_MGMT_CROSS_AKM_ROAM (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK)
+#define IS_CROSS_AKM_ROAM_KEY_MGMT(key_mgmt) \
+	((key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) == WPA_KEY_MGMT_CROSS_AKM_ROAM)
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 #endif /* IEEE802_11_DEFS_H */
diff --git a/src/common/ptksa_cache.c b/src/common/ptksa_cache.c
index 6a053d6..8fcb135 100644
--- a/src/common/ptksa_cache.c
+++ b/src/common/ptksa_cache.c
@@ -269,7 +269,7 @@
 					   u32 life_time,
 					   const struct wpa_ptk *ptk)
 {
-	struct ptksa_cache_entry *entry, *tmp;
+	struct ptksa_cache_entry *entry, *tmp, *tmp2 = NULL;
 	struct os_reltime now;
 
 	if (!ptksa || !ptk || !addr || !life_time || cipher == WPA_CIPHER_NONE)
@@ -296,21 +296,21 @@
 	entry->expiration = now.sec + life_time;
 
 	dl_list_for_each(tmp, &ptksa->ptksa, struct ptksa_cache_entry, list) {
-		if (tmp->expiration > entry->expiration)
+		if (tmp->expiration > entry->expiration) {
+			tmp2 = tmp;
 			break;
+		}
 	}
 
 	/*
-	 * If the list was empty add to the head; otherwise if the expiration is
-	 * later then all other entries, add it to the end of the list;
+	 * If the expiration is later then all other or the list is empty
+	 * entries, add it to the end of the list;
 	 * otherwise add it before the relevant entry.
 	 */
-	if (!tmp)
-		dl_list_add(&ptksa->ptksa, &entry->list);
-	else if (tmp->expiration < entry->expiration)
-		dl_list_add(&tmp->list, &entry->list);
+	if (tmp2)
+		dl_list_add(&tmp2->list, &entry->list);
 	else
-		dl_list_add_tail(&tmp->list, &entry->list);
+		dl_list_add_tail(&ptksa->ptksa, &entry->list);
 
 	ptksa->n_ptksa++;
 	wpa_printf(MSG_DEBUG,
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index f7e5571..0f7d3af 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -512,7 +512,9 @@
  * @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to
  *	configure parameters per peer to capture Channel Frequency Response
  *	(CFR) and enable Periodic CFR capture. The attributes for this command
- *	are defined in enum qca_wlan_vendor_peer_cfr_capture_attr.
+ *	are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. This command
+ *	can also be used to send CFR data from the driver to userspace when
+ *	netlink events are used to send CFR data.
  *
  * @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes
  *	in throughput dynamically. The driver estimates the throughput based on
@@ -620,7 +622,14 @@
  *	This new command is alternative to existing command
  *	QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
  *	is using stream of bytes instead of structured data using vendor
- *	attributes.
+ *	attributes. User space sends unsafe frequency ranges to the driver using
+ *	a nested attribute %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE. On
+ *	reception of this command, the driver shall check if an interface is
+ *	operating on an unsafe frequency and the driver shall try to move to a
+ *	safe channel when needed. If the driver is not able to find a safe
+ *	channel the interface can keep operating on an unsafe channel with the
+ *	TX power limit derived based on internal configurations	like
+ *	regulatory/SAR rules.
  *
  * @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
  *	add the STA node details in driver/firmware. Attributes for this event
@@ -699,7 +708,86 @@
  *	The host driver selects Tx VDEV, and notifies user. The attributes
  *	used with this event are defined in enum
  *	qca_wlan_vendor_attr_mbssid_tx_vdev_status.
+ *	This event contains Tx VDEV group information, other VDEVs
+ *	interface index, and status information.
  *
+ * @QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY: Vendor command to
+ *	configure the concurrent session policies when multiple STA interfaces
+ *	are (getting) active. The attributes used by this command are defined
+ *	in enum qca_wlan_vendor_attr_concurrent_sta_policy.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS: Userspace can use this command
+ *	to query usable channels for different interface types such as STA,
+ *	AP, P2P GO, P2P Client, NAN, etc. The driver shall report all usable
+ *	channels in the response based on country code, different static
+ *	configurations, concurrency combinations, etc. The attributes used
+ *	with this command are defined in
+ *	enum qca_wlan_vendor_attr_usable_channels.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY: This vendor subcommand is used
+ *	to get DFS radar history from the driver to userspace. The driver
+ *	returns QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES attribute with an
+ *	array of nested entries.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD: Userspace can use this command to
+ *	enable/disable mDNS offload to the firmware. The attributes used with
+ *	this command are defined in enum qca_wlan_vendor_attr_mdns_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used
+ *	to set packet monitor mode that aims to send the specified set of TX and
+ *	RX frames on the current client interface to an active monitor
+ *	interface. If this monitor mode is set, the driver will send the
+ *	configured frames, from the interface on which the command is issued, to
+ *	an active monitor interface. The attributes used with this command are
+ *	defined in enum qca_wlan_vendor_attr_set_monitor_mode.
+ *
+ *	Though the monitor mode is configured for the respective
+ *	Data/Management/Control frames, it is up to the respective WLAN
+ *	driver/firmware/hardware designs to consider the possibility of sending
+ *	these frames over the monitor interface. For example, the Control frames
+ *	are handled within the hardware and thus passing such frames over the
+ *	monitor interface is left to the respective designs.
+ *
+ *	Also, this monitor mode is governed to behave accordingly in
+ *	suspend/resume states. If the firmware handles any of such frames in
+ *	suspend state without waking up the host and if the monitor mode is
+ *	configured to notify all such frames, the firmware is expected to resume
+ *	the host and forward the respective frames to the monitor interface.
+ *	Please note that such a request to get the frames over the monitor
+ *	interface will have a definite power implication.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both
+ *	as a request to set the driver/firmware with the parameters to trigger
+ *	the roaming events, and also used by the driver/firmware to pass on the
+ *	various roam events to userspace.
+ *	Applicable only for the STA mode. The attributes used with this command
+ *	are defined in enum qca_wlan_vendor_attr_roam_events.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG: Subcommand to set or reset the
+ *	rate mask config for a list of PHY types. Userspace shall provide an
+ *	array of the vendor attributes defined in
+ *	enum qca_wlan_vendor_attr_ratemask_params.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA: Multi-channel Concurrency (MCC) occurs
+ *	when two interfaces are active on the same band, using two different
+ *	home channels, and only supported by a single radio. In this scenario
+ *	the device must split the use of the radio between the two interfaces.
+ *	The percentage of time allocated to a given interface is the quota.
+ *	Depending on the configuration, the quota can either be fixed or
+ *	dynamic.
+ *
+ *	When used as an event, the device will report the quota type, and for
+ *	all interfaces operating in MCC it will report the current quota.
+ *	When used as a command, the device can be configured for a specific
+ *	quota type, and in the case of a fixed quota, the quota to apply to one
+ *	of the interfaces.
+ *
+ *	Applications can use the event to do TX bitrate control based on the
+ *	information, and can use the command to explicitly set the quota to
+ *	enhance performance in specific scenarios.
+ *
+ *	The attributes used with this command are defined in
+ *	enum qca_wlan_vendor_attr_mcc_quota.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -886,6 +974,15 @@
 	QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194,
 	QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195,
 	QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196,
+	QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197,
+	QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198,
+	QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY = 199,
+	QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD = 200,
+	/* 201 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202,
+	QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203,
+	QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG = 204,
+	QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA = 205,
 };
 
 enum qca_wlan_vendor_attr {
@@ -1124,7 +1221,7 @@
  * @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel
  * or environment being very noisy or congested.
  *
- * @QCA_ROAM_REASON_EXPLICIT_REQUEST: Roam triggered due to an explicit request
+ * @QCA_ROAM_REASON_USER_TRIGGER: Roam triggered due to an explicit request
  * from the user (user space).
  *
  * @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from
@@ -1132,6 +1229,26 @@
  *
  * @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization
  * breaching out the configured threshold.
+ *
+ * @QCA_ROAM_REASON_WTC: Roam triggered due to Wireless to Cellular BSS
+ * transition request.
+ *
+ * @QCA_ROAM_REASON_IDLE: Roam triggered when device is suspended, there is no
+ * data activity with the AP and the current RSSI falls below a certain
+ * threshold.
+ *
+ * @QCA_ROAM_REASON_DISCONNECTION: Roam triggered due to Deauthentication or
+ * Disassociation frames received from the connected AP.
+ *
+ * @QCA_ROAM_REASON_PERIODIC_TIMER: Roam triggered as part of the periodic scan
+ * that happens when there is no candidate AP found during the poor RSSI scan
+ * trigger.
+ *
+ * @QCA_ROAM_REASON_BACKGROUND_SCAN: Roam triggered based on the scan results
+ * obtained from an external scan (not aimed at roaming).
+ *
+ * @QCA_ROAM_REASON_BT_ACTIVITY: Roam triggered due to Bluetooth connection is
+ * established when the station is connected in the 2.4 GHz band.
  */
 enum qca_roam_reason {
 	QCA_ROAM_REASON_UNKNOWN,
@@ -1143,6 +1260,12 @@
 	QCA_ROAM_REASON_USER_TRIGGER,
 	QCA_ROAM_REASON_BTM,
 	QCA_ROAM_REASON_BSS_LOAD,
+	QCA_ROAM_REASON_WTC,
+	QCA_ROAM_REASON_IDLE,
+	QCA_ROAM_REASON_DISCONNECTION,
+	QCA_ROAM_REASON_PERIODIC_TIMER,
+	QCA_ROAM_REASON_BACKGROUND_SCAN,
+	QCA_ROAM_REASON_BT_ACTIVITY,
 };
 
 enum qca_wlan_vendor_attr_roam_auth {
@@ -1362,6 +1485,16 @@
  * Used with event to notify the EDMG channel number selected in ACS
  * operation.
  * EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP: Optional (u16).
+ * Used with event to notify the puncture pattern selected in ACS operation.
+ * Encoding for this attribute will follow the convention used in the Disabled
+ * Subchannel Bitmap field of the EHT Operation IE.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED: Flag attribute.
+ * Used with command to configure ACS operation for EHT mode.
+ * Disable (flag attribute not present) - EHT disabled and
+ * Enable (flag attribute present) - EHT enabled.
  */
 enum qca_wlan_vendor_attr_acs_offload {
 	QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
@@ -1382,6 +1515,8 @@
 	QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15,
 	QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16,
 	QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17,
+	QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
+	QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
@@ -1687,32 +1822,62 @@
 };
 
 /**
- * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
- * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
- * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
- * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized
- *	SOC timer value at TSF capture
+ * enum qca_vendor_attr_tsf_cmd: Vendor attributes for TSF capture
+ * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: Required (u32)
+ * Specify the TSF command. Possible values are defined in
+ * &enum qca_tsf_cmd.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64)
+ * This attribute contains TSF timer value. This attribute is only available
+ * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64)
+ * This attribute contains SOC timer value at TSF capture. This attribute is
+ * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL: Optional (u32)
+ * This attribute is used to provide TSF sync interval and only applicable when
+ * TSF command is %QCA_TSF_SYNC_START. If this attribute is not provided, the
+ * driver will use the default value. Time unit is in milliseconds.
  */
 enum qca_vendor_attr_tsf_cmd {
 	QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0,
 	QCA_WLAN_VENDOR_ATTR_TSF_CMD,
 	QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
 	QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
+	QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL,
 	QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_TSF_MAX =
 	QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1
 };
 
 /**
- * enum qca_tsf_operation: TSF driver commands
+ * enum qca_tsf_cmd: TSF driver commands
  * @QCA_TSF_CAPTURE: Initiate TSF Capture
  * @QCA_TSF_GET: Get TSF capture value
  * @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target
+ * will automatically send TSF report to the host. To query
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
+ * initiated first.
+ * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target
+ * will not automatically send TSF report to the host. If
+ * %QCA_TSF_AUTO_REPORT_ENABLE is initiated and
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
+ * operation needs to be initiated.
+ * @QCA_TSF_SYNC_START: Start periodic TSF sync feature. The driver periodically
+ * fetches TSF and host time mapping from the firmware with interval configured
+ * through the %QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL attribute. If the
+ * interval value is not provided the driver will use the default value. The
+ * userspace can query the TSF and host time mapping via the %QCA_TSF_GET
+ * command.
+ * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature.
  */
 enum qca_tsf_cmd {
 	QCA_TSF_CAPTURE,
 	QCA_TSF_GET,
 	QCA_TSF_SYNC_GET,
+	QCA_TSF_AUTO_REPORT_ENABLE,
+	QCA_TSF_AUTO_REPORT_DISABLE,
+	QCA_TSF_SYNC_START,
+	QCA_TSF_SYNC_STOP,
 };
 
 /**
@@ -1806,6 +1971,23 @@
 };
 
 /**
+ * enum qca_wlan_vendor_scan_priority - Specifies the valid values that the
+ * vendor scan attribute QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY can take.
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW: Very low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW: Low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM: Medium priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH: High priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH: Very high priority
+ */
+enum qca_wlan_vendor_scan_priority {
+	QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW = 0,
+	QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW = 1,
+	QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM = 2,
+	QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH = 3,
+	QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH = 4,
+};
+
+/**
  * enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes
  *
  * @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan
@@ -1830,6 +2012,11 @@
  * @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in
  *	microseconds. This is a common value which applies across all
  *	frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES.
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY: Priority of vendor scan relative to
+ *	other scan requests. It is a u32 attribute and takes values from enum
+ *	qca_wlan_vendor_scan_priority. This is an optional attribute.
+ *	If this attribute is not configured, the driver shall use
+ *	QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan.
  */
 enum qca_wlan_vendor_attr_scan {
 	QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
@@ -1845,6 +2032,7 @@
 	QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10,
 	QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11,
 	QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12,
+	QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
 	QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
 	QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -2399,6 +2587,46 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78,
 
+	/*
+	 * 8-bit unsigned value. This attribute, when set, indicates whether the
+	 * specified interface is the primary STA interface when there are more
+	 * than one STA interfaces concurrently active.
+	 *
+	 * This configuration helps the firmware/hardware to support certain
+	 * features (e.g., roaming) on this primary interface, if the same
+	 * cannot be supported on the concurrent STA interfaces simultaneously.
+	 *
+	 * This configuration is only applicable for a single STA interface on
+	 * a device and gives the priority for it only over other concurrent STA
+	 * interfaces.
+	 *
+	 * If the device is a multi wiphy/soc, this configuration applies to a
+	 * single STA interface across the wiphys.
+	 *
+	 * 1-Enable (is the primary STA), 0-Disable (is not the primary STA)
+	 */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY = 79,
+
+	/*
+	 * 8-bit unsigned value. This attribute can be used to configure the
+	 * driver to enable/disable FT-over-DS feature. Possible values for
+	 * this attribute are 1-Enable and 0-Disable.
+	 */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS = 80,
+
+	/*
+	 * 8-bit unsigned value. This attribute can be used to configure the
+	 * firmware to enable/disable ARP/NS offload feature. Possible values
+	 * for this attribute are 0-Disable and 1-Enable.
+	 *
+	 * This attribute is only applicable for STA/P2P-Client interface,
+	 * and is optional, default behavior is ARP/NS offload enabled.
+	 *
+	 * This attribute can be set in disconnected and connected state, and
+	 * will restore to the default behavior if the interface is closed.
+	 */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD = 81,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -3818,6 +4046,14 @@
 	 * QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO.
 	 */
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85,
+	/* u8 value representing the channel load percentage. Possible values
+	 * are 0-100.
+	 */
+	QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86,
+	/* u8 value representing the time slicing duty cycle percentage.
+	 * Possible values are 0-100.
+	 */
+	QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87,
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
@@ -4545,7 +4781,13 @@
  * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm,
  *	signifying the RSSI threshold of the candidate AP, indicating
  *	the driver to trigger roam only to the candidate AP with RSSI
- *	better than this threshold.
+ *	better than this threshold. If RSSI thresholds for candidate APs found
+ *	in the 2.4 GHz, 5 GHz, and 6 GHz bands are configured separately using
+ *	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ,
+ *	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ, and/or
+ *	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ, those values will
+ *	take precedence over the value configured using the
+ *	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute.
  *
  * @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the
  *	user defined reason code to be sent to the AP in response to AP's
@@ -4564,6 +4806,69 @@
  *	If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and
  *	QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the
  *	driver shall proceed with the default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ: Signed 32-bit value
+ *	in dBm, signifying the RSSI threshold of the candidate AP found in the
+ *	2.4 GHz band. The driver/firmware shall trigger roaming to the candidate
+ *	AP found in the 2.4 GHz band only if its RSSI value is better than this
+ *	threshold. Optional attribute. If this attribute is not included, the
+ *	threshold value specified by the
+ *	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ: Signed 32-bit value in
+ *	dBm, signifying the RSSI threshold of the candidate AP found in the 5
+ *	GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ *	found in the 5 GHz band only if its RSSI value is better than this
+ *	threshold. Optional attribute. If this attribute is not included, the
+ *	threshold value specified by tge
+ *	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ: Signed 32-bit value in
+ *	dBm, signifying the RSSI threshold of the candidate AP found in the 6
+ *	GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ *	found in the 6 GHz band only if its RSSI value is better than this
+ *	threshold. Optional attribute. If this attribute is not included, the
+ *	threshold value specified by the
+ *	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_BAND_MASK: Unsigned 32-bit value.
+ *	Carries bitmask value of bits from &enum qca_set_band and represents
+ *	all the bands in which roaming is allowed. The configuration is valid
+ *	until next disconnection. If this attribute is not present, the
+ *	existing configuration shall be used. By default, roaming is allowed on
+ *	all bands supported by the local device. When the value is set to
+ *	%QCA_SETBAND_AUTO, all supported bands shall be enabled.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ *	Optional parameter. Scan dwell time for active channels in the 2.4/5 GHz
+ *	bands. If this attribute is not configured, the driver shall proceed
+ *	with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ *	Optional parameter. Scan dwell time for passive channels in the 5 GHz
+ *	band. If this attribute is not configured, the driver shall proceed with
+ *	default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME: u16 value in milliseconds.
+ *	Optional parameter. The minimum duration to stay on the connected AP
+ *	channel during the channel scanning. If this attribute is not
+ *	configured, the driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME: u16 value in milliseconds.
+ *	Optional parameter. The maximum duration for which the radio can scan
+ *	foreign channels consecutively without coming back to home channel. If
+ *	this attribute is not configured, the driver shall proceed with default
+ *	behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME: u16 value in milliseconds.
+ *	Optional parameter. Scan dwell time for 6G Preferred Scanning Channels.
+ *	If this attribute is not configured, the driver shall proceed with
+ *	default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME: u16 value in milliseconds.
+ *	Optional parameter. Scan dwell time for 6G Non Preferred Scanning
+ *	Channels. If this attribute is not configured, the driver shall proceed
+ *	with default behavior.
  */
 enum qca_vendor_attr_roam_control {
 	QCA_ATTR_ROAM_CONTROL_ENABLE = 1,
@@ -4579,6 +4884,16 @@
 	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11,
 	QCA_ATTR_ROAM_CONTROL_USER_REASON = 12,
 	QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13,
+	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ = 14,
+	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ = 15,
+	QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ = 16,
+	QCA_ATTR_ROAM_CONTROL_BAND_MASK = 17,
+	QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME = 18,
+	QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME = 19,
+	QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME = 20,
+	QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME = 21,
+	QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME = 22,
+	QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME = 23,
 
 	/* keep last */
 	QCA_ATTR_ROAM_CONTROL_AFTER_LAST,
@@ -4601,14 +4916,14 @@
  *	ignored BSSIDs and accordingly clear the respective ones with the
  *	matching ID.
  *
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned
- *	32-bit value.Represents the number of whitelist SSIDs configured.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS: Unsigned
+ *	32-bit value. Represents the number of allowlist SSIDs configured.
  *
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST: Nested attribute
- *	to carry the list of Whitelist SSIDs.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST: Nested attribute
+ *	to carry the list of allowlist SSIDs.
  *
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID: SSID (binary attribute,
- *	0..32 octets). Represents the white list SSID. Whitelist SSIDs
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID: SSID (binary attribute,
+ *	0..32 octets). Represents the allow list SSID. Allowlist SSIDs
  *	represent the list of SSIDs to which the firmware/driver can consider
  *	to roam to.
  *
@@ -4646,7 +4961,7 @@
  *
  * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE: Unsigned 32-bit
  *	value. 1-Enable, 0-Disable. Represents "Lazy" mode, where
- *	firmware is hunting for a better BSSID or white listed SSID even though
+ *	firmware is hunting for a better BSSID or allow listed SSID even though
  *	the RSSI of the link is good. The parameters enabling the roaming are
  *	configured through the PARAM_A_BAND_XX attrbutes.
  *
@@ -4688,10 +5003,10 @@
 	QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1,
 	QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2,
 
-	/* Attributes for wifi_set_ssid_white_list */
-	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3,
-	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4,
-	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5,
+	/* Attributes for wifi_set_ssid_allow_list */
+	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS = 3,
+	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST = 4,
+	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID = 5,
 
 	/* Attributes for set_roam_params */
 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6,
@@ -4726,16 +5041,24 @@
 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1,
 };
 
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS \
+	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST \
+	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID \
+	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
+
 /*
  * enum qca_wlan_vendor_roaming_subcmd: Referred by
  * QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD.
  *
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST: Sub command to
- *	configure the white list SSIDs. These are configured through
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST: Sub command to
+ *	configure the allow list SSIDs. These are configured through
  *	the following attributes.
- *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
- *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST,
- *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
+ *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS,
+ *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST,
+ *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
  *
  * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS: Sub command to
  *	configure the Roam params. These parameters are evaluated on the GScan
@@ -4751,7 +5074,7 @@
  *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID
  *	preference.
  *
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID: Sets the list of BSSIDs
  *	to ignore in roaming decision. Uses
  *	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list.
  *
@@ -4775,17 +5098,23 @@
  */
 enum qca_wlan_vendor_roaming_subcmd {
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_INVALID = 0,
-	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST = 1,
+	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST = 1,
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2,
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM = 3,
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS = 4,
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PARAMS = 5,
-	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID = 6,
+	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID = 6,
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET = 7,
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET = 8,
 	QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR = 9,
 };
 
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST \
+	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID \
+	QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID
+
 enum qca_wlan_vendor_attr_gscan_config_params {
 	QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0,
 
@@ -5144,7 +5473,7 @@
 	QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
 	= 43,
 	/* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
-	QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
+	QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
 	= 44,
 
 	QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45,
@@ -5152,10 +5481,10 @@
 	/* Unsigned 32-bit value; a GSCAN Capabilities attribute.
 	 * This is used to limit the maximum number of BSSIDs while sending
 	 * the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with subcmd
-	 * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID and attribute
+	 * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID and attribute
 	 * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID.
 	 */
-	QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46,
+	QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID = 46,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST,
@@ -5163,6 +5492,12 @@
 	QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1,
 };
 
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID \
+	QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID \
+	QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID
+
 enum qca_wlan_vendor_attr_pno_config_params {
 	QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0,
 	/* Attributes for data used by
@@ -6186,6 +6521,14 @@
 	 * u32 attribute.
 	 */
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29,
+	/* This attribute specifies the bandwidth to be used for spectral scan
+	 * operation. This is an u8 attribute and uses the values in enum
+	 * nl80211_chan_width. This is an optional attribute.
+	 * If this attribute is not populated, the driver should configure the
+	 * spectral scan bandwidth to the maximum value supported by the target
+	 * for the current operating bandwidth.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH = 30,
 
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
@@ -6296,6 +6639,14 @@
 	 * u32 attribute.
 	 */
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18,
+	/* Flag attribute to indicate agile spectral scan capability
+	 * for 320 MHz mode.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320 = 19,
+	/* Number of spectral detectors used for scan in 320 MHz.
+	 * u32 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ = 20,
 
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX =
@@ -6486,6 +6837,8 @@
 	QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25,
 	/* Bus failure */
 	QCA_WLAN_HANG_BUS_FAILURE = 26,
+	/* tasklet/credit latency found */
+	QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT = 27,
 };
 
 /**
@@ -6511,6 +6864,28 @@
 };
 
 /**
+ * enum qca_wlan_vendor_flush_pending_policy: Represents values for
+ * the policy to flush pending frames, configured via
+ * %QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING. This enumeration defines the
+ * valid values for %QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY.
+ *
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE: This value clears all
+ * the flush policy configured before. This command basically disables the
+ * flush config set by the user.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE: This value configures
+ * the flush policy to be immediate. All pending packets for the peer/TID are
+ * flushed when this command/policy is received.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END: This value configures
+ * the flush policy to the end of TWT SP. All pending packets for the peer/TID
+ * are flushed when the end of TWT SP is reached.
+ */
+enum qca_wlan_vendor_flush_pending_policy  {
+	QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE = 0,
+	QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE = 1,
+	QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END = 2,
+};
+
+/**
  * enum qca_wlan_vendor_attr_flush_pending - Attributes for
  * flushing pending traffic in firmware.
  *
@@ -6518,12 +6893,25 @@
  * @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending
  * packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK,
  * AC_VI, AC_VO respectively. Set the corresponding bit to 1 to
- * flush packets with access category.
+ * flush packets with access category. This is optional. See below.
+ * @QCA_WLAN_VENDOR_ATTR_TID_MASK: Configure TID mask of the pending packets.
+ * It is a u32 value with bit 0-7 representing TID 0-7. Set corresponding
+ * bit to 1 to act upon the TID. This is optional. Either this attribute or
+ * %QCA_WLAN_VENDOR_ATTR_AC must be provided. If both are provided,
+ * %QCA_WLAN_VENDOR_ATTR_TID_MASK takes precedence. If neither are provided
+ * it is an error.
+ * @QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY: Policy of flushing the pending
+ * packets corresponding to the peer/TID provided. It is a u32 value,
+ * represented by %enum qca_wlan_vendor_flush_pending_policy. This
+ * value is honored only when TID mask is provided. This is not honored when AC
+ * mask is provided.
  */
 enum qca_wlan_vendor_attr_flush_pending {
 	QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0,
 	QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1,
 	QCA_WLAN_VENDOR_ATTR_AC = 2,
+	QCA_WLAN_VENDOR_ATTR_TID_MASK = 3,
+	QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY = 4,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST,
@@ -6640,8 +7028,9 @@
  *
  * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
  *	Default WLAN operation level which throughput orientated.
- * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
- *	Use moderate level to improve latency by limit scan duration.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR:
+ *	Use XR level to benefit XR (extended reality) application to achieve
+ *	latency and power by via constraint scan/roaming/adaptive PS.
  * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
  *	Use low latency level to benifit application like concurrent
  *	downloading or video streaming via constraint scan/adaptive PS.
@@ -6652,7 +7041,10 @@
 enum qca_wlan_vendor_attr_config_latency_level {
 	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0,
 	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1,
-	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2,
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR = 2,
+	/* legacy name */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE =
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR,
 	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3,
 	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4,
 
@@ -7203,6 +7595,15 @@
 	 * there is any critical ongoing operation.
 	 */
 	QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW = 3,
+	/* Nested attribute, the driver/firmware uses this attribute to report
+	 * thermal statistics of different thermal levels to userspace when
+	 * requested using the
+	 * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS command
+	 * type. This attribute contains a nested array of records of thermal
+	 * statistics of multiple levels. The attributes used inside this nested
+	 * attribute are defined in enum qca_wlan_vendor_attr_thermal_stats.
+	 */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS = 4,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST,
@@ -7231,6 +7632,13 @@
  * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current
  * thermal level from the driver/firmware. The driver should respond with a
  * thermal level defined in enum qca_wlan_vendor_thermal_level.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS: Request to get the
+ * current thermal statistics from the driver/firmware. The driver should
+ * respond with statistics of all thermal levels encapsulated in the attribute
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS: Request to clear
+ * the current thermal statistics for all thermal levels maintained in the
+ * driver/firmware and start counting from zero again.
  */
 enum qca_wlan_vendor_attr_thermal_cmd_type {
 	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS,
@@ -7239,6 +7647,8 @@
 	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME,
 	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL,
 	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS,
 };
 
 /**
@@ -7334,6 +7744,35 @@
 };
 
 /**
+ * enum qca_wlan_vendor_attr_thermal_stats - vendor subcmd attributes
+ * to get thermal status from the driver/firmware.
+ * enum values are used for NL attributes encapsulated inside the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS nested attribute.
+ *
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE: Minimum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE: Maximum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME: The total time spent on each
+ * thermal level in milliseconds. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER: Indicates the number
+ * of times the temperature crossed into the temperature range defined by the
+ * thermal level from both higher and lower directions. u32 size.
+ */
+enum qca_wlan_vendor_attr_thermal_stats {
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX =
+	QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST - 1,
+};
+
+/**
  * enum he_fragmentation_val - HE fragmentation support values
  * Indicates level of dynamic fragmentation that is supported by
  * a STA as a recipient.
@@ -7492,6 +7931,21 @@
 };
 
 /**
+ * enum qca_wlan_keep_alive_data_type - Keep alive data type configuration
+ *
+ * Indicates the frame types to use for keep alive data.
+ *
+ * @QCA_WLAN_KEEP_ALIVE_DEFAULT: Driver default type used for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_DATA: Data frame type for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_MGMT: Management frame type for keep alive.
+ */
+enum qca_wlan_keep_alive_data_type {
+	QCA_WLAN_KEEP_ALIVE_DEFAULT = 0,
+	QCA_WLAN_KEEP_ALIVE_DATA = 1,
+	QCA_WLAN_KEEP_ALIVE_MGMT = 2,
+};
+
+/**
  * enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for
  * HE operating mode control transmit request. These attributes are
  * sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and
@@ -7989,6 +8443,78 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX = 49,
 
+	/* 8-bit unsigned value to configure the driver to ignore the SAE H2E
+	 * requirement mismatch for 6 GHz connection.
+	 * 0 - Default behavior, 1 - Ignore SAE H2E requirement mismatch.
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE = 50,
+
+	/* 8-bit unsigned value to configure the driver to allow 6 GHz
+	 * connection with all security modes.
+	 * 0 - Default behavior, 1 - Allow 6 GHz connection with all security
+	 * modes.
+	 * This attribute is used for testing purposes.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE = 51,
+
+	/* 8-bit unsigned value to configure the driver to transmit data with
+	 * ER SU PPDU type.
+	 *
+	 * 0 - Default behavior, 1 - Enable ER SU PPDU type TX.
+	 * This attribute is used for testing purposes.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE = 52,
+
+	/* 8-bit unsigned value to configure the driver to use Data or
+	 * Management frame type for keep alive data.
+	 * Uses enum qca_wlan_keep_alive_data_type values.
+	 *
+	 * This attribute is used for testing purposes.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE = 53,
+
+	/* 8-bit unsigned value to configure the driver to use scan request
+	 * BSSID value in Probe Request frame RA(A1) during the scan. The
+	 * driver saves this configuration and applies this setting to all user
+	 * space scan requests until the setting is cleared. If this
+	 * configuration is set, the driver uses the BSSID value from the scan
+	 * request to set the RA(A1) in the Probe Request frames during the
+	 * scan.
+	 *
+	 * 0 - Default behavior uses the broadcast RA in Probe Request frames.
+	 * 1 - Uses the scan request BSSID in RA in Probe Request frames.
+	 * This attribute is used for testing purposes.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA = 54,
+
+	/* 8-bit unsigned value to configure the driver to enable/disable the
+	 * BSS max idle period support.
+	 *
+	 * 0 - Disable the BSS max idle support.
+	 * 1 - Enable the BSS max idle support.
+	 * This attribute is used for testing purposes.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE = 55,
+
+	/* 8-bit unsigned value to configure the driver/firmware to enable or
+	 * disable Rx control frame to MultiBSS subfield in the HE MAC
+	 * capabilities information field.
+	 * 0 - Disable Rx control frame to MultiBSS subfield
+	 * 1 - Enable Rx control frame to MultiBSS subfield
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS = 56,
+
+	/* 8-bit unsigned value to configure the driver/firmware to enable or
+	 * disable Broadcast TWT support subfield in the HE MAC capabilities
+	 * information field.
+	 * 0 - Disable Broadcast TWT support subfield
+	 * 1 - Enable Broadcast TWT support subfield
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT = 57,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -8061,6 +8587,10 @@
  *
  * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is
  * ready for a new TWT session setup after it issued a TWT teardown.
+ *
+ * @QCA_WLAN_TWT_SET_PARAM: Configure TWT related parameters. Required
+ * parameters are obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refer
+ * the enum qca_wlan_vendor_attr_twt_set_param.
  */
 enum qca_wlan_twt_operation {
 	QCA_WLAN_TWT_SET = 0,
@@ -8073,6 +8603,7 @@
 	QCA_WLAN_TWT_CLEAR_STATS = 7,
 	QCA_WLAN_TWT_GET_CAPABILITIES = 8,
 	QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9,
+	QCA_WLAN_TWT_SET_PARAM = 10,
 };
 
 /**
@@ -8087,7 +8618,8 @@
  * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the
  * parameters configured for TWT. These parameters are represented by
  * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume,
- * or enum qca_wlan_vendor_attr_twt_stats based on the operation.
+ * enum qca_wlan_vendor_attr_twt_set_param, or
+ * enum qca_wlan_vendor_attr_twt_stats based on the operation.
  */
 enum qca_wlan_vendor_attr_config_twt {
 	QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0,
@@ -8378,9 +8910,13 @@
  * response.
  *
  * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64)
- * This field is applicable for TWT response only.
- * This field contains absolute TSF value of the wake time received
- * from the TWT responder and is passed to the userspace.
+ * In TWT setup command this field contains absolute TSF that will
+ * be used by TWT requester during setup.
+ * In TWT response this field contains absolute TSF value of the
+ * wake time received from the TWT responder and is passed to
+ * the userspace.
+ * This is an optional parameter for
+ * 1. TWT SET Request
  * This is a required parameter for
  * 1. TWT SET Response
  * 2. TWT GET Response
@@ -8397,14 +8933,17 @@
  * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address
  * Represents the MAC address of the peer for which the TWT session
  * is being configured. This is used in AP mode to represent the respective
- * client. In AP mode, this is an optional parameter for response and is
- * a required parameter for
- * 1. TWT SET Request
- * 2. TWT GET Request
- * 3. TWT TERMINATE Request
- * 4. TWT SUSPEND Request
+ * client.
+ * In AP mode, this is a required parameter in response for
+ * 1. TWT SET
+ * 2. TWT GET
+ * 3. TWT TERMINATE
+ * 4. TWT SUSPEND
  * In STA mode, this is an optional parameter in request and response for
  * the above four TWT operations.
+ * In AP mode, this is a required parameter in request for
+ * 1. TWT GET
+ * 2. TWT TERMINATE
  *
  * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32)
  * Minimum tolerance limit of wake interval parameter in microseconds.
@@ -8422,6 +8961,59 @@
  * TWT state for the given dialog id. The values for this are represented
  * by enum qca_wlan_twt_setup_state.
  * This is obtained through TWT GET operation.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA: Optional (u32)
+ * This attribute is used to configure wake interval mantissa.
+ * The unit is microseconds. This attribute, when specified, takes
+ * precedence over QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA.
+ * This parameter is used for
+ * 1. TWT SET Request and Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8)
+ * This attribute is used to configure Broadcast TWT ID.
+ * The Broadcast TWT ID indicates a specific Broadcast TWT for which the
+ * transmitting STA is providing TWT parameters. The allowed values are 0 to 31.
+ * This parameter is used for
+ * 1. TWT SET Request
+ * 2. TWT TERMINATE Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8)
+ * This attribute is used to configure Broadcast TWT recommendation.
+ * The Broadcast TWT Recommendation subfield contains a value that indicates
+ * recommendations on the types of frames that are transmitted by TWT
+ * scheduled STAs and scheduling AP during the broadcast TWT SP.
+ * The allowed values are 0 - 3.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8)
+ * This attribute is used to configure Broadcast TWT Persistence.
+ * The Broadcast TWT Persistence subfield indicates the number of
+ * TBTTs during which the Broadcast TWT SPs corresponding to this
+ * broadcast TWT Parameter set are present. The number of beacon intervals
+ * during which the Broadcast TWT SPs are present is equal to the value in the
+ * Broadcast TWT Persistence subfield plus 1 except that the value 255
+ * indicates that the Broadcast TWT SPs are present until explicitly terminated.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE: Optional (u8)
+ * This attribute contains the value of the Responder PM Mode subfield (0 or 1)
+ * from TWT response frame.
+ * This parameter is used for
+ * 1. TWT SET Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT: Optional (u32)
+ * This attribute is used to configure the announce timeout value (in us) in
+ * the firmware. This timeout value is only applicable for the announced TWT. If
+ * the timeout value is non-zero the firmware waits up to the timeout value to
+ * use Data frame as an announcement frame. If the timeout value is 0 the
+ * firmware sends an explicit QoS NULL frame as the announcement frame on SP
+ * start. The default value in the firmware is 0.
+ * This parameter is used for
+ * 1. TWT SET Request
  */
 enum qca_wlan_vendor_attr_twt_setup {
 	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
@@ -8449,6 +9041,15 @@
 	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19,
 	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20,
 
+	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
+
+	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22,
+	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
+	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
+
+	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE = 25,
+	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT = 26,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX =
@@ -8487,6 +9088,18 @@
  * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
  * session due to roaming. Used on the TWT_TERMINATE notification from the
  * firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the
+ * TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel
+ * Concurrency). Used on the TWT_TERMINATE notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup
+ * request due to roaming in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT
+ * setup request due to channel switch in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS: FW rejected the TWT setup
+ * request due to scan in progress.
+ * QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE: The driver requested to
+ * terminate an existing TWT session on power save exit request from userspace.
+ * Used on the TWT_TERMINATE notification from the driver/firmware.
  */
 enum qca_wlan_vendor_twt_status {
 	QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
@@ -8507,6 +9120,11 @@
 	QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
 	QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
 	QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
+	QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18,
+	QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19,
+	QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20,
+	QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS = 21,
+	QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE = 22,
 };
 
 /**
@@ -8763,6 +9381,27 @@
 };
 
 /**
+ * enum qca_wlan_vendor_attr_twt_set_param: Represents attributes for
+ * TWT (Target Wake Time) related parameters. It is used when
+ * %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to %QCA_WLAN_TWT_SET_PARAM.
+ * These attributes are sent as part of %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE: Optional (u8)
+ * This attribute configures AC parameters to be used for all TWT
+ * sessions in AP mode.
+ * Uses the enum qca_wlan_ac_type values.
+ */
+enum qca_wlan_vendor_attr_twt_set_param {
+	QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE = 1,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_MAX =
+	QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST - 1,
+};
+
+/**
  * enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by
  * the TWT responder
  *
@@ -8853,6 +9492,22 @@
 };
 
 /**
+ * enum qca_wlan_vendor_cfr_data_transport_modes - Defines QCA vendor CFR data
+ * transport modes and is used by the attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE as a part of the vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
+ * @QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS: Use relayfs to send CFR data.
+ * @QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS: Use netlink events to send CFR
+ * data. The data shall be encapsulated within
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA along with the vendor sub command
+ * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an asynchronous event.
+ */
+enum qca_wlan_vendor_cfr_data_transport_modes {
+	QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS = 0,
+	QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS = 1,
+};
+
+/**
  * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by
  * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor
  * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
@@ -9042,6 +9697,27 @@
  * MAC for CFR capture. This is a bitmask in which each bit represents the
  * corresponding Data frame subtype value per IEEE Std 802.11-2016,
  * 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE: Optional (u8)
+ * Userspace can use this attribute to specify the driver about which transport
+ * mode shall be used by the driver to send CFR data to userspace. Uses values
+ * from enum qca_wlan_vendor_cfr_data_transport_modes. When this attribute is
+ * not present, the driver shall use the default transport mechanism which is
+ * QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID: Optional (u32)
+ * Userspace can use this attribute to specify the nl port id of the application
+ * which receives the CFR data and processes it further so that the drivers can
+ * unicast the netlink events to a specific application. Optionally included
+ * when QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE is set to
+ * QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS, not required otherwise. The drivers
+ * shall multicast the netlink events when this attribute is not included.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA: Required (NLA_BINARY).
+ * This attribute will be used by the driver to encapsulate and send CFR data
+ * to userspace along with QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an
+ * asynchronous event when the driver is configured to send CFR data using
+ * netlink events with %QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS.
  */
 enum qca_wlan_vendor_peer_cfr_capture_attr {
 	QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0,
@@ -9070,6 +9746,9 @@
 	QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23,
 	QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24,
 	QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25,
+	QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE = 26,
+	QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID = 27,
+	QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA = 28,
 
 	/* Keep last */
 	QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST,
@@ -9291,7 +9970,6 @@
  *		has priority over BT_A2DP and ZB_HIGH.
  *	3: BT_A2DP has priority over ZB_HIGH.
  */
-
 enum qca_vendor_attr_coex_config_three_way {
 	QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0,
 	QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1,
@@ -9756,20 +10434,48 @@
  *
  * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required
  * Nested attribute containing multiple ranges with following attributes:
- *	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
- *	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ *	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START,
+ *	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, and
+ *	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM.
  *
  * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32)
  * Starting center frequency in MHz.
  *
  * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
  * Ending center frequency in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM:
+ * s32 attribute, optional. It is a per frequency range attribute.
+ * The maximum TX power limit from user space is to be applied on an
+ * unrestricted interface for corresponding frequency range. It is also
+ * possible that the actual TX power may be even lower than this cap due to
+ * other considerations such as regulatory compliance, SAR, etc. In absence of
+ * this attribute the driver shall follow current behavior which means
+ * interface (SAP/P2P) function can keep operating on an unsafe channel with TX
+ * power derived by the driver based on regulatory/SAR during interface up.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK:
+ * u32 attribute, optional. Indicates all the interface types which are
+ * restricted for all frequency ranges provided in
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * This attribute encapsulates bitmasks of interface types defined in
+ * enum nl80211_iftype. If an interface is marked as restricted the driver must
+ * move to a safe channel and if no safe channel is available the driver shall
+ * terminate that interface functionality. In absence of this attribute,
+ * interface (SAP/P2P) can still continue operating on an unsafe channel with
+ * TX power limit derived from either
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on
+ * regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM
+ * is not provided.
  */
 enum qca_wlan_vendor_attr_avoid_frequency_ext {
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
+	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4,
+	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5,
 
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
@@ -10140,6 +10846,11 @@
  * failed roam invoke. Different roam invoke failure reason codes
  * are specified in enum qca_vendor_roam_invoke_fail_reasons. This can be
  * queried either in connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY: u32, used in STA mode only.
+ * This represents the average congestion duration of uplink frames in MAC
+ * queue in unit of ms. This can be queried either in connected state or
+ * disconnected state.
  */
 enum qca_wlan_vendor_attr_get_sta_info {
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0,
@@ -10192,6 +10903,7 @@
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON = 47,
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON = 48,
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON = 49,
+	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY = 50,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST,
@@ -10630,10 +11342,25 @@
  * u8 attribute. Notify the TX VDEV status. Possible values 0, 1
  * belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV,
  * 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT:
+ * u8 attribute, required. 1 means Tx VDEV up event. 0 means Tx VDEV down event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID:
+ * u8 attribute, required. Indicates group id of Tx VDEV.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * group information. The attributes defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_group_info
+ * are nested in this attribute.
  */
 enum qca_wlan_vendor_attr_mbssid_tx_vdev_status {
 	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0,
 	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1,
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT = 2,
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID = 3,
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO = 4,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST,
@@ -10642,6 +11369,79 @@
 };
 
 /**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX:
+ * u32 attribute, required. Contains interface index.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS:
+ * u8 attribute, required. 0 - means vdev is in down state.
+ * 1 - means vdev is in up state.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info {
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX = 1,
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS = 2,
+
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_MAX =
+	QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO - 1,
+};
+
+/**
+ * enum qca_wlan_concurrent_sta_policy_config - Concurrent STA policies
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY: Preference to the primary
+ * STA interface has to be given while selecting the connection policies
+ * (e.g., BSSID, band, TX/RX chains, etc.) for the subsequent STA interface.
+ * An interface is set as primary through the attribute
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY. This policy is not
+ * applicable if the primary interface has not been set earlier.
+ *
+ * The intention is not to downgrade the primary STA performance, such as:
+ * - Do not reduce the number of TX/RX chains of primary connection.
+ * - Do not optimize DBS vs. MCC/SCC, if DBS ends up reducing the number of
+ *   chains.
+ * - If using MCC, should set the MCC duty cycle of the primary connection to
+ *   be higher than the secondary connection.
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED: The connection policies for the
+ * subsequent STA connection shall be chosen to balance with the existing
+ * concurrent STA's performance.
+ * Such as
+ * - Can choose MCC or DBS mode depending on the MCC efficiency and hardware
+ *   capability.
+ * - If using MCC, set the MCC duty cycle of the primary connection to be equal
+ *   to the secondary.
+ * - Prefer BSSID candidates which will help provide the best "overall"
+ *   performance for all the STA connections.
+ */
+enum qca_wlan_concurrent_sta_policy_config {
+	QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY = 0,
+	QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_concurrent_sta_policy - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG:
+ * u8 attribute. Configures the concurrent STA policy configuration.
+ * Possible values are defined in enum qca_wlan_concurrent_sta_policy_config.
+ */
+enum qca_wlan_vendor_attr_concurrent_sta_policy {
+	QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG = 1,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX =
+	QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST - 1,
+
+};
+
+/**
  * enum qca_sta_connect_fail_reason_codes - Defines values carried
  * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor
  * attribute.
@@ -10669,4 +11469,583 @@
 	QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7,
 };
 
+/**
+ * enum qca_wlan_vendor_usable_channels_filter - Bitmask of different
+ * filters defined in this enum are used in attribute
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK.
+ *
+ * @QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX: When this bit is set, the driver
+ * shall filter the channels which are not usable because of coexistence with
+ * cellular radio.
+ * @QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY: When this bit is set, the driver
+ * shall filter the channels which are not usable because of existing active
+ * interfaces in the driver and will result in Multi Channel Concurrency, etc.
+ *
+ */
+enum qca_wlan_vendor_usable_channels_filter {
+	QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX = 0,
+	QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_chan_info - Attributes used inside
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ:
+ * u32 attribute, required. Indicates the center frequency of the primary
+ * channel in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ:
+ * u32 attribute. Indicates the center frequency of the primary segment of the
+ * channel in MHz. This attribute is required when reporting 40 MHz, 80 MHz,
+ * 160 MHz, and 320 MHz channels.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ:
+ * u32 attribute. Indicates the center frequency of the secondary segment of
+ * 80+80 channel in MHz. This attribute is required only when
+ * QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH is set to NL80211_CHAN_WIDTH_80P80.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH:
+ * u32 attribute, required. Indicates the bandwidth of the channel, possible
+ * values are defined in enum nl80211_chan_width.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK:
+ * u32 attribute, required. Indicates all the interface types for which this
+ * channel is usable. This attribute encapsulates bitmasks of interface types
+ * defined in enum nl80211_iftype.
+ *
+ */
+enum qca_wlan_vendor_attr_chan_info {
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ = 1,
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ = 2,
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ = 3,
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH = 4,
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK = 5,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX =
+	QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_usable_channels - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK:
+ * u32 attribute. Indicates the bands from which the channels should be reported
+ * in response. This attribute encapsulates bit masks of bands defined in enum
+ * nl80211_band. Optional attribute, if not present in the request the driver
+ * shall return channels from all supported bands.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK:
+ * u32 attribute. Indicates all the interface types for which the usable
+ * channels information is requested. This attribute encapsulates bitmasks of
+ * interface types defined in enum nl80211_iftype. Optional attribute, if not
+ * present in the request the driver shall send information of all supported
+ * interface modes.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK:
+ * u32 attribute. This attribute carries information of all filters that shall
+ * be applied while populating usable channels information by the driver. This
+ * attribute carries bit masks of different filters defined in enum
+ * qca_wlan_vendor_usable_channels_filter. Optional attribute, if not present
+ * in the request the driver shall send information of channels without applying
+ * any of the filters that can be configured through this attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * usability information of each channel. The attributes defined in enum
+ * qca_wlan_vendor_attr_chan_info are used inside this attribute.
+ */
+enum qca_wlan_vendor_attr_usable_channels {
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK = 1,
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK = 2,
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK = 3,
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO = 4,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX =
+	QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_radar_history: Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY to get DFS radar history.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES: Nested attribute to carry
+ *	the list of radar history entries.
+ *	Each entry contains freq, timestamp, and radar signal detect flag.
+ *	The driver shall add an entry when CAC has finished, or radar signal
+ *	has been detected post AP beaconing. The driver shall maintain at least
+ *	8 entries in order to save CAC result for a 160 MHz channel.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ: u32 attribute.
+ *	Channel frequency in MHz.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP: u64 nanoseconds.
+ *	CLOCK_BOOTTIME timestamp when this entry is updated due to CAC
+ *	or radar detection.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED: NLA_FLAG attribute.
+ *	This flag indicates radar signal has been detected.
+ */
+enum qca_wlan_vendor_attr_radar_history {
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_INVALID = 0,
+
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES = 1,
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ = 2,
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP = 3,
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED = 4,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST,
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX =
+	QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_mcc_quota_type: MCC channel time quota type
+ *
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR: In the event, it indicates that the
+ *	target exited MCC state and cleared the quota information. In the
+ *	command it clears MCC quota setting and restores adaptive scheduling.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED: Channel time quota is fixed and
+ *      will not be changed.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC: Channel time quota is dynamic
+ *      and the target may change the quota based on the data activity.
+ */
+enum qca_wlan_vendor_mcc_quota_type {
+	QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR = 0,
+	QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED = 1,
+	QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mcc_quota: Used by the vendor event
+ * QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA to indicate MCC channel
+ * quota information or as a command to set the required MCC quota for an
+ * interface.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE: u32 attribute.
+ * The type is defined in enum qca_wlan_vendor_mcc_quota_type.
+ * In a command this specifies the MCC quota type to be set for the interface.
+ * In an event this provides the current quota type in force.
+ * This is required in a command and an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES: Nested attribute to carry
+ * the list of channel quota entries.
+ * In an event each entry contains the frequency and respective time quota for
+ * all the MCC interfaces.
+ * In a command it specifies the interface index and respective time quota.
+ * In a command only one entry (ifindex, quota pair) may be specified.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ: u32 attribute.
+ * Channel frequency in MHz. This is present only in an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE: u32 attribute.
+ * Channel time quota expressed as percentage.
+ * This is present in an event and a command.
+ * In an command, the user shall specify the quota to be allocated for the
+ * interface represented by %QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX.
+ * In an event this provides the existing quota for the channel.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX: u32 attribute.
+ * Specifies the interface index (netdev) for which the corresponding
+ * configurations are applied. This is required in a command only. Only one
+ * interface index may be specified. If not specified, the configuration is
+ * rejected.
+ */
+enum qca_wlan_vendor_attr_mcc_quota {
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE = 1,
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES = 2,
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ = 3,
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE = 4,
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX = 5,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST,
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX =
+	QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mdns_offload - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE: Required (flag)
+ * Enable mDNS offload. This attribute is mandatory to enable
+ * mDNS offload feature. If this attribute is not present, mDNS offload
+ * is disabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE: Nested attribute containing
+ * one or more %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY attributes. This
+ * attribute is mandatory when enabling the feature, and not required when
+ * disabling the feature.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY: Nested attribute containing
+ * the following attributes:
+ *	%QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN
+ *	%QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT
+ *	%QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN: Required string attribute.
+ * It consists of a hostname and ".local" as the domain name. The character
+ * set is limited to UTF-8 encoding. The maximum allowed size is 63 bytes.
+ * It is used to compare the domain in the "QU" query. Only 1 FQDN is
+ * supported per vdev.
+ * For example: myphone.local
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT: Required
+ * u16 attribute. It specifies the total number of resource records present
+ * in the answer section of the answer payload. This attribute is needed by the
+ * firmware to populate the mDNS response frame for mDNS queries without having
+ * to parse the answer payload.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD: Required binary blob
+ * attribute sent by the mdnsResponder from userspace. It contains resource
+ * records of various types (e.g., A, AAAA, PTR, TXT) and service list. This
+ * payload is passed down to the firmware and is transmitted in response to
+ * mDNS queries.
+ * The maximum supported size of the answer payload is 512 bytes.
+ */
+enum qca_wlan_vendor_attr_mdns_offload {
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE = 1,
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE = 2,
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY = 3,
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN = 4,
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT = 5,
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD = 6,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_MAX =
+	QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_monitor_data_frame_type - Represent the various
+ * Data frame types to be sent over the monitor interface.
+ */
+enum qca_wlan_vendor_monitor_data_frame_type {
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0),
+	/* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is not set
+	 */
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16),
+	QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17),
+};
+
+/**
+ * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various
+ * Management frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the Management Frames.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the Management frames
+ * except the Beacon frame.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected
+ * BSSID Beacon frames. Valid only in the connected state.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents
+ * the Beacon frames obtained during the scan (off channel and connected
+ * channel), when in connected state.
+ */
+enum qca_wlan_vendor_monitor_mgmt_frame_type {
+	QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0),
+	/* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set
+	 */
+	QCA_WLAN_VENDOR_MONITOR_MGMT_NO_BEACON = BIT(1),
+	QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2),
+	QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3),
+};
+
+/**
+ * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various
+ * Control frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the Control frames
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger frame
+ */
+enum qca_wlan_vendor_monitor_ctrl_frame_type {
+	QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0),
+	/* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set
+	 */
+	QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the
+ * monitor mode.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: u32
+ * attribute.
+ * Represents the interval in milliseconds only for the connected Beacon frames,
+ * expecting the connected BSS's Beacon frames to be sent on the monitor
+ * interface at this specific interval.
+ */
+enum qca_wlan_vendor_attr_set_monitor_mode {
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX =
+	QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags.
+ * Bits will be set to 1 if the corresponding state is enabled.
+ *
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start.
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end.
+ */
+enum qca_wlan_vendor_roam_scan_state {
+	QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0),
+	QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_roam_event_type - Roam event type flags.
+ * Bits will be set to 1 if the corresponding event is notified.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event
+ * carries the trigger reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries
+ * the BSSID, RSSI, frequency info of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event
+ * carries the roam fail reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the
+ * BSSID, RSSI, frequency info of the AP to which the roam was attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam
+ * event carries the roam invoke fail reason. When set, it is expected that
+ * the roam event carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event
+ * carries the roam scan state. When set, it is expected that the roam event
+ * carries the respective scan state via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding
+ * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST.
+ */
+enum qca_wlan_vendor_roam_event_type {
+	QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0),
+	QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1),
+	QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2),
+	QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info.
+ * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address
+ * representing the BSSID of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value
+ * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is
+ * attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, frequency in MHz
+ * on which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam fail reason for the last failed
+ * roaming attempt by the firmware for the specific BSSID. Different roam
+ * failure reason codes are specified in enum qca_vendor_roam_fail_reasons.
+ */
+enum qca_wlan_vendor_attr_roam_events_candidate_info {
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX =
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the
+ * roam events to the driver or notify these events from the driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the
+ * driver/firmware to enable/disable the notification of roam events. It's a
+ * mandatory attribute and used only in the request from the userspace to the
+ * host driver. 1-Enable, 0-Disable.
+ * If the roaming is totally offloaded to the firmware, this request when
+ * enabled shall mandate the firmware to notify all the relevant roam events
+ * represented by the below attributes. If the host is in the suspend mode,
+ * the behavior of the firmware to notify these events is guided by
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get
+ * these events in the suspend state, the firmware is expected to wake up the
+ * host before the respective events are notified. Please note that such a
+ * request to get the events in the suspend state will have a definite power
+ * implication.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents
+ * that the roam events need to be notified in the suspend state too. By
+ * default, these roam events are notified in the resume state. With this flag,
+ * the roam events are notified in both resume and suspend states.
+ * This attribute is used in the request from the userspace to the host driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only.
+ * Represents the different roam event types, signified by the enum
+ * qca_wlan_vendor_roam_event_type.
+ * Each bit of this attribute represents the different roam even types reported
+ * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. Each bit of this attribute represents the
+ * different roam trigger reason code which are defined in enum
+ * qca_vendor_roam_triggers.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info
+ * for which the roam is attempted. Each entry is a nested attribute defined
+ * by enum qca_wlan_vendor_attr_roam_events_candidate_info.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents
+ * the scan state on which the roam events need to be notified. The values for
+ * this attribute are referred from enum qca_wlan_vendor_roam_scan_state.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of
+ * u32 values. List of frequencies in MHz considered for a roam scan.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ */
+enum qca_wlan_vendor_attr_roam_events {
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX =
+	QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST -1,
+};
+
+/**
+ * enum qca_wlan_ratemask_params_type - Rate mask config type
+ *
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM: CCK/OFDM rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HT: HT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT: VHT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HE: HE rate mask config
+ */
+enum qca_wlan_ratemask_params_type {
+	QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM = 0,
+	QCA_WLAN_RATEMASK_PARAMS_TYPE_HT = 1,
+	QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT = 2,
+	QCA_WLAN_RATEMASK_PARAMS_TYPE_HE = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ratemask_params - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG.
+ * This is used to set the rate mask value to be used in rate selection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST:
+ * Array of nested containing attributes
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE and
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE: u8, represents
+ * the different PHY types to which the rate mask config is to be applied.
+ * The values for this attribute are referred from enum
+ * qca_wlan_vendor_ratemask_params_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP: binary, rate mask bitmap.
+ * A bit value of 1 represents rate is enabled and a value of 0
+ * represents rate is disabled.
+ * For HE targets, 12 bits correspond to one NSS setting.
+ * b0-13  => NSS1, MCS 0-13
+ * b14-27 => NSS2, MCS 0-13 and so on for other NSS.
+ * For VHT targets, 10 bits correspond to one NSS setting.
+ * b0-9   => NSS1, MCS 0-9
+ * b10-19 => NSS2, MCS 0-9 and so on for other NSS.
+ * For HT targets, 8 bits correspond to one NSS setting.
+ * b0-7  => NSS1, MCS 0-7
+ * b8-15 => NSS2, MCS 0-7 and so on for other NSS.
+ * For OFDM/CCK targets, 8 bits correspond to one NSS setting.
+ */
+enum qca_wlan_vendor_attr_ratemask_params {
+	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST = 1,
+	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE = 2,
+	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP = 3,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX =
+	QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST - 1,
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index 372905d..c0f154e 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -280,32 +280,33 @@
 
 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
 			      const u8 *addr2, const u8 *password,
-			      size_t password_len, const char *identifier)
+			      size_t password_len)
 {
 	u8 counter, k;
 	u8 addrs[2 * ETH_ALEN];
-	const u8 *addr[3];
-	size_t len[3];
-	size_t num_elem;
-	u8 *dummy_password, *tmp_password;
+	const u8 *addr[2];
+	size_t len[2];
+	u8 *stub_password, *tmp_password;
 	int pwd_seed_odd = 0;
 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
 	size_t prime_len;
-	struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
+	struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL;
 	u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
 	u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
 	u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
 	u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
+	u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
 	int res = -1;
 	u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
 		       * mask */
+	unsigned int is_eq;
 
 	os_memset(x_bin, 0, sizeof(x_bin));
 
-	dummy_password = os_malloc(password_len);
+	stub_password = os_malloc(password_len);
 	tmp_password = os_malloc(password_len);
-	if (!dummy_password || !tmp_password ||
-	    random_get_bytes(dummy_password, password_len) < 0)
+	if (!stub_password || !tmp_password ||
+	    random_get_bytes(stub_password, password_len) < 0)
 		goto fail;
 
 	prime_len = sae->tmp->prime_len;
@@ -324,13 +325,10 @@
 
 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
 			      password, password_len);
-	if (identifier)
-		wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
-			   identifier);
 
 	/*
 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
-	 * base = password [|| identifier]
+	 * base = password
 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
 	 *              base || counter)
 	 */
@@ -338,15 +336,8 @@
 
 	addr[0] = tmp_password;
 	len[0] = password_len;
-	num_elem = 1;
-	if (identifier) {
-		addr[num_elem] = (const u8 *) identifier;
-		len[num_elem] = os_strlen(identifier);
-		num_elem++;
-	}
-	addr[num_elem] = &counter;
-	len[num_elem] = sizeof(counter);
-	num_elem++;
+	addr[1] = &counter;
+	len[1] = sizeof(counter);
 
 	/*
 	 * Continue for at least k iterations to protect against side-channel
@@ -365,9 +356,9 @@
 		}
 
 		wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
-		const_time_select_bin(found, dummy_password, password,
+		const_time_select_bin(found, stub_password, password,
 				      password_len, tmp_password);
-		if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+		if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
 				       addr, len, pwd_seed) < 0)
 			break;
 
@@ -407,26 +398,43 @@
 		goto fail;
 	}
 
-	if (!sae->tmp->pwe_ecc)
-		sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
-	if (!sae->tmp->pwe_ecc)
-		res = -1;
-	else
-		res = crypto_ec_point_solve_y_coord(sae->tmp->ec,
-						    sae->tmp->pwe_ecc, x,
-						    pwd_seed_odd);
-	if (res < 0) {
-		/*
-		 * This should not happen since we already checked that there
-		 * is a result.
-		 */
+	/* y = sqrt(x^3 + ax + b) mod p
+	 * if LSB(save) == LSB(y): PWE = (x, y)
+	 * else: PWE = (x, p - y)
+	 *
+	 * Calculate y and the two possible values for PWE and after that,
+	 * use constant time selection to copy the correct alternative.
+	 */
+	y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x);
+	if (!y ||
+	    dragonfly_sqrt(sae->tmp->ec, y, y) < 0 ||
+	    crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN,
+				 prime_len) < 0 ||
+	    crypto_bignum_sub(sae->tmp->prime, y, y) < 0 ||
+	    crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN,
+				 SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) {
 		wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
+		goto fail;
+	}
+
+	is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01);
+	const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN,
+			      prime_len, x_y + prime_len);
+	os_memcpy(x_y, x_bin, prime_len);
+	wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len);
+	crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
+	sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y);
+	if (!sae->tmp->pwe_ecc) {
+		wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
+		res = -1;
 	}
 
 fail:
+	forced_memzero(x_y, sizeof(x_y));
 	crypto_bignum_deinit(qr, 0);
 	crypto_bignum_deinit(qnr, 0);
-	os_free(dummy_password);
+	crypto_bignum_deinit(y, 1);
+	os_free(stub_password);
 	bin_clear_free(tmp_password, password_len);
 	crypto_bignum_deinit(x, 1);
 	os_memset(x_bin, 0, sizeof(x_bin));
@@ -438,13 +446,12 @@
 
 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
 			      const u8 *addr2, const u8 *password,
-			      size_t password_len, const char *identifier)
+			      size_t password_len)
 {
 	u8 counter, k, sel_counter = 0;
 	u8 addrs[2 * ETH_ALEN];
-	const u8 *addr[3];
-	size_t len[3];
-	size_t num_elem;
+	const u8 *addr[2];
+	size_t len[2];
 	u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
 		       * mask */
 	u8 mask;
@@ -468,21 +475,14 @@
 	/*
 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
-	 *              password [|| identifier] || counter)
+	 *              password || counter)
 	 */
 	sae_pwd_seed_key(addr1, addr2, addrs);
 
 	addr[0] = password;
 	len[0] = password_len;
-	num_elem = 1;
-	if (identifier) {
-		addr[num_elem] = (const u8 *) identifier;
-		len[num_elem] = os_strlen(identifier);
-		num_elem++;
-	}
-	addr[num_elem] = &counter;
-	len[num_elem] = sizeof(counter);
-	num_elem++;
+	addr[1] = &counter;
+	len[1] = sizeof(counter);
 
 	k = dragonfly_min_pwe_loop_iter(sae->group);
 
@@ -497,7 +497,7 @@
 		}
 
 		wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
-		if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+		if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
 				       addr, len, pwd_seed) < 0)
 			break;
 		res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
@@ -766,19 +766,9 @@
 	const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y);
 	wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
 
-	/* y = sqrt(v)
-	 * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */
-	if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0)
-		goto fail;
-	if ((bin1[prime_len - 1] & 0x03) != 3) {
-		wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4");
-		goto fail;
-	}
+	/* y = sqrt(v) */
 	y = crypto_bignum_init();
-	if (!y ||
-	    crypto_bignum_add(prime, one, t1) < 0 ||
-	    crypto_bignum_rshift(t1, 2, t1) < 0 ||
-	    crypto_bignum_exptmod(v, t1, prime, y) < 0)
+	if (!y || dragonfly_sqrt(ec, v, y) < 0)
 		goto fail;
 	debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
 
@@ -1354,15 +1344,13 @@
 
 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
 		       const u8 *password, size_t password_len,
-		       const char *identifier, struct sae_data *sae)
+		       struct sae_data *sae)
 {
 	if (sae->tmp == NULL ||
 	    (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
-						password_len,
-						identifier) < 0) ||
+						password_len) < 0) ||
 	    (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
-						password_len,
-						identifier) < 0))
+						password_len) < 0))
 		return -1;
 
 	sae->h2e = 0;
@@ -2023,6 +2011,9 @@
 static int sae_parse_password_identifier(struct sae_data *sae,
 					 const u8 **pos, const u8 *end)
 {
+	const u8 *epos;
+	u8 len;
+
 	wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
 		    *pos, end - *pos);
 	if (!sae_is_password_id_elem(*pos, end)) {
@@ -2037,9 +2028,17 @@
 		return WLAN_STATUS_SUCCESS; /* No Password Identifier */
 	}
 
+	epos = *pos;
+	epos++; /* skip IE type */
+	len = *epos++; /* IE length */
+	if (len > end - epos || len < 1)
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	epos++; /* skip ext ID */
+	len--;
+
 	if (sae->tmp->pw_id &&
-	    ((*pos)[1] - 1 != (int) os_strlen(sae->tmp->pw_id) ||
-	     os_memcmp(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1) != 0)) {
+	    (len != os_strlen(sae->tmp->pw_id) ||
+	     os_memcmp(sae->tmp->pw_id, epos, len) != 0)) {
 		wpa_printf(MSG_DEBUG,
 			   "SAE: The included Password Identifier does not match the expected one (%s)",
 			   sae->tmp->pw_id);
@@ -2047,14 +2046,14 @@
 	}
 
 	os_free(sae->tmp->pw_id);
-	sae->tmp->pw_id = os_malloc((*pos)[1]);
+	sae->tmp->pw_id = os_malloc(len + 1);
 	if (!sae->tmp->pw_id)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
-	os_memcpy(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1);
-	sae->tmp->pw_id[(*pos)[1] - 1] = '\0';
+	os_memcpy(sae->tmp->pw_id, epos, len);
+	sae->tmp->pw_id[len] = '\0';
 	wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
-			  sae->tmp->pw_id, (*pos)[1] -  1);
-	*pos = *pos + 2 + (*pos)[1];
+			  sae->tmp->pw_id, len);
+	*pos = epos + len;
 	return WLAN_STATUS_SUCCESS;
 }
 
@@ -2062,19 +2061,30 @@
 static int sae_parse_rejected_groups(struct sae_data *sae,
 				     const u8 **pos, const u8 *end)
 {
+	const u8 *epos;
+	u8 len;
+
 	wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
 		    *pos, end - *pos);
 	if (!sae_is_rejected_groups_elem(*pos, end))
 		return WLAN_STATUS_SUCCESS;
+
+	epos = *pos;
+	epos++; /* skip IE type */
+	len = *epos++; /* IE length */
+	if (len > end - epos || len < 1)
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	epos++; /* skip ext ID */
+	len--;
+
 	wpabuf_free(sae->tmp->peer_rejected_groups);
-	sae->tmp->peer_rejected_groups = wpabuf_alloc((*pos)[1] - 1);
+	sae->tmp->peer_rejected_groups = wpabuf_alloc(len);
 	if (!sae->tmp->peer_rejected_groups)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
-	wpabuf_put_data(sae->tmp->peer_rejected_groups, (*pos) + 3,
-			(*pos)[1] - 1);
+	wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len);
 	wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list",
 			sae->tmp->peer_rejected_groups);
-	*pos = *pos + 2 + (*pos)[1];
+	*pos = epos + len;
 	return WLAN_STATUS_SUCCESS;
 }
 
@@ -2246,10 +2256,10 @@
 	hash_len = sae->tmp->kck_len;
 
 	/* Send-Confirm */
-	sc = wpabuf_put(buf, 0);
-	wpabuf_put_le16(buf, sae->send_confirm);
 	if (sae->send_confirm < 0xffff)
 		sae->send_confirm++;
+	sc = wpabuf_put(buf, 0);
+	wpabuf_put_le16(buf, sae->send_confirm);
 
 	if (sae->tmp->ec)
 		res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
diff --git a/src/common/sae.h b/src/common/sae.h
index 2243c0f..93fc5fb 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -122,7 +122,7 @@
 
 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
 		       const u8 *password, size_t password_len,
-		       const char *identifier, struct sae_data *sae);
+		       struct sae_data *sae);
 int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
 			  const u8 *addr1, const u8 *addr2,
 			  int *rejected_groups, const struct sae_pk *pk);
diff --git a/src/common/version.h b/src/common/version.h
index 0235c9b..4409e1c 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -9,6 +9,6 @@
 #define GIT_VERSION_STR_POSTFIX ""
 #endif /* GIT_VERSION_STR_POSTFIX */
 
-#define VERSION_STR "2.10-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
+#define VERSION_STR "2.11-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
 
 #endif /* VERSION_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 2b8c7f6..b78db05 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -3226,6 +3226,16 @@
 			   pos[1] >= sizeof(struct ieee80211_vht_capabilities))
 		{
 			ie->vht_capabilities = pos + 2;
+		} else if (*pos == WLAN_EID_EXTENSION &&
+			   pos[1] >= 1 + IEEE80211_HE_CAPAB_MIN_LEN &&
+			   pos[2] == WLAN_EID_EXT_HE_CAPABILITIES) {
+			ie->he_capabilities = pos + 3;
+			ie->he_capab_len = pos[1] - 1;
+		} else if (*pos == WLAN_EID_EXTENSION &&
+			   pos[1] >= 1 +
+			   sizeof(struct ieee80211_he_6ghz_band_cap) &&
+			   pos[2] == WLAN_EID_EXT_HE_6GHZ_BAND_CAP) {
+			ie->he_6ghz_capabilities = pos + 3;
 		} else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
 			ie->qosinfo = pos[2];
 		} else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) {
@@ -3414,14 +3424,17 @@
  * @pasn_group: Finite Cyclic Group ID for PASN authentication
  * @wrapped_data_format: Format of the data in the Wrapped Data IE
  * @pubkey: A buffer holding the local public key. Can be NULL
+ * @compressed: In case pubkey is included, indicates if the public key is
+ *     compressed (only x coordinate is included) or not (both x and y
+ *     coordinates are included)
  * @comeback: A buffer holding the comeback token. Can be NULL
  * @after: If comeback is set, defined the comeback time in seconds. -1 to not
  *	include the Comeback After field (frames from non-AP STA).
  */
 void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
 			       u8 wrapped_data_format,
-			       struct wpabuf *pubkey,
-			       struct wpabuf *comeback, int after)
+			       const struct wpabuf *pubkey, bool compressed,
+			       const struct wpabuf *comeback, int after)
 {
 	struct pasn_parameter_ie *params;
 
@@ -3460,13 +3473,22 @@
 
 		/*
 		 * 2 octets for the finite cyclic group + 2 octets public key
-		 * length + the actual key
+		 * length + 1 octet for the compressed/uncompressed indication +
+		 * the actual key.
 		 */
-		params->len += 2 + 1 + wpabuf_len(pubkey);
+		params->len += 2 + 1 + 1 + wpabuf_len(pubkey);
 		params->control |= WPA_PASN_CTRL_GROUP_AND_KEY_PRESENT;
 
 		wpabuf_put_le16(buf, pasn_group);
-		wpabuf_put_u8(buf, wpabuf_len(pubkey));
+
+		/*
+		 * The first octet indicates whether the public key is
+		 * compressed, as defined in RFC 5480 section 2.2.
+		 */
+		wpabuf_put_u8(buf, wpabuf_len(pubkey) + 1);
+		wpabuf_put_u8(buf, compressed ? WPA_PASN_PUBKEY_COMPRESSED_0 :
+			      WPA_PASN_PUBKEY_UNCOMPRESSED);
+
 		wpabuf_put_buf(buf, pubkey);
 	}
 }
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index c31e1a0..c28c55d 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -546,6 +546,11 @@
 	const u8 *pubkey;
 };
 
+/* See RFC 5480 section 2.2 */
+#define WPA_PASN_PUBKEY_COMPRESSED_0 0x02
+#define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
+#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
+
 int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
 		     int use_sha384);
 
@@ -592,6 +597,9 @@
 	size_t ext_supp_rates_len;
 	const u8 *ht_capabilities;
 	const u8 *vht_capabilities;
+	const u8 *he_capabilities;
+	size_t he_capab_len;
+	const u8 *he_6ghz_capabilities;
 	const u8 *supp_channels;
 	size_t supp_channels_len;
 	const u8 *supp_oper_classes;
@@ -655,8 +663,8 @@
 
 void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
 			       u8 wrapped_data_format,
-			       struct wpabuf *pubkey,
-			       struct wpabuf *comeback, int after);
+			       const struct wpabuf *pubkey, bool compressed,
+			       const struct wpabuf *comeback, int after);
 
 int wpa_pasn_add_wrapped_data(struct wpabuf *buf,
 			      struct wpabuf *wrapped_data_buf);
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 126a789..3d3a62a 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -126,6 +126,10 @@
 #define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT "
 /** Frequency ranges that the driver recommends to avoid */
 #define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ "
+/** A new network profile was added (followed by network entry id) */
+#define WPA_EVENT_NETWORK_ADDED "CTRL-EVENT-NETWORK-ADDED "
+/** A network profile was removed (followed by prior network entry id) */
+#define WPA_EVENT_NETWORK_REMOVED "CTRL-EVENT-NETWORK-REMOVED "
 /** Result of MSCS setup */
 #define WPA_EVENT_MSCS_RESULT "CTRL-EVENT-MSCS-RESULT "
 /** WPS overlap detected in PBC mode */
@@ -157,6 +161,10 @@
 #define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
 
 #define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK "
+/** Result of SCS setup */
+#define WPA_EVENT_SCS_RESULT "CTRL-EVENT-SCS-RESULT "
+/* Event indicating DSCP policy */
+#define WPA_EVENT_DSCP_POLICY "CTRL-EVENT-DSCP-POLICY "
 
 /* WPS ER events */
 #define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
@@ -204,6 +212,7 @@
 #define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT "
 #define DPP_EVENT_CSR "DPP-CSR "
 #define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
+#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
 
 /* MESH events */
 #define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 7d2ebd6..e6150b0 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -495,6 +495,13 @@
  */
 int crypto_get_random(void *buf, size_t len);
 
+/**
+ * crypto_pkcs7_get_certificates - Extract X.509 certificates from PKCS#7 data
+ * @pkcs7: DER encoded PKCS#7 data
+ * Returns: Buffer of the extracted PEM X.509 certificates or %NULL on failure
+ */
+struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7);
+
 
 /**
  * struct crypto_bignum - bignum
@@ -714,6 +721,14 @@
 struct crypto_ec;
 
 /**
+ * struct crypto_ec_point - Elliptic curve point
+ *
+ * Internal data structure for EC implementation to represent a point. The
+ * contents is specific to the used crypto library.
+ */
+struct crypto_ec_point;
+
+/**
  * crypto_ec_init - Initialize elliptic curve context
  * @group: Identifying number for the ECC group (IANA "Group Description"
  *	attribute registrty for RFC 2409)
@@ -762,16 +777,26 @@
  */
 const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e);
 
+/**
+ * crypto_ec_get_a - Get 'a' coefficient of an EC group's curve
+ * @e: EC context from crypto_ec_init()
+ * Returns: 'a' coefficient (bignum) of the group
+ */
 const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e);
+
+/**
+ * crypto_ec_get_b - Get 'b' coeffiecient of an EC group's curve
+ * @e: EC context from crypto_ec_init()
+ * Returns: 'b' coefficient (bignum) of the group
+ */
 const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e);
 
 /**
- * struct crypto_ec_point - Elliptic curve point
- *
- * Internal data structure for EC implementation to represent a point. The
- * contents is specific to the used crypto library.
+ * crypto_ec_get_generator - Get generator point of the EC group's curve
+ * @e: EC context from crypto_ec_init()
+ * Returns: Pointer to generator point
  */
-struct crypto_ec_point;
+const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e);
 
 /**
  * crypto_ec_point_init - Initialize data for an EC point
@@ -858,18 +883,6 @@
 int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p);
 
 /**
- * crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate
- * @e: EC context from crypto_ec_init()
- * @p: EC point to use for the returning the result
- * @x: x coordinate
- * @y_bit: y-bit (0 or 1) for selecting the y value to use
- * Returns: 0 on success, -1 on failure
- */
-int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
-				  struct crypto_ec_point *p,
-				  const struct crypto_bignum *x, int y_bit);
-
-/**
  * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b
  * @e: EC context from crypto_ec_init()
  * @x: x coordinate
@@ -909,25 +922,357 @@
 			const struct crypto_ec_point *a,
 			const struct crypto_ec_point *b);
 
-struct crypto_ecdh;
+/**
+ * crypto_ec_point_debug_print - Dump EC point to debug log
+ * @e: EC context from crypto_ec_init()
+ * @p: EC point
+ * @title: Name of the EC point in the trace
+ */
+void crypto_ec_point_debug_print(const struct crypto_ec *e,
+				 const struct crypto_ec_point *p,
+				 const char *title);
 
-struct crypto_ecdh * crypto_ecdh_init(int group);
-struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y);
-struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
-					const u8 *key, size_t len);
-void crypto_ecdh_deinit(struct crypto_ecdh *ecdh);
-size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh);
-
+/**
+ * struct crypto_ec_key - Elliptic curve key pair
+ *
+ * Internal data structure for EC key pair. The contents is specific to the used
+ * crypto library.
+ */
 struct crypto_ec_key;
 
+/**
+ * struct crypto_ecdh - Elliptic Curve Diffie–Hellman context
+ *
+ * Internal data structure for ECDH. The contents is specific to the used
+ * crypto library.
+ */
+struct crypto_ecdh;
+
+/**
+ * crypto_ecdh_init - Initialize elliptic curve Diffie–Hellman context
+ * @group: Identifying number for the ECC group (IANA "Group Description"
+ *	attribute registry for RFC 2409)
+ * This function generates an ephemeral key pair.
+ * Returns: Pointer to ECDH context or %NULL on failure
+ */
+struct crypto_ecdh * crypto_ecdh_init(int group);
+
+/**
+ * crypto_ecdh_init2 - Initialize elliptic curve Diffie–Hellman context with a
+ * given EC key
+ * @group: Identifying number for the ECC group (IANA "Group Description"
+ *	attribute registry for RFC 2409)
+ * @own_key: Our own EC Key
+ * Returns: Pointer to ECDH context or %NULL on failure
+ */
+struct crypto_ecdh * crypto_ecdh_init2(int group,
+				       struct crypto_ec_key *own_key);
+
+/**
+ * crypto_ecdh_get_pubkey - Retrieve public key from ECDH context
+ * @ecdh: ECDH context from crypto_ecdh_init() or crypto_ecdh_init2()
+ * @inc_y: Whether public key should include y coordinate (explicit form)
+ * or not (compressed form)
+ * Returns: Binary data f the public key or %NULL on failure
+ */
+struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y);
+
+/**
+ * crypto_ecdh_set_peerkey - Compute ECDH secret
+ * @ecdh: ECDH context from crypto_ecdh_init() or crypto_ecdh_init2()
+ * @inc_y: Whether peer's public key includes y coordinate (explicit form)
+ * or not (compressed form)
+ * @key: Binary data of the peer's public key
+ * @len: Length of the @key buffer
+ * Returns: Binary data with the EDCH secret or %NULL on failure
+ */
+struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
+					const u8 *key, size_t len);
+
+/**
+ * crypto_ecdh_deinit - Free ECDH context
+ * @ecdh: ECDH context from crypto_ecdh_init() or crypto_ecdh_init2()
+ */
+void crypto_ecdh_deinit(struct crypto_ecdh *ecdh);
+
+/**
+ * crypto_ecdh_prime_len - Get length of the prime in octets
+ * @e: ECDH context from crypto_ecdh_init()
+ * Returns: Length of the prime defining the group
+ */
+size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh);
+
+/**
+ * crypto_ec_key_parse_priv - Initialize EC key pair from ECPrivateKey ASN.1
+ * @der: DER encoding of ASN.1 ECPrivateKey
+ * @der_len: Length of @der buffer
+ * Returns: EC key or %NULL on failure
+ */
 struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len);
+
+/**
+ * crypto_ec_key_parse_pub - Initialize EC key pair from SubjectPublicKeyInfo ASN.1
+ * @der: DER encoding of ASN.1 SubjectPublicKeyInfo
+ * @der_len: Length of @der buffer
+ * Returns: EC key or %NULL on failure
+ */
 struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len);
+
+/**
+ * crypto_ec_key_set_pub - Initialize an EC public key from EC point coordinates
+ * @group: Identifying number for the ECC group
+ * @x: X coordinate of the public key
+ * @y: Y coordinate of the public key
+ * @len: Length of @x and @y buffer
+ * Returns: EC key or %NULL on failure
+ *
+ * This function initialize an EC key from public key coordinates, in big endian
+ * byte order padded to the length of the prime defining the group.
+ */
+struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x,
+					     const u8 *y, size_t len);
+
+/**
+ * crypto_ec_key_set_pub_point - Initialize an EC public key from EC point
+ * @e: EC context from crypto_ec_init()
+ * @pub: Public key point
+ * Returns: EC key or %NULL on failure
+ */
+struct crypto_ec_key *
+crypto_ec_key_set_pub_point(struct crypto_ec *e,
+			    const struct crypto_ec_point *pub);
+
+/**
+ * crypto_ec_key_gen - Generate EC key pair
+ * @group: Identifying number for the ECC group
+ * Returns: EC key or %NULL on failure
+ */
+struct crypto_ec_key * crypto_ec_key_gen(int group);
+
+/**
+ * crypto_ec_key_deinit - Free EC key
+ * @key: EC key from crypto_ec_key_parse_pub/priv() or crypto_ec_key_gen()
+ */
 void crypto_ec_key_deinit(struct crypto_ec_key *key);
+
+/**
+ * crypto_ec_key_get_subject_public_key - Get SubjectPublicKeyInfo ASN.1 for an EC key
+ * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen()
+ * Returns: Buffer with DER encoding of ASN.1 SubjectPublicKeyInfo or %NULL on failure
+ */
 struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key);
+
+/**
+ * crypto_ec_key_get_ecprivate_key - Get ECPrivateKey ASN.1 for a EC key
+ * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen()
+ * @include_pub: Whether to include public key in the ASN.1 sequence
+ * Returns: Buffer with DER encoding of ASN.1 ECPrivateKey or %NULL on failure
+ */
+struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
+						bool include_pub);
+
+/**
+ * crypto_ec_key_get_pubkey_point - Get public key point coordinates
+ * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv()
+ * @prefix: Whether output buffer should include the octet to indicate
+ * coordinate form (as defined for SubjectPublicKeyInfo)
+ * Returns: Buffer with coordinates of public key in uncompressed form or %NULL
+ * on failure
+ */
+struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
+					       int prefix);
+
+/**
+ * crypto_ec_key_get_public_key - Get EC public key as an EC point
+ * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv()
+ * Returns: Public key as an EC point or %NULL on failure
+ */
+const struct crypto_ec_point *
+crypto_ec_key_get_public_key(struct crypto_ec_key *key);
+
+/**
+ * crypto_ec_key_get_private_key - Get EC private key as a bignum
+ * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv()
+ * Returns: Private key as a bignum or %NULL on failure
+ */
+const struct crypto_bignum *
+crypto_ec_key_get_private_key(struct crypto_ec_key *key);
+
+/**
+ * crypto_ec_key_sign - Sign a buffer with an EC key
+ * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen()
+ * @data: Data to sign
+ * @len: Length of @data buffer
+ * Returns: Buffer with DER encoding of ASN.1 Ecdsa-Sig-Value or %NULL on failure
+ */
 struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
 				   size_t len);
+
+/**
+ * crypto_ec_key_sign_r_s - Sign a buffer with an EC key
+ * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen()
+ * @data: Data to sign
+ * @len: Length of @data buffer
+ * Returns: Buffer with the concatenated r and s values. Each value is in big
+ * endian byte order padded to the length of the prime defining the group of
+ * the key.
+ */
+struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
+				       const u8 *data, size_t len);
+
+/**
+ * crypto_ec_key_verify_signature - Verify ECDSA signature
+ * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_gen()
+ * @data: Data to be signed
+ * @len: Length of @data buffer
+ * @sig: DER encoding of ASN.1 Ecdsa-Sig-Value
+ * @sig_len: Length of @sig buffer
+ * Returns: 1 if signature is valid, 0 if signature is invalid and -1 on failure
+ */
 int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
 				   size_t len, const u8 *sig, size_t sig_len);
+
+/**
+ * crypto_ec_key_verify_signature_r_s - Verify signature
+ * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_gen()
+ * @data: Data to signed
+ * @len: Length of @data buffer
+ * @r: Binary data, in big endian byte order, of the 'r' field of the ECDSA
+ * signature.
+ * @s: Binary data, in big endian byte order, of the 's' field of the ECDSA
+ * signature.
+ * @r_len: Length of @r buffer
+ * @s_len: Length of @s buffer
+ * Returns: 1 if signature is valid, 0 if signature is invalid, or -1 on failure
+ */
+int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key,
+				       const u8 *data, size_t len,
+				       const u8 *r, size_t r_len,
+				       const u8 *s, size_t s_len);
+
+/**
+ * crypto_ec_key_group - Get IANA group identifier for an EC key
+ * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen()
+ * Returns: IANA group identifier and -1 on failure
+ */
 int crypto_ec_key_group(struct crypto_ec_key *key);
 
+/**
+ * crypto_ec_key_cmp - Compare two EC public keys
+ * @key1: Key 1
+ * @key2: Key 2
+ * Returns: 0 if public keys are identical, -1 otherwise
+ */
+int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2);
+
+/**
+ * crypto_ec_key_debug_print - Dump EC key to debug log
+ * @key:  EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen()
+ * @title: Name of the EC point in the trace
+ */
+void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
+			       const char *title);
+
+/**
+ * struct crypto_csr - Certification Signing Request
+ *
+ * Internal data structure for CSR. The contents is specific to the used
+ * crypto library.
+ * For now it is assumed that only an EC public key can be used
+ */
+struct crypto_csr;
+
+/**
+ * enum crypto_csr_name - CSR name type
+ */
+enum crypto_csr_name {
+	CSR_NAME_CN,
+	CSR_NAME_SN,
+	CSR_NAME_C,
+	CSR_NAME_O,
+	CSR_NAME_OU,
+};
+
+/**
+ * enum crypto_csr_attr - CSR attribute
+ */
+enum crypto_csr_attr {
+	CSR_ATTR_CHALLENGE_PASSWORD,
+};
+
+/**
+ * crypto_csr_init - Initialize empty CSR
+ * Returns: Pointer to CSR data or %NULL on failure
+ */
+struct crypto_csr * crypto_csr_init(void);
+
+/**
+ * crypto_csr_verify - Initialize CSR from CertificationRequest
+ * @req: DER encoding of ASN.1 CertificationRequest
+ *
+ * Returns: Pointer to CSR data or %NULL on failure or if signature is invalid
+ */
+struct crypto_csr * crypto_csr_verify(const struct wpabuf *req);
+
+/**
+ * crypto_csr_deinit - Free CSR structure
+ * @csr: CSR structure from @crypto_csr_init() or crypto_csr_verify()
+ */
+void crypto_csr_deinit(struct crypto_csr *csr);
+
+/**
+ * crypto_csr_set_ec_public_key - Set public key in CSR
+ * @csr: CSR structure from @crypto_csr_init()
+ * @key: EC public key to set as public key in the CSR
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_csr_set_ec_public_key(struct crypto_csr *csr,
+				 struct crypto_ec_key *key);
+
+/**
+ * crypto_csr_set_name - Set name entry in CSR SubjectName
+ * @csr: CSR structure from @crypto_csr_init()
+ * @type: Name type  to add into the CSR SubjectName
+ * @name: UTF-8 string to write in the CSR SubjectName
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
+			const char *name);
+
+/**
+ * crypto_csr_set_attribute - Set attribute in CSR
+ * @csr: CSR structure from @crypto_csr_init()
+ * @attr: Attribute identifier
+ * @attr_type: ASN.1 type of @value buffer
+ * @value: Attribute value
+ * @len: length of @value buffer
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
+			     int attr_type, const u8 *value, size_t len);
+
+/**
+ * crypto_csr_get_attribute - Get attribute from CSR
+ * @csr: CSR structure from @crypto_csr_verify()
+ * @attr: Updated with atribute identifier
+ * @len: Updated with length of returned buffer
+ * @type: ASN.1 type of the attribute buffer
+ * Returns: Type, length, and pointer on attribute value or %NULL on failure
+ */
+const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
+				    enum crypto_csr_attr attr,
+				    size_t *len, int *type);
+
+/**
+ * crypto_csr_sign - Sign CSR and return ASN.1 CertificationRequest
+ * @csr: CSR structure from @crypto_csr_init()
+ * @key: Private key to sign the CSR (for now ony EC key are supported)
+ * @algo: Hash algorithm to use for the signature
+ * Returns: DER encoding of ASN.1 CertificationRequest for the CSR or %NULL on
+ * failure
+ */
+struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
+				struct crypto_ec_key *key,
+				enum crypto_hash_alg algo);
+
 #endif /* CRYPTO_H */
diff --git a/src/crypto/crypto_internal-rsa.c b/src/crypto/crypto_internal-rsa.c
index dc7f350..0c5cead 100644
--- a/src/crypto/crypto_internal-rsa.c
+++ b/src/crypto/crypto_internal-rsa.c
@@ -14,7 +14,7 @@
 #include "tls/pkcs1.h"
 #include "tls/pkcs8.h"
 
-/* Dummy structures; these are just typecast to struct crypto_rsa_key */
+/* Stub structures; these are just typecast to struct crypto_rsa_key */
 struct crypto_public_key;
 struct crypto_private_key;
 
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 72f93c1..82c8576 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -22,7 +22,11 @@
 #ifdef CONFIG_ECC
 #include <openssl/ec.h>
 #include <openssl/x509.h>
+#include <openssl/pem.h>
 #endif /* CONFIG_ECC */
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+#endif /* OpenSSL version >= 3.0 */
 
 #include "common.h"
 #include "utils/const_time.h"
@@ -81,6 +85,8 @@
 }
 
 
+#ifdef CONFIG_ECC
+
 static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
 {
 	if (pkey->type != EVP_PKEY_EC)
@@ -88,8 +94,52 @@
 	return pkey->pkey.ec;
 }
 
+
+static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+	sig->r = r;
+	sig->s = s;
+	return 1;
+}
+
+
+static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
+			   const BIGNUM **ps)
+{
+	if (pr)
+		*pr = sig->r;
+	if (ps)
+		*ps = sig->s;
+}
+
+#endif /* CONFIG_ECC */
+
+static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
+{
+	return ASN1_STRING_data((ASN1_STRING *) x);
+}
 #endif /* OpenSSL version < 1.1.0 */
 
+
+void openssl_load_legacy_provider(void)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	static bool loaded = false;
+	OSSL_PROVIDER *legacy;
+
+	if (loaded)
+		return;
+
+	legacy = OSSL_PROVIDER_load(NULL, "legacy");
+
+	if (legacy) {
+		OSSL_PROVIDER_load(NULL, "default");
+		loaded = true;
+	}
+#endif /* OpenSSL version >= 3.0 */
+}
+
+
 static BIGNUM * get_group5_prime(void)
 {
 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
@@ -196,6 +246,7 @@
 #ifndef CONFIG_FIPS
 int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
+	openssl_load_legacy_provider();
 	return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac);
 }
 #endif /* CONFIG_FIPS */
@@ -204,8 +255,10 @@
 int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
 {
 	u8 pkey[8], next, tmp;
-	int i;
-	DES_key_schedule ks;
+	int i, plen, ret = -1;
+	EVP_CIPHER_CTX *ctx;
+
+	openssl_load_legacy_provider();
 
 	/* Add parity bits to the key */
 	next = 0;
@@ -216,10 +269,19 @@
 	}
 	pkey[i] = next | 1;
 
-	DES_set_key((DES_cblock *) &pkey, &ks);
-	DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
-			DES_ENCRYPT);
-	return 0;
+	ctx = EVP_CIPHER_CTX_new();
+	if (ctx &&
+	    EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, pkey, NULL) == 1 &&
+	    EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
+	    EVP_EncryptUpdate(ctx, cypher, &plen, clear, 8) == 1 &&
+	    EVP_EncryptFinal_ex(ctx, &cypher[plen], &plen) == 1)
+		ret = 0;
+	else
+		wpa_printf(MSG_ERROR, "OpenSSL: DES encrypt failed");
+
+	if (ctx)
+		EVP_CIPHER_CTX_free(ctx);
+	return ret;
 }
 
 
@@ -235,10 +297,12 @@
 	int res = -1;
 	unsigned char skip_buf[16];
 
+	openssl_load_legacy_provider();
+
 	ctx = EVP_CIPHER_CTX_new();
 	if (!ctx ||
-	    !EVP_CIPHER_CTX_set_padding(ctx, 0) ||
 	    !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
+	    !EVP_CIPHER_CTX_set_padding(ctx, 0) ||
 	    !EVP_CIPHER_CTX_set_key_length(ctx, keylen) ||
 	    !EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1))
 		goto out;
@@ -698,8 +762,8 @@
 	}
 
 	if (!(ctx->enc = EVP_CIPHER_CTX_new()) ||
-	    !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) ||
 	    !EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) ||
+	    !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) ||
 	    !EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) ||
 	    !EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) {
 		if (ctx->enc)
@@ -709,8 +773,8 @@
 	}
 
 	if (!(ctx->dec = EVP_CIPHER_CTX_new()) ||
-	    !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) ||
 	    !EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) ||
+	    !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) ||
 	    !EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) ||
 	    !EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) {
 		EVP_CIPHER_CTX_free(ctx->enc);
@@ -1629,51 +1693,51 @@
 	BIGNUM *b;
 };
 
+
+static int crypto_ec_group_2_nid(int group)
+{
+	/* Map from IANA registry for IKE D-H groups to OpenSSL NID */
+	switch (group) {
+	case 19:
+		return NID_X9_62_prime256v1;
+	case 20:
+		return NID_secp384r1;
+	case 21:
+		return NID_secp521r1;
+	case 25:
+		return NID_X9_62_prime192v1;
+	case 26:
+		return NID_secp224r1;
+#ifdef NID_brainpoolP224r1
+	case 27:
+		return NID_brainpoolP224r1;
+#endif /* NID_brainpoolP224r1 */
+#ifdef NID_brainpoolP256r1
+	case 28:
+		return NID_brainpoolP256r1;
+#endif /* NID_brainpoolP256r1 */
+#ifdef NID_brainpoolP384r1
+	case 29:
+		return NID_brainpoolP384r1;
+#endif /* NID_brainpoolP384r1 */
+#ifdef NID_brainpoolP512r1
+	case 30:
+		return NID_brainpoolP512r1;
+#endif /* NID_brainpoolP512r1 */
+	default:
+		return -1;
+	}
+}
+
+
 struct crypto_ec * crypto_ec_init(int group)
 {
 	struct crypto_ec *e;
 	int nid;
 
-	/* Map from IANA registry for IKE D-H groups to OpenSSL NID */
-	switch (group) {
-	case 19:
-		nid = NID_X9_62_prime256v1;
-		break;
-	case 20:
-		nid = NID_secp384r1;
-		break;
-	case 21:
-		nid = NID_secp521r1;
-		break;
-	case 25:
-		nid = NID_X9_62_prime192v1;
-		break;
-	case 26:
-		nid = NID_secp224r1;
-		break;
-#ifdef NID_brainpoolP224r1
-	case 27:
-		nid = NID_brainpoolP224r1;
-		break;
-#endif /* NID_brainpoolP224r1 */
-#ifdef NID_brainpoolP256r1
-	case 28:
-		nid = NID_brainpoolP256r1;
-		break;
-#endif /* NID_brainpoolP256r1 */
-#ifdef NID_brainpoolP384r1
-	case 29:
-		nid = NID_brainpoolP384r1;
-		break;
-#endif /* NID_brainpoolP384r1 */
-#ifdef NID_brainpoolP512r1
-	case 30:
-		nid = NID_brainpoolP512r1;
-		break;
-#endif /* NID_brainpoolP512r1 */
-	default:
+	nid = crypto_ec_group_2_nid(group);
+	if (nid < 0)
 		return NULL;
-	}
 
 	e = os_zalloc(sizeof(*e));
 	if (e == NULL)
@@ -1764,6 +1828,13 @@
 }
 
 
+const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e)
+{
+	return (const struct crypto_ec_point *)
+		EC_GROUP_get0_generator(e->group);
+}
+
+
 void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
 {
 	if (clear)
@@ -1880,48 +1951,27 @@
 }
 
 
-int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
-				  struct crypto_ec_point *p,
-				  const struct crypto_bignum *x, int y_bit)
-{
-	if (TEST_FAIL())
-		return -1;
-	if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p,
-						     (const BIGNUM *) x, y_bit,
-						     e->bnctx) ||
-	    !EC_POINT_is_on_curve(e->group, (EC_POINT *) p, e->bnctx))
-		return -1;
-	return 0;
-}
-
-
 struct crypto_bignum *
 crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
 			      const struct crypto_bignum *x)
 {
-	BIGNUM *tmp, *tmp2, *y_sqr = NULL;
+	BIGNUM *tmp;
 
 	if (TEST_FAIL())
 		return NULL;
 
 	tmp = BN_new();
-	tmp2 = BN_new();
 
-	/* y^2 = x^3 + ax + b */
-	if (tmp && tmp2 &&
+	/* y^2 = x^3 + ax + b = (x^2 + a)x + b */
+	if (tmp &&
 	    BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
+	    BN_mod_add_quick(tmp, e->a, tmp, e->prime) &&
 	    BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
-	    BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) &&
-	    BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) &&
-	    BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) {
-		y_sqr = tmp2;
-		tmp2 = NULL;
-	}
+	    BN_mod_add_quick(tmp, tmp, e->b, e->prime))
+		return (struct crypto_bignum *) tmp;
 
 	BN_clear_free(tmp);
-	BN_clear_free(tmp2);
-
-	return (struct crypto_bignum *) y_sqr;
+	return NULL;
 }
 
 
@@ -1949,6 +1999,35 @@
 }
 
 
+void crypto_ec_point_debug_print(const struct crypto_ec *e,
+				 const struct crypto_ec_point *p,
+				 const char *title)
+{
+	BIGNUM *x, *y;
+	char *x_str = NULL, *y_str = NULL;
+
+	x = BN_new();
+	y = BN_new();
+	if (!x || !y ||
+	    EC_POINT_get_affine_coordinates_GFp(e->group, (const EC_POINT *) p,
+						x, y, e->bnctx) != 1)
+		goto fail;
+
+	x_str = BN_bn2hex(x);
+	y_str = BN_bn2hex(y);
+	if (!x_str || !y_str)
+		goto fail;
+
+	wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str);
+
+fail:
+	OPENSSL_free(x_str);
+	OPENSSL_free(y_str);
+	BN_free(x);
+	BN_free(y);
+}
+
+
 struct crypto_ecdh {
 	struct crypto_ec *ec;
 	EVP_PKEY *pkey;
@@ -2013,6 +2092,32 @@
 }
 
 
+struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key)
+{
+	struct crypto_ecdh *ecdh;
+
+	ecdh = os_zalloc(sizeof(*ecdh));
+	if (!ecdh)
+		goto fail;
+
+	ecdh->ec = crypto_ec_init(group);
+	if (!ecdh->ec)
+		goto fail;
+
+	ecdh->pkey = EVP_PKEY_new();
+	if (!ecdh->pkey ||
+	    EVP_PKEY_assign_EC_KEY(ecdh->pkey,
+				   EVP_PKEY_get1_EC_KEY((EVP_PKEY *) own_key))
+	    != 1)
+		goto fail;
+
+	return ecdh;
+fail:
+	crypto_ecdh_deinit(ecdh);
+	return NULL;
+}
+
+
 struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
 {
 	struct wpabuf *buf = NULL;
@@ -2184,83 +2289,348 @@
 }
 
 
-struct crypto_ec_key {
-	EVP_PKEY *pkey;
-	EC_KEY *eckey;
-};
-
-
 struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
 {
-	struct crypto_ec_key *key;
+	EVP_PKEY *pkey = NULL;
+	EC_KEY *eckey;
 
-	key = os_zalloc(sizeof(*key));
-	if (!key)
-		return NULL;
-
-	key->eckey = d2i_ECPrivateKey(NULL, &der, der_len);
-	if (!key->eckey) {
+	eckey = d2i_ECPrivateKey(NULL, &der, der_len);
+	if (!eckey) {
 		wpa_printf(MSG_INFO, "OpenSSL: d2i_ECPrivateKey() failed: %s",
 			   ERR_error_string(ERR_get_error(), NULL));
 		goto fail;
 	}
-	EC_KEY_set_conv_form(key->eckey, POINT_CONVERSION_COMPRESSED);
+	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
 
-	key->pkey = EVP_PKEY_new();
-	if (!key->pkey || EVP_PKEY_assign_EC_KEY(key->pkey, key->eckey) != 1) {
-		EC_KEY_free(key->eckey);
-		key->eckey = NULL;
+	pkey = EVP_PKEY_new();
+	if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
+		EC_KEY_free(eckey);
 		goto fail;
 	}
 
-	return key;
+	return (struct crypto_ec_key *) pkey;
 fail:
-	crypto_ec_key_deinit(key);
+	crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
 	return NULL;
 }
 
 
 struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
 {
-	struct crypto_ec_key *key;
+	EVP_PKEY *pkey;
 
-	key = os_zalloc(sizeof(*key));
-	if (!key)
-		return NULL;
-
-	key->pkey = d2i_PUBKEY(NULL, &der, der_len);
-	if (!key->pkey) {
+	pkey = d2i_PUBKEY(NULL, &der, der_len);
+	if (!pkey) {
 		wpa_printf(MSG_INFO, "OpenSSL: d2i_PUBKEY() failed: %s",
 			   ERR_error_string(ERR_get_error(), NULL));
 		goto fail;
 	}
 
-	key->eckey = EVP_PKEY_get0_EC_KEY(key->pkey);
-	if (!key->eckey)
+	/* Ensure this is an EC key */
+	if (!EVP_PKEY_get0_EC_KEY(pkey))
 		goto fail;
-	return key;
+	return (struct crypto_ec_key *) pkey;
 fail:
-	crypto_ec_key_deinit(key);
+	crypto_ec_key_deinit((struct crypto_ec_key *) pkey);
 	return NULL;
 }
 
 
+struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *buf_x,
+					     const u8 *buf_y, size_t len)
+{
+	EC_KEY *eckey = NULL;
+	EVP_PKEY *pkey = NULL;
+	EC_GROUP *ec_group = NULL;
+	BN_CTX *ctx;
+	EC_POINT *point = NULL;
+	BIGNUM *x = NULL, *y = NULL;
+	int nid;
+
+	if (!buf_x || !buf_y)
+		return NULL;
+
+	nid = crypto_ec_group_2_nid(group);
+	if (nid < 0) {
+		wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
+		return NULL;
+	}
+
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto fail;
+
+	ec_group = EC_GROUP_new_by_curve_name(nid);
+	if (!ec_group)
+		goto fail;
+
+	x = BN_bin2bn(buf_x, len, NULL);
+	y = BN_bin2bn(buf_y, len, NULL);
+	point = EC_POINT_new(ec_group);
+	if (!x || !y || !point)
+		goto fail;
+
+	if (!EC_POINT_set_affine_coordinates_GFp(ec_group, point, x, y, ctx)) {
+		wpa_printf(MSG_ERROR,
+			   "OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		goto fail;
+	}
+
+	if (!EC_POINT_is_on_curve(ec_group, point, ctx) ||
+	    EC_POINT_is_at_infinity(ec_group, point)) {
+		wpa_printf(MSG_ERROR, "OpenSSL: Invalid point");
+		goto fail;
+	}
+
+	eckey = EC_KEY_new();
+	if (!eckey ||
+	    EC_KEY_set_group(eckey, ec_group) != 1 ||
+	    EC_KEY_set_public_key(eckey, point) != 1) {
+		wpa_printf(MSG_ERROR,
+			   "OpenSSL: Failed to set EC_KEY: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		goto fail;
+	}
+	EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
+
+	pkey = EVP_PKEY_new();
+	if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
+		wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
+		goto fail;
+	}
+
+out:
+	EC_GROUP_free(ec_group);
+	BN_free(x);
+	BN_free(y);
+	EC_POINT_free(point);
+	BN_CTX_free(ctx);
+	return (struct crypto_ec_key *) pkey;
+
+fail:
+	EC_KEY_free(eckey);
+	EVP_PKEY_free(pkey);
+	pkey = NULL;
+	goto out;
+}
+
+
+struct crypto_ec_key *
+crypto_ec_key_set_pub_point(struct crypto_ec *ec,
+			    const struct crypto_ec_point *pub)
+{
+	EC_KEY *eckey;
+	EVP_PKEY *pkey = NULL;
+
+	eckey = EC_KEY_new();
+	if (!eckey ||
+	    EC_KEY_set_group(eckey, ec->group) != 1 ||
+	    EC_KEY_set_public_key(eckey, (const EC_POINT *) pub) != 1) {
+		wpa_printf(MSG_ERROR,
+			   "OpenSSL: Failed to set EC_KEY: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		goto fail;
+	}
+	EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
+
+	pkey = EVP_PKEY_new();
+	if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
+		wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY");
+		goto fail;
+	}
+
+out:
+	return (struct crypto_ec_key *) pkey;
+
+fail:
+	EVP_PKEY_free(pkey);
+	EC_KEY_free(eckey);
+	pkey = NULL;
+	goto out;
+}
+
+
+struct crypto_ec_key * crypto_ec_key_gen(int group)
+{
+	EVP_PKEY_CTX *kctx = NULL;
+	EC_KEY *ec_params = NULL, *eckey;
+	EVP_PKEY *params = NULL, *key = NULL;
+	int nid;
+
+	nid = crypto_ec_group_2_nid(group);
+	if (nid < 0) {
+		wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group);
+		return NULL;
+	}
+
+	ec_params = EC_KEY_new_by_curve_name(nid);
+	if (!ec_params) {
+		wpa_printf(MSG_ERROR,
+			   "OpenSSL: Failed to generate EC_KEY parameters");
+		goto fail;
+	}
+	EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
+	params = EVP_PKEY_new();
+	if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
+		wpa_printf(MSG_ERROR,
+			   "OpenSSL: Failed to generate EVP_PKEY parameters");
+		goto fail;
+	}
+
+	kctx = EVP_PKEY_CTX_new(params, NULL);
+	if (!kctx ||
+	    EVP_PKEY_keygen_init(kctx) != 1 ||
+	    EVP_PKEY_keygen(kctx, &key) != 1) {
+		wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EC key");
+		key = NULL;
+		goto fail;
+	}
+
+	eckey = EVP_PKEY_get1_EC_KEY(key);
+	if (!eckey) {
+		key = NULL;
+		goto fail;
+	}
+	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
+	EC_KEY_free(eckey);
+
+fail:
+	EC_KEY_free(ec_params);
+	EVP_PKEY_free(params);
+	EVP_PKEY_CTX_free(kctx);
+	return (struct crypto_ec_key *) key;
+}
+
+
 void crypto_ec_key_deinit(struct crypto_ec_key *key)
 {
-	if (key) {
-		EVP_PKEY_free(key->pkey);
-		os_free(key);
-	}
+	EVP_PKEY_free((EVP_PKEY *) key);
 }
 
 
+#ifdef OPENSSL_IS_BORINGSSL
+
+/* BoringSSL version of i2d_PUBKEY() always outputs public EC key using
+ * uncompressed form so define a custom function to export EC pubkey using
+ * the compressed format that is explicitly required for some protocols. */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+
+typedef struct {
+	/* AlgorithmIdentifier ecPublicKey with optional parameters present
+	 * as an OID identifying the curve */
+	X509_ALGOR *alg;
+	/* Compressed format public key per ANSI X9.63 */
+	ASN1_BIT_STRING *pub_key;
+} EC_COMP_PUBKEY;
+
+ASN1_SEQUENCE(EC_COMP_PUBKEY) = {
+	ASN1_SIMPLE(EC_COMP_PUBKEY, alg, X509_ALGOR),
+	ASN1_SIMPLE(EC_COMP_PUBKEY, pub_key, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(EC_COMP_PUBKEY);
+
+IMPLEMENT_ASN1_FUNCTIONS(EC_COMP_PUBKEY);
+
+#endif /* OPENSSL_IS_BORINGSSL */
+
+
 struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
 {
+#ifdef OPENSSL_IS_BORINGSSL
+	unsigned char *der = NULL;
+	int der_len;
+	const EC_KEY *eckey;
+	struct wpabuf *ret = NULL;
+	size_t len;
+	const EC_GROUP *group;
+	const EC_POINT *point;
+	BN_CTX *ctx;
+	EC_COMP_PUBKEY *pubkey = NULL;
+	int nid;
+
+	ctx = BN_CTX_new();
+	eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+	if (!ctx || !eckey)
+		goto fail;
+
+	group = EC_KEY_get0_group(eckey);
+	point = EC_KEY_get0_public_key(eckey);
+	if (!group || !point)
+		goto fail;
+	nid = EC_GROUP_get_curve_name(group);
+
+	pubkey = EC_COMP_PUBKEY_new();
+	if (!pubkey ||
+	    X509_ALGOR_set0(pubkey->alg, OBJ_nid2obj(EVP_PKEY_EC),
+			    V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
+		goto fail;
+
+	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
+				 NULL, 0, ctx);
+	if (len == 0)
+		goto fail;
+
+	der = OPENSSL_malloc(len);
+	if (!der)
+		goto fail;
+	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
+				 der, len, ctx);
+
+	OPENSSL_free(pubkey->pub_key->data);
+	pubkey->pub_key->data = der;
+	der = NULL;
+	pubkey->pub_key->length = len;
+	/* No unused bits */
+	pubkey->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+	pubkey->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+	der_len = i2d_EC_COMP_PUBKEY(pubkey, &der);
+	if (der_len <= 0) {
+		wpa_printf(MSG_ERROR,
+			   "BoringSSL: Failed to build DER encoded public key");
+		goto fail;
+	}
+
+	ret = wpabuf_alloc_copy(der, der_len);
+fail:
+	EC_COMP_PUBKEY_free(pubkey);
+	OPENSSL_free(der);
+	BN_CTX_free(ctx);
+	return ret;
+#else /* OPENSSL_IS_BORINGSSL */
 	unsigned char *der = NULL;
 	int der_len;
 	struct wpabuf *buf;
+	EC_KEY *eckey;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	EVP_PKEY *tmp;
+#endif /* OpenSSL version >= 3.0 */
 
-	der_len = i2d_PUBKEY(key->pkey, &der);
+	eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
+	if (!eckey)
+		return NULL;
+
+	/* For now, all users expect COMPRESSED form */
+	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	tmp = EVP_PKEY_new();
+	if (!tmp)
+		return NULL;
+	if (EVP_PKEY_set1_EC_KEY(tmp, eckey) != 1) {
+		EVP_PKEY_free(tmp);
+		return NULL;
+	}
+	key = (struct crypto_ec_key *) tmp;
+#endif /* OpenSSL version >= 3.0 */
+
+	der_len = i2d_PUBKEY((EVP_PKEY *) key, &der);
+	EC_KEY_free(eckey);
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+	EVP_PKEY_free(tmp);
+#endif /* OpenSSL version >= 3.0 */
 	if (der_len <= 0) {
 		wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s",
 			   ERR_error_string(ERR_get_error(), NULL));
@@ -2270,6 +2640,112 @@
 	buf = wpabuf_alloc_copy(der, der_len);
 	OPENSSL_free(der);
 	return buf;
+#endif /* OPENSSL_IS_BORINGSSL */
+}
+
+
+struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
+						bool include_pub)
+{
+	EC_KEY *eckey;
+	unsigned char *der = NULL;
+	int der_len;
+	struct wpabuf *buf;
+	unsigned int key_flags;
+
+	eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
+	if (!eckey)
+		return NULL;
+
+	key_flags = EC_KEY_get_enc_flags(eckey);
+	if (include_pub)
+		key_flags &= ~EC_PKEY_NO_PUBKEY;
+	else
+		key_flags |= EC_PKEY_NO_PUBKEY;
+	EC_KEY_set_enc_flags(eckey, key_flags);
+
+	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
+
+	der_len = i2d_ECPrivateKey(eckey, &der);
+	EC_KEY_free(eckey);
+	if (der_len <= 0)
+		return NULL;
+	buf = wpabuf_alloc_copy(der, der_len);
+	OPENSSL_free(der);
+
+	return buf;
+}
+
+
+struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
+					       int prefix)
+{
+	int len, res;
+	EC_KEY *eckey;
+	struct wpabuf *buf;
+	unsigned char *pos;
+
+	eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
+	if (!eckey)
+		return NULL;
+	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
+	len = i2o_ECPublicKey(eckey, NULL);
+	if (len <= 0) {
+		wpa_printf(MSG_ERROR,
+			   "OpenSSL: Failed to determine public key encoding length");
+		EC_KEY_free(eckey);
+		return NULL;
+	}
+
+	buf = wpabuf_alloc(len);
+	if (!buf) {
+		EC_KEY_free(eckey);
+		return NULL;
+	}
+
+	pos = wpabuf_put(buf, len);
+	res = i2o_ECPublicKey(eckey, &pos);
+	EC_KEY_free(eckey);
+	if (res != len) {
+		wpa_printf(MSG_ERROR,
+			   "OpenSSL: Failed to encode public key (res=%d/%d)",
+			   res, len);
+		wpabuf_free(buf);
+		return NULL;
+	}
+
+	if (!prefix) {
+		/* Remove 0x04 prefix if requested */
+		pos = wpabuf_mhead(buf);
+		os_memmove(pos, pos + 1, len - 1);
+		buf->used--;
+	}
+
+	return buf;
+}
+
+
+const struct crypto_ec_point *
+crypto_ec_key_get_public_key(struct crypto_ec_key *key)
+{
+	const EC_KEY *eckey;
+
+	eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+	if (!eckey)
+		return NULL;
+	return (const struct crypto_ec_point *) EC_KEY_get0_public_key(eckey);
+}
+
+
+const struct crypto_bignum *
+crypto_ec_key_get_private_key(struct crypto_ec_key *key)
+{
+	const EC_KEY *eckey;
+
+	eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+	if (!eckey)
+		return NULL;
+	return (const struct crypto_bignum *) EC_KEY_get0_private_key(eckey);
 }
 
 
@@ -2280,12 +2756,12 @@
 	struct wpabuf *sig_der;
 	size_t sig_len;
 
-	sig_len = EVP_PKEY_size(key->pkey);
+	sig_len = EVP_PKEY_size((EVP_PKEY *) key);
 	sig_der = wpabuf_alloc(sig_len);
 	if (!sig_der)
 		return NULL;
 
-	pkctx = EVP_PKEY_CTX_new(key->pkey, NULL);
+	pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL);
 	if (!pkctx ||
 	    EVP_PKEY_sign_init(pkctx) <= 0 ||
 	    EVP_PKEY_sign(pkctx, wpabuf_put(sig_der, 0), &sig_len,
@@ -2301,13 +2777,68 @@
 }
 
 
+struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
+				       const u8 *data, size_t len)
+{
+	const EC_GROUP *group;
+	const EC_KEY *eckey;
+	BIGNUM *prime = NULL;
+	ECDSA_SIG *sig = NULL;
+	const BIGNUM *r, *s;
+	u8 *r_buf, *s_buf;
+	struct wpabuf *buf;
+	const unsigned char *p;
+	int prime_len;
+
+	buf = crypto_ec_key_sign(key, data, len);
+	if (!buf)
+		return NULL;
+
+	/* Extract (r,s) from Ecdsa-Sig-Value */
+	eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+	if (!eckey)
+		goto fail;
+	group = EC_KEY_get0_group(eckey);
+	prime = BN_new();
+	if (!prime || !group ||
+	    !EC_GROUP_get_curve_GFp(group, prime, NULL, NULL, NULL))
+		goto fail;
+	prime_len = BN_num_bytes(prime);
+
+	p = wpabuf_head(buf);
+	sig = d2i_ECDSA_SIG(NULL, &p, wpabuf_len(buf));
+	if (!sig)
+		goto fail;
+	ECDSA_SIG_get0(sig, &r, &s);
+
+	/* Re-use wpabuf returned by crypto_ec_key_sign() */
+	buf->used = 0;
+	r_buf = wpabuf_put(buf, prime_len);
+	s_buf = wpabuf_put(buf, prime_len);
+	if (crypto_bignum_to_bin((const struct crypto_bignum *) r, r_buf,
+				 prime_len, prime_len) < 0 ||
+	    crypto_bignum_to_bin((const struct crypto_bignum *) s, s_buf,
+				 prime_len, prime_len) < 0)
+		goto fail;
+
+out:
+	BN_free(prime);
+	ECDSA_SIG_free(sig);
+	return buf;
+fail:
+	wpabuf_clear_free(buf);
+	buf = NULL;
+	goto out;
+}
+
+
 int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
 				   size_t len, const u8 *sig, size_t sig_len)
 {
 	EVP_PKEY_CTX *pkctx;
 	int ret;
 
-	pkctx = EVP_PKEY_CTX_new(key->pkey, NULL);
+	pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL);
 	if (!pkctx || EVP_PKEY_verify_init(pkctx) <= 0) {
 		EVP_PKEY_CTX_free(pkctx);
 		return -1;
@@ -2323,12 +2854,53 @@
 }
 
 
+int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key,
+				       const u8 *data, size_t len,
+				       const u8 *r, size_t r_len,
+				       const u8 *s, size_t s_len)
+{
+	ECDSA_SIG *sig;
+	BIGNUM *r_bn, *s_bn;
+	unsigned char *der = NULL;
+	int der_len;
+	int ret = -1;
+
+	r_bn = BN_bin2bn(r, r_len, NULL);
+	s_bn = BN_bin2bn(s, s_len, NULL);
+	sig = ECDSA_SIG_new();
+	if (!r_bn || !s_bn || !sig || ECDSA_SIG_set0(sig, r_bn, s_bn) != 1)
+		goto fail;
+	r_bn = NULL;
+	s_bn = NULL;
+
+	der_len = i2d_ECDSA_SIG(sig, &der);
+	if (der_len <= 0) {
+		wpa_printf(MSG_DEBUG,
+			   "OpenSSL: Could not DER encode signature");
+		goto fail;
+	}
+
+	ret = crypto_ec_key_verify_signature(key, data, len, der, der_len);
+
+fail:
+	OPENSSL_free(der);
+	BN_free(r_bn);
+	BN_free(s_bn);
+	ECDSA_SIG_free(sig);
+	return ret;
+}
+
+
 int crypto_ec_key_group(struct crypto_ec_key *key)
 {
+	const EC_KEY *eckey;
 	const EC_GROUP *group;
 	int nid;
 
-	group = EC_KEY_get0_group(key->eckey);
+	eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+	if (!eckey)
+		return -1;
+	group = EC_KEY_get0_group(eckey);
 	if (!group)
 		return -1;
 	nid = EC_GROUP_get_curve_name(group);
@@ -2339,8 +2911,334 @@
 		return 20;
 	case NID_secp521r1:
 		return 21;
+#ifdef NID_brainpoolP256r1
+	case NID_brainpoolP256r1:
+		return 28;
+#endif /* NID_brainpoolP256r1 */
+#ifdef NID_brainpoolP384r1
+	case NID_brainpoolP384r1:
+		return 29;
+#endif /* NID_brainpoolP384r1 */
+#ifdef NID_brainpoolP512r1
+	case NID_brainpoolP512r1:
+		return 30;
+#endif /* NID_brainpoolP512r1 */
 	}
+	wpa_printf(MSG_ERROR, "OpenSSL: Unsupported curve (nid=%d) in EC key",
+		   nid);
 	return -1;
 }
 
+
+int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2)
+{
+	if (EVP_PKEY_cmp((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1)
+		return -1;
+	return 0;
+}
+
+
+void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
+			       const char *title)
+{
+	BIO *out;
+	size_t rlen;
+	char *txt;
+	int res;
+
+	out = BIO_new(BIO_s_mem());
+	if (!out)
+		return;
+
+	EVP_PKEY_print_private(out, (EVP_PKEY *) key, 0, NULL);
+	rlen = BIO_ctrl_pending(out);
+	txt = os_malloc(rlen + 1);
+	if (txt) {
+		res = BIO_read(out, txt, rlen);
+		if (res > 0) {
+			txt[res] = '\0';
+			wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
+		}
+		os_free(txt);
+	}
+	BIO_free(out);
+}
+
+
+struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7)
+{
+#ifdef OPENSSL_IS_BORINGSSL
+	CBS pkcs7_cbs;
+#else /* OPENSSL_IS_BORINGSSL */
+	PKCS7 *p7 = NULL;
+	const unsigned char *p = wpabuf_head(pkcs7);
+#endif /* OPENSSL_IS_BORINGSSL */
+	STACK_OF(X509) *certs;
+	int i, num;
+	BIO *out = NULL;
+	size_t rlen;
+	struct wpabuf *pem = NULL;
+	int res;
+
+#ifdef OPENSSL_IS_BORINGSSL
+	certs = sk_X509_new_null();
+	if (!certs)
+		goto fail;
+	CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7));
+	if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
+		wpa_printf(MSG_INFO,
+			   "OpenSSL: Could not parse PKCS#7 object: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		goto fail;
+	}
+#else /* OPENSSL_IS_BORINGSSL */
+	p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7));
+	if (!p7) {
+		wpa_printf(MSG_INFO,
+			   "OpenSSL: Could not parse PKCS#7 object: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		goto fail;
+	}
+
+	switch (OBJ_obj2nid(p7->type)) {
+	case NID_pkcs7_signed:
+		certs = p7->d.sign->cert;
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		certs = p7->d.signed_and_enveloped->cert;
+		break;
+	default:
+		certs = NULL;
+		break;
+	}
+#endif /* OPENSSL_IS_BORINGSSL */
+
+	if (!certs || ((num = sk_X509_num(certs)) == 0)) {
+		wpa_printf(MSG_INFO,
+			   "OpenSSL: No certificates found in PKCS#7 object");
+		goto fail;
+	}
+
+	out = BIO_new(BIO_s_mem());
+	if (!out)
+		goto fail;
+
+	for (i = 0; i < num; i++) {
+		X509 *cert = sk_X509_value(certs, i);
+
+		PEM_write_bio_X509(out, cert);
+	}
+
+	rlen = BIO_ctrl_pending(out);
+	pem = wpabuf_alloc(rlen);
+	if (!pem)
+		goto fail;
+	res = BIO_read(out, wpabuf_put(pem, 0), rlen);
+	if (res <= 0) {
+		wpabuf_free(pem);
+		pem = NULL;
+		goto fail;
+	}
+	wpabuf_put(pem, res);
+
+fail:
+#ifdef OPENSSL_IS_BORINGSSL
+	if (certs)
+		sk_X509_pop_free(certs, X509_free);
+#else /* OPENSSL_IS_BORINGSSL */
+	PKCS7_free(p7);
+#endif /* OPENSSL_IS_BORINGSSL */
+	if (out)
+		BIO_free_all(out);
+
+	return pem;
+}
+
+
+struct crypto_csr * crypto_csr_init()
+{
+	return (struct crypto_csr *)X509_REQ_new();
+}
+
+
+struct crypto_csr * crypto_csr_verify(const struct wpabuf *req)
+{
+	X509_REQ *csr;
+	EVP_PKEY *pkey = NULL;
+	const u8 *der = wpabuf_head(req);
+
+	csr = d2i_X509_REQ(NULL, &der, wpabuf_len(req));
+	if (!csr)
+		return NULL;
+
+	pkey = X509_REQ_get_pubkey((X509_REQ *)csr);
+	if (!pkey)
+		goto fail;
+
+	if (X509_REQ_verify((X509_REQ *)csr, pkey) != 1)
+		goto fail;
+
+	return (struct crypto_csr *)csr;
+fail:
+	X509_REQ_free(csr);
+	return NULL;
+}
+
+
+void crypto_csr_deinit(struct crypto_csr *csr)
+{
+	X509_REQ_free((X509_REQ *)csr);
+}
+
+
+int crypto_csr_set_ec_public_key(struct crypto_csr *csr, struct crypto_ec_key *key)
+{
+	if (!X509_REQ_set_pubkey((X509_REQ *)csr, (EVP_PKEY *)key))
+		return -1;
+
+	return 0;
+}
+
+
+int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
+			const char *name)
+{
+	X509_NAME *n;
+	int nid;
+
+	switch (type) {
+	case CSR_NAME_CN:
+		nid = NID_commonName;
+		break;
+	case CSR_NAME_SN:
+		nid = NID_surname;
+		break;
+	case CSR_NAME_C:
+		nid = NID_countryName;
+		break;
+	case CSR_NAME_O:
+		nid = NID_organizationName;
+		break;
+	case CSR_NAME_OU:
+		nid = NID_organizationalUnitName;
+		break;
+	default:
+		return -1;
+	}
+
+	n = X509_REQ_get_subject_name((X509_REQ *) csr);
+	if (!n)
+		return -1;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+	if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8,
+					(unsigned char *) name,
+					os_strlen(name), -1, 0))
+		return -1;
+#else
+	if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8,
+					(const unsigned char *) name,
+					os_strlen(name), -1, 0))
+		return -1;
+#endif
+
+	return 0;
+}
+
+
+int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
+			     int attr_type, const u8 *value, size_t len)
+{
+	int nid;
+
+	switch (attr) {
+	case CSR_ATTR_CHALLENGE_PASSWORD:
+		nid = NID_pkcs9_challengePassword;
+		break;
+	default:
+		return -1;
+	}
+
+	if (!X509_REQ_add1_attr_by_NID((X509_REQ *) csr, nid, attr_type, value,
+				       len))
+		return -1;
+
+	return 0;
+}
+
+
+const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
+				    enum crypto_csr_attr attr,
+				    size_t *len, int *type)
+{
+	X509_ATTRIBUTE *attrib;
+	ASN1_TYPE *attrib_type;
+	ASN1_STRING *data;
+	int loc;
+	int nid;
+
+	switch (attr) {
+	case CSR_ATTR_CHALLENGE_PASSWORD:
+		nid = NID_pkcs9_challengePassword;
+		break;
+	default:
+		return NULL;
+	}
+
+	loc = X509_REQ_get_attr_by_NID((X509_REQ *) csr, nid, -1);
+	if (loc < 0)
+		return NULL;
+
+	attrib = X509_REQ_get_attr((X509_REQ *) csr, loc);
+	if (!attrib)
+		return NULL;
+
+	attrib_type = X509_ATTRIBUTE_get0_type(attrib, 0);
+	if (!attrib_type)
+		return NULL;
+	*type = ASN1_TYPE_get(attrib_type);
+	data = X509_ATTRIBUTE_get0_data(attrib, 0, *type, NULL);
+	if (!data)
+		return NULL;
+	*len = ASN1_STRING_length(data);
+	return ASN1_STRING_get0_data(data);
+}
+
+
+struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
+				struct crypto_ec_key *key,
+				enum crypto_hash_alg algo)
+{
+	const EVP_MD *sign_md;
+	struct wpabuf *buf;
+	unsigned char *der = NULL;
+	int der_len;
+
+	switch (algo) {
+	case CRYPTO_HASH_ALG_SHA256:
+		sign_md = EVP_sha256();
+		break;
+	case CRYPTO_HASH_ALG_SHA384:
+		sign_md = EVP_sha384();
+		break;
+	case CRYPTO_HASH_ALG_SHA512:
+		sign_md = EVP_sha512();
+		break;
+	default:
+		return NULL;
+	}
+
+	if (!X509_REQ_sign((X509_REQ *) csr, (EVP_PKEY *) key, sign_md))
+		return NULL;
+
+	der_len = i2d_X509_REQ((X509_REQ *) csr, &der);
+	if (der_len < 0)
+		return NULL;
+
+	buf = wpabuf_alloc_copy(der, der_len);
+	OPENSSL_free(der);
+
+	return buf;
+}
+
 #endif /* CONFIG_ECC */
diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c
index 2e4bf89..00ecf61 100644
--- a/src/crypto/crypto_wolfssl.c
+++ b/src/crypto/crypto_wolfssl.c
@@ -609,7 +609,7 @@
 #endif
 
 
-#ifdef CONFIG_WPS_NFC
+#ifdef CONFIG_WPS
 
 static const unsigned char RFC3526_PRIME_1536[] = {
 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
@@ -695,6 +695,8 @@
 }
 
 
+#ifdef CONFIG_WPS_NFC
+
 void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
 {
 	DhKey *ret = NULL;
@@ -736,6 +738,8 @@
 	return ret;
 }
 
+#endif /* CONFIG_WPS_NFC */
+
 
 struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
 				  const struct wpabuf *own_private)
@@ -772,7 +776,7 @@
 	XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
 }
 
-#endif /* CONFIG_WPS_NFC */
+#endif /* CONFIG_WPS */
 
 
 int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
@@ -1626,30 +1630,6 @@
 }
 
 
-int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
-				  struct crypto_ec_point *p,
-				  const struct crypto_bignum *x, int y_bit)
-{
-	byte buf[1 + 2 * MAX_ECC_BYTES];
-	int ret;
-	int prime_len = crypto_ec_prime_len(e);
-
-	if (TEST_FAIL())
-		return -1;
-
-	buf[0] = y_bit ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
-	ret = crypto_bignum_to_bin(x, buf + 1, prime_len, prime_len);
-	if (ret <= 0)
-		return -1;
-	ret = wc_ecc_import_point_der(buf, 1 + 2 * ret, e->key.idx,
-				      (ecc_point *) p);
-	if (ret != 0)
-		return -1;
-
-	return 0;
-}
-
-
 struct crypto_bignum *
 crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
 			      const struct crypto_bignum *x)
diff --git a/src/crypto/random.c b/src/crypto/random.c
index ca9c0c8..c569abd 100644
--- a/src/crypto/random.c
+++ b/src/crypto/random.c
@@ -49,9 +49,9 @@
 static u32 pool[POOL_WORDS];
 static unsigned int input_rotate = 0;
 static unsigned int pool_pos = 0;
-static u8 dummy_key[20];
+static u8 stub_key[20];
 #ifdef __linux__
-static size_t dummy_key_avail = 0;
+static size_t stub_key_avail = 0;
 static int random_fd = -1;
 #endif /* __linux__ */
 static unsigned int own_pool_ready = 0;
@@ -109,13 +109,13 @@
 	u32 buf[POOL_WORDS / 2];
 
 	/* First, add hash back to pool to make backtracking more difficult. */
-	hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) pool,
+	hmac_sha1(stub_key, sizeof(stub_key), (const u8 *) pool,
 		  sizeof(pool), hash);
 	random_mix_pool(hash, sizeof(hash));
 	/* Hash half the pool to extra data */
 	for (i = 0; i < POOL_WORDS / 2; i++)
 		buf[i] = pool[(pool_pos - i) & POOL_WORDS_MASK];
-	hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) buf,
+	hmac_sha1(stub_key, sizeof(stub_key), (const u8 *) buf,
 		  sizeof(buf), hash);
 	/*
 	 * Fold the hash to further reduce any potential output pattern.
@@ -234,7 +234,7 @@
 	 * some key derivation operations to proceed.
 	 */
 
-	if (dummy_key_avail == sizeof(dummy_key))
+	if (stub_key_avail == sizeof(stub_key))
 		return 1; /* Already initialized - good to continue */
 
 	/*
@@ -245,8 +245,8 @@
 	 */
 
 #ifdef CONFIG_GETRANDOM
-	res = getrandom(dummy_key + dummy_key_avail,
-			sizeof(dummy_key) - dummy_key_avail, GRND_NONBLOCK);
+	res = getrandom(stub_key + stub_key_avail,
+			sizeof(stub_key) - stub_key_avail, GRND_NONBLOCK);
 	if (res < 0) {
 		if (errno == ENOSYS) {
 			wpa_printf(MSG_DEBUG,
@@ -270,8 +270,8 @@
 			return -1;
 		}
 
-		res = read(fd, dummy_key + dummy_key_avail,
-			   sizeof(dummy_key) - dummy_key_avail);
+		res = read(fd, stub_key + stub_key_avail,
+			   sizeof(stub_key) - stub_key_avail);
 		if (res < 0) {
 			wpa_printf(MSG_ERROR,
 				   "random: Cannot read from /dev/random: %s",
@@ -282,10 +282,10 @@
 	}
 
 	wpa_printf(MSG_DEBUG, "random: Got %u/%u random bytes", (unsigned) res,
-		   (unsigned) (sizeof(dummy_key) - dummy_key_avail));
-	dummy_key_avail += res;
+		   (unsigned) (sizeof(stub_key) - stub_key_avail));
+	stub_key_avail += res;
 
-	if (dummy_key_avail == sizeof(dummy_key)) {
+	if (stub_key_avail == sizeof(stub_key)) {
 		if (own_pool_ready < MIN_READY_MARK)
 			own_pool_ready = MIN_READY_MARK;
 		random_write_entropy();
@@ -294,7 +294,7 @@
 
 	wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
 		   "random data available",
-		   (unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key));
+		   (unsigned) stub_key_avail, (unsigned) sizeof(stub_key));
 
 	if (own_pool_ready >= MIN_READY_MARK ||
 	    total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY) {
@@ -338,13 +338,13 @@
 {
 	ssize_t res;
 
-	if (dummy_key_avail == sizeof(dummy_key)) {
+	if (stub_key_avail == sizeof(stub_key)) {
 		random_close_fd();
 		return;
 	}
 
-	res = read(sock, dummy_key + dummy_key_avail,
-		   sizeof(dummy_key) - dummy_key_avail);
+	res = read(sock, stub_key + stub_key_avail,
+		   sizeof(stub_key) - stub_key_avail);
 	if (res < 0) {
 		wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
 			   "%s", strerror(errno));
@@ -353,10 +353,10 @@
 
 	wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from /dev/random",
 		   (unsigned) res,
-		   (unsigned) (sizeof(dummy_key) - dummy_key_avail));
-	dummy_key_avail += res;
+		   (unsigned) (sizeof(stub_key) - stub_key_avail));
+	stub_key_avail += res;
 
-	if (dummy_key_avail == sizeof(dummy_key)) {
+	if (stub_key_avail == sizeof(stub_key)) {
 		random_close_fd();
 		if (own_pool_ready < MIN_READY_MARK)
 			own_pool_ready = MIN_READY_MARK;
@@ -447,9 +447,9 @@
 
 #ifdef CONFIG_GETRANDOM
 	{
-		u8 dummy;
+		u8 stub;
 
-		if (getrandom(&dummy, 0, GRND_NONBLOCK) == 0 ||
+		if (getrandom(&stub, 0, GRND_NONBLOCK) == 0 ||
 		    errno != ENOSYS) {
 			wpa_printf(MSG_DEBUG,
 				   "random: getrandom() support available");
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 086dfb3..ba3ef80 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -984,6 +984,10 @@
 	const char *ciphers;
 
 	if (tls_openssl_ref_count == 0) {
+		void openssl_load_legacy_provider(void);
+
+		openssl_load_legacy_provider();
+
 		tls_global = context = tls_context_new(conf);
 		if (context == NULL)
 			return NULL;
@@ -3053,20 +3057,30 @@
 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
 	!defined(LIBRESSL_VERSION_NUMBER) && \
 	!defined(OPENSSL_IS_BORINGSSL)
-	if ((flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) &&
-	    SSL_get_security_level(ssl) >= 2) {
-		/*
-		 * Need to drop to security level 1 to allow TLS versions older
-		 * than 1.2 to be used when explicitly enabled in configuration.
-		 */
-		SSL_set_security_level(conn->ssl, 1);
+	{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+		int need_level = 0;
+#else
+		int need_level = 1;
+#endif
+
+		if ((flags &
+		     (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) &&
+		    SSL_get_security_level(ssl) > need_level) {
+			/*
+			 * Need to drop to security level 1 (or 0  with OpenSSL
+			 * 3.0) to allow TLS versions older than 1.2 to be used
+			 * when explicitly enabled in configuration.
+			 */
+			SSL_set_security_level(conn->ssl, need_level);
+		}
 	}
 #endif
 
 #ifdef CONFIG_SUITEB
 #ifdef OPENSSL_IS_BORINGSSL
 	/* Start with defaults from BoringSSL */
-	SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, NULL, 0);
+	SSL_set_verify_algorithm_prefs(conn->ssl, NULL, 0);
 #endif /* OPENSSL_IS_BORINGSSL */
 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
 	if (flags & TLS_CONN_SUITEB_NO_ECDH) {
@@ -3120,7 +3134,7 @@
 #ifdef OPENSSL_IS_BORINGSSL
 		uint16_t sigalgs[1] = { SSL_SIGN_RSA_PKCS1_SHA384 };
 
-		if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
+		if (SSL_set_verify_algorithm_prefs(conn->ssl, sigalgs,
 						       1) != 1) {
 			wpa_printf(MSG_INFO,
 				   "OpenSSL: Failed to set Suite B sigalgs");
@@ -3158,7 +3172,7 @@
 			return -1;
 		}
 
-		if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
+		if (SSL_set_verify_algorithm_prefs(conn->ssl, sigalgs,
 						       1) != 1) {
 			wpa_printf(MSG_INFO,
 				   "OpenSSL: Failed to set Suite B sigalgs");
@@ -3811,6 +3825,7 @@
 				      const u8 *private_key_blob,
 				      size_t private_key_blob_len)
 {
+	BIO *bio;
 	int ok;
 
 	if (private_key == NULL && private_key_blob == NULL)
@@ -3856,6 +3871,28 @@
 			break;
 		}
 
+		bio = BIO_new_mem_buf((u8 *) private_key_blob,
+				      private_key_blob_len);
+		if (bio) {
+			EVP_PKEY *pkey;
+
+			pkey = PEM_read_bio_PrivateKey(
+				bio, NULL, tls_passwd_cb,
+				(void *) private_key_passwd);
+			if (pkey) {
+				if (SSL_use_PrivateKey(conn->ssl, pkey) == 1) {
+					wpa_printf(MSG_DEBUG,
+						   "OpenSSL: SSL_use_PrivateKey --> OK");
+					ok = 1;
+					EVP_PKEY_free(pkey);
+					BIO_free(bio);
+					break;
+				}
+				EVP_PKEY_free(pkey);
+			}
+			BIO_free(bio);
+		}
+
 		if (tls_read_pkcs12_blob(data, conn->ssl, private_key_blob,
 					 private_key_blob_len,
 					 private_key_passwd) == 0) {
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 5b2c71c..8b92e12 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -645,6 +645,12 @@
 	 */
 	unsigned int oce_scan:1;
 
+	/**
+	 * p2p_include_6ghz - Include 6 GHz channels for P2P full scan
+	 *
+	 */
+	unsigned int p2p_include_6ghz:1;
+
 	/*
 	 * NOTE: Whenever adding new parameters here, please make sure
 	 * wpa_scan_clone_params() and wpa_scan_free_params() get updated with
@@ -1197,6 +1203,12 @@
 	 * 2 = both hunting-and-pecking loop and hash-to-element enabled
 	 */
 	int sae_pwe;
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	/**
+	 * td_policy - Transition Disable Policy
+	 */
+	u32 td_policy;
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 };
 
 enum hide_ssid {
@@ -1584,6 +1596,7 @@
 #define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS	0x00000004
 #define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE		0x00000008
 #define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD	0x00000010
+#define WPA_DRIVER_MESH_CONF_FLAG_FORWARDING		0x00000020
 	/*
 	 * TODO: Other mesh configuration parameters would go here.
 	 * See NL80211_MESHCONF_* for all the mesh config parameters.
@@ -1593,6 +1606,7 @@
 	int peer_link_timeout;
 	int max_peer_links;
 	int rssi_threshold;
+	int forwarding;
 	u16 ht_opmode;
 };
 
@@ -1888,11 +1902,11 @@
  */
 #define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P		0x00002000
 /**
- * Driver is known to use sane error codes, i.e., when it indicates that
+ * Driver is known to use valid error codes, i.e., when it indicates that
  * something (e.g., association) fails, there was indeed a failure and the
  * operation does not end up getting completed successfully later.
  */
-#define WPA_DRIVER_FLAGS_SANE_ERROR_CODES		0x00004000
+#define WPA_DRIVER_FLAGS_VALID_ERROR_CODES		0x00004000
 /** Driver supports off-channel TX */
 #define WPA_DRIVER_FLAGS_OFFCHANNEL_TX			0x00008000
 /** Driver indicates TX status events for EAPOL Data frames */
@@ -2145,6 +2159,7 @@
 #define STA_DRV_DATA_TX_SHORT_GI BIT(6)
 #define STA_DRV_DATA_RX_SHORT_GI BIT(7)
 #define STA_DRV_DATA_LAST_ACK_RSSI BIT(8)
+#define STA_DRV_DATA_CONN_TIME BIT(9)
 
 struct hostap_sta_driver_data {
 	unsigned long rx_packets, tx_packets;
@@ -2154,6 +2169,7 @@
 	unsigned long current_tx_rate;
 	unsigned long current_rx_rate;
 	unsigned long inactive_msec;
+	unsigned long connected_sec;
 	unsigned long flags; /* bitfield of STA_DRV_DATA_* */
 	unsigned long num_ps_buf_frames;
 	unsigned long tx_retry_failed;
@@ -2392,6 +2408,7 @@
 	TDLS_PEER_HT = BIT(0),
 	TDLS_PEER_VHT = BIT(1),
 	TDLS_PEER_WMM = BIT(2),
+	TDLS_PEER_HE = BIT(3),
 };
 
 /* valid info in the wmm_params struct */
@@ -2484,6 +2501,9 @@
 	WPA_DRV_UPDATE_ASSOC_IES	= BIT(0),
 	WPA_DRV_UPDATE_FILS_ERP_INFO	= BIT(1),
 	WPA_DRV_UPDATE_AUTH_TYPE	= BIT(2),
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	WPA_DRV_UPDATE_TD_POLICY	= BIT(3),
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 };
 
 /**
@@ -4553,6 +4573,12 @@
 	 * explicitly allow reception of broadcast Public Action frames.
 	 */
 	int (*dpp_listen)(void *priv, bool enable);
+
+#ifdef CONFIG_TESTING_OPTIONS
+	int (*register_frame)(void *priv, u16 type,
+			      const u8 *match, size_t match_len,
+			      bool multicast);
+#endif /* CONFIG_TESTING_OPTIONS */
 };
 
 /**
@@ -5112,6 +5138,15 @@
 	 * is required to provide more details of the frame.
 	 */
 	EVENT_UNPROT_BEACON,
+
+	/**
+	 * EVENT_TX_WAIT_EXPIRE - TX wait timed out
+	 *
+	 * This event is used to indicate when the driver has completed
+	 * wait for a response frame based on a TX request that specified a
+	 * non-zero wait time and that has not been explicitly cancelled.
+	 */
+	EVENT_TX_WAIT_EXPIRE,
 };
 
 
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index a7ebe95..741521c 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -90,6 +90,7 @@
 	E2S(WDS_STA_INTERFACE_STATUS);
 	E2S(UPDATE_DH);
 	E2S(UNPROT_BEACON);
+	E2S(TX_WAIT_EXPIRE);
 	}
 
 	return "UNKNOWN";
@@ -268,7 +269,7 @@
 	DF2S(P2P_CAPABLE);
 	DF2S(AP_TEARDOWN_SUPPORT);
 	DF2S(P2P_MGMT_AND_NON_P2P);
-	DF2S(SANE_ERROR_CODES);
+	DF2S(VALID_ERROR_CODES);
 	DF2S(OFFCHANNEL_TX);
 	DF2S(EAPOL_TX_STATUS);
 	DF2S(DEAUTH_TX_STATUS);
diff --git a/src/drivers/driver_hostap.h b/src/drivers/driver_hostap.h
index 4c1e6d6..ac0b83a 100644
--- a/src/drivers/driver_hostap.h
+++ b/src/drivers/driver_hostap.h
@@ -55,8 +55,6 @@
 	PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
 	PRISM2_PARAM_HOST_ENCRYPT = 17,
 	PRISM2_PARAM_HOST_DECRYPT = 18,
-	PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19,
-	PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20,
 	PRISM2_PARAM_HOST_ROAMING = 21,
 	PRISM2_PARAM_BCRX_STA_KEY = 22,
 	PRISM2_PARAM_IEEE_802_1X = 23,
diff --git a/src/drivers/driver_macsec_qca.c b/src/drivers/driver_macsec_qca.c
index 928f024..54964f3 100644
--- a/src/drivers/driver_macsec_qca.c
+++ b/src/drivers/driver_macsec_qca.c
@@ -257,6 +257,33 @@
 }
 
 
+static int macsec_qca_secy_id_get(const char *ifname, u32 *secy_id)
+{
+#ifdef NSS_MACSEC_SECY_ID_GET_FUNC
+	/* Get secy id from nss macsec driver */
+	return nss_macsec_secy_id_get((u8 *) ifname, secy_id);
+#else /* NSS_MACSEC_SECY_ID_GET_FUNC */
+	/* Board specific settings */
+	if (os_strcmp(ifname, "eth2") == 0) {
+		*secy_id = 1;
+	} else if (os_strcmp(ifname, "eth3") == 0) {
+		*secy_id = 2;
+	} else if (os_strcmp(ifname, "eth4") == 0 ||
+		   os_strcmp(ifname, "eth0") == 0) {
+		*secy_id = 0;
+	} else if (os_strcmp(ifname, "eth5") == 0 ||
+		   os_strcmp(ifname, "eth1") == 0) {
+		*secy_id = 1;
+	} else {
+		*secy_id = -1;
+		return -1;
+	}
+
+	return 0;
+#endif /* NSS_MACSEC_SECY_ID_GET_FUNC */
+}
+
+
 static void * macsec_qca_init(void *ctx, const char *ifname)
 {
 	struct macsec_qca_data *drv;
@@ -265,13 +292,12 @@
 	if (drv == NULL)
 		return NULL;
 
-	/* Board specific settings */
-	if (os_memcmp("eth2", ifname, 4) == 0)
-		drv->secy_id = 1;
-	else if (os_memcmp("eth3", ifname, 4) == 0)
-		drv->secy_id = 2;
-	else
-		drv->secy_id = -1;
+	if (macsec_qca_secy_id_get(ifname, &drv->secy_id)) {
+		wpa_printf(MSG_ERROR,
+			   "macsec_qca: Failed to get secy_id for %s", ifname);
+		os_free(drv);
+		return NULL;
+	}
 
 	if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
 		os_free(drv);
@@ -303,17 +329,13 @@
 		return NULL;
 	}
 
-	/* Board specific settings */
-	if (os_memcmp("eth2", params->ifname, 4) == 0)
-		drv->secy_id = 1;
-	else if (os_memcmp("eth3", params->ifname, 4) == 0)
-		drv->secy_id = 2;
-	else if (os_memcmp("eth4", params->ifname, 4) == 0)
-		drv->secy_id = 0;
-	else if (os_memcmp("eth5", params->ifname, 4) == 0)
-		drv->secy_id = 1;
-	else
-		drv->secy_id = -1;
+	if (macsec_qca_secy_id_get(params->ifname, &drv->secy_id)) {
+		wpa_printf(MSG_ERROR,
+			   "macsec_qca: Failed to get secy_id for %s",
+			   params->ifname);
+		os_free(drv);
+		return NULL;
+	}
 
 	drv->common.ctx = hapd;
 	os_strlcpy(drv->common.ifname, params->ifname,
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index b5fff48..b32e009 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -1111,20 +1111,20 @@
 		auth_mode = Ndis802_11AuthModeOpen;
 		priv_mode = Ndis802_11PrivFilterAcceptAll;
 		if (params->wps == WPS_MODE_PRIVACY) {
-			u8 dummy_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
+			u8 stub_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
 			/*
 			 * Some NDIS drivers refuse to associate in open mode
 			 * configuration due to Privacy field mismatch, so use
 			 * a workaround to make the configuration look like
 			 * matching one for WPS provisioning.
 			 */
-			wpa_printf(MSG_DEBUG, "NDIS: Set dummy WEP key as a "
+			wpa_printf(MSG_DEBUG, "NDIS: Set stub WEP key as a "
 				   "workaround to allow driver to associate "
 				   "for WPS");
 			wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
 						bcast, 0, 1,
-						NULL, 0, dummy_key,
-						sizeof(dummy_key));
+						NULL, 0, stub_key,
+						sizeof(stub_key));
 		}
 #endif /* CONFIG_WPS */
 	} else {
@@ -2233,10 +2233,10 @@
 
 	/*
 	 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
-	 * descriptions. Fill in dummy descriptors to work around this.
+	 * descriptions. Fill in stub descriptors to work around this.
 	 */
 	while (num_desc < num_name)
-		desc[num_desc++] = "dummy description";
+		desc[num_desc++] = "stub description";
 
 	if (num_name != num_desc) {
 		wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
@@ -3164,10 +3164,10 @@
 
 	/*
 	 * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
-	 * descriptions. Fill in dummy descriptors to work around this.
+	 * descriptions. Fill in stub descriptors to work around this.
 	 */
 	while (num_desc < num_name)
-		desc[num_desc++] = "dummy description";
+		desc[num_desc++] = "stub description";
 
 	if (num_name != num_desc) {
 		wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5d4f71e..a2c4842 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -27,6 +27,7 @@
 #include "eloop.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
+#include "common/brcm_vendor.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/wpa_common.h"
@@ -198,7 +199,9 @@
 #endif /* CONFIG_MESH */
 static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
 			     u16 reason);
-
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+static int nl80211_set_td_policy(void *priv, u32 td_policy);
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 
 /* Converts nl80211_chan_width to a common format */
 enum chan_width convert2width(int width)
@@ -532,6 +535,22 @@
 }
 
 
+static int
+send_and_recv_msgs_connect_handle(struct wpa_driver_nl80211_data *drv,
+				  struct nl_msg *msg, struct i802_bss *bss,
+				  int set_owner)
+{
+	struct nl_sock *nl_connect = get_connect_handle(bss);
+
+	if (nl_connect)
+		return send_and_recv_msgs_owner(drv, msg, nl_connect, set_owner,
+						process_bss_event, bss, NULL,
+						NULL);
+	else
+		return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+}
+
+
 struct nl_sock * get_connect_handle(struct i802_bss *bss)
 {
 	if ((bss->drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) ||
@@ -589,7 +608,7 @@
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -ENOMEM;
-	if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
+	if (!genlmsg_put(msg, 0, 0, global->nlctrl_id,
 			 0, 0, CTRL_CMD_GETFAMILY, 0) ||
 	    nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
 		nlmsg_free(msg);
@@ -641,12 +660,10 @@
 
 
 static struct nl_msg *
-nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
-		    int flags, uint8_t cmd)
+nl80211_ifindex_msg_build(struct wpa_driver_nl80211_data *drv,
+			  struct nl_msg *msg, int ifindex, int flags,
+			  uint8_t cmd)
 {
-	struct nl_msg *msg;
-
-	msg = nlmsg_alloc();
 	if (!msg)
 		return NULL;
 
@@ -660,6 +677,15 @@
 }
 
 
+static struct nl_msg *
+nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
+		    int flags, uint8_t cmd)
+{
+	return nl80211_ifindex_msg_build(drv, nlmsg_alloc(), ifindex, flags,
+					 cmd);
+}
+
+
 struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
 				uint8_t cmd)
 {
@@ -1286,7 +1312,6 @@
 	} else if (ifi->ifi_flags & IFF_UP) {
 		/* Re-read MAC address as it may have changed */
 		nl80211_refresh_mac(drv, ifi->ifi_index, 1);
-		return;
 	}
 
 	/*
@@ -1865,6 +1890,13 @@
 		goto err;
 	}
 
+	global->nlctrl_id = genl_ctrl_resolve(global->nl, "nlctrl");
+	if (global->nlctrl_id < 0) {
+		wpa_printf(MSG_ERROR,
+			   "nl80211: 'nlctrl' generic netlink not found");
+		goto err;
+	}
+
 	global->nl_event = nl_create_handle(global->nl_cb, "event");
 	if (global->nl_event == NULL)
 		goto err;
@@ -2487,10 +2519,19 @@
 	    (nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0))
 		ret = -1;
 
+	/* Robust AV SCS Response */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x13\x01", 2) < 0)
+		ret = -1;
+
 	/* Robust AV MSCS Response */
 	if (nl80211_register_action_frame(bss, (u8 *) "\x13\x05", 2) < 0)
 		ret = -1;
 
+	/* Protected QoS Management Action frame */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x7e\x50\x6f\x9a\x1a",
+					  5) < 0)
+		ret = -1;
+
 	nl80211_mgmt_handle_register_eloop(bss);
 
 	return ret;
@@ -2828,8 +2869,8 @@
 				set_addr)))
 		return -1;
 
-	if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
-		drv->start_mode_ap = 1;
+	if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_STATION)
+		drv->start_mode_sta = 1;
 
 	if (drv->hostapd || bss->static_ap)
 		nlmode = NL80211_IFTYPE_AP;
@@ -2994,7 +3035,7 @@
 	}
 
 	if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
-		if (!drv->hostapd || !drv->start_mode_ap)
+		if (drv->start_mode_sta)
 			wpa_driver_nl80211_set_mode(bss,
 						    NL80211_IFTYPE_STATION);
 		nl80211_mgmt_unsubscribe(bss, "deinit");
@@ -3151,98 +3192,75 @@
 }
 
 #ifdef CONFIG_DRIVER_NL80211_BRCM
-static int wpa_driver_do_broadcom_acs(void *priv, struct drv_acs_params
-	*params)
+static int wpa_driver_do_broadcom_acs(struct wpa_driver_nl80211_data *drv,
+				      struct drv_acs_params *params)
 {
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
 	struct nlattr *data;
-	int  freq_list_len;
-	int  ret = 0;
-	do {
-		freq_list_len =
-			int_array_len(params->freq_list);
-		wpa_printf(MSG_DEBUG, "%s: freq_list_len=%d",
-				__FUNCTION__, freq_list_len);
-		msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
-		if (!msg) {
-			wpa_printf(MSG_ERROR, "%s: *errof, no memory for msg", __FUNCTION__);
-			return ret;
-		}
-		if ((nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, NL80211_ATTR_VENDOR_ID",
-					__FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
+	int freq_list_len;
+	int ret = -1;
 
-		if ((nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, BRCM_VENDOR_SCMD_ACS))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, NL80211_ATTR_VENDOR_SUBCMD",
-				__FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
-		if (!(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, NL80211_ATTR_VENDOR_DATA", __FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
-		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE, params->hw_mode))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, BRCM_VENDOR_ATTR_ACS_HW_MODE",
-				__FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
-		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT_ENABLED, params->ht_enabled))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, BRCM_VENDOR_ATTR_ACS_HT_ENABLED",
-				__FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
-		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED, params->ht40_enabled))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED",
-				__FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
-		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED, params->vht_enabled))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED",
-				__FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
-		if ((nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH, params->ch_width))) {
-			wpa_printf(MSG_ERROR, "%s: *errof, BRCM_VENDOR_ATTR_ACS_CHWIDTH",
-				__FUNCTION__);
-			nlmsg_free(msg);
-			return ret;
-		}
-		wpa_printf(MSG_DEBUG, "%s: ht40=%d, ch_width=%d\n",
-			__FUNCTION__, params->ht40_enabled, params->ch_width);
-		if ((freq_list_len > 0)	&& (nla_put(msg, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
-				sizeof(int) * freq_list_len, params->freq_list))) {
-			wpa_printf(MSG_ERROR, "%s: *error, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,"
-				"list_len=%d\n", __FUNCTION__, freq_list_len);
-			nlmsg_free(msg);
-			return ret;
-		}
-		nla_nest_end(msg, data);
-		wpa_printf(MSG_DEBUG, "nl80211: ACS Params: HW_MODE: %d HT: %d HT40:"
-			" %d VHT: %d BW: %d\n",
-			params->hw_mode, params->ht_enabled, params->ht40_enabled,
-			params->vht_enabled, params->ch_width);
-		ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
-		if (ret) {
-			wpa_printf(MSG_ERROR, "nl80211:	Failed to invoke vendor"
-				" driver ACS function: %s\n",
-				strerror(errno));
-		}
-	} while (0);
+	freq_list_len = int_array_len(params->freq_list);
+	wpa_printf(MSG_DEBUG, "%s: freq_list_len=%d",
+		    __func__, freq_list_len);
+
+	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+	if (!msg ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+			BRCM_VENDOR_SCMD_ACS) ||
+	    !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE, params->hw_mode) ||
+	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT_ENABLED,
+		       params->ht_enabled) ||
+	    nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED,
+		       params->ht40_enabled) ||
+		nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED,
+		       params->vht_enabled) ||
+	    nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH, params->ch_width) ||
+	    (freq_list_len > 0 &&
+	     nla_put(msg, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
+		     sizeof(int) * freq_list_len, params->freq_list)))
+		goto fail;
+	nla_nest_end(msg, data);
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d",
+		   params->hw_mode, params->ht_enabled, params->ht40_enabled,
+		   params->vht_enabled, params->ch_width);
+
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+	if (ret) {
+		wpa_printf(MSG_ERROR,
+			   "nl80211: BRCM Failed to invoke driver ACS function: %s",
+			   strerror(errno));
+	}
+
+	msg = NULL;
+fail:
+	nlmsg_free(msg);
 	return ret;
 }
 #endif /* CONFIG_DRIVER_NL80211_BRCM */
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+static int wpa_cross_akm_key_mgmt_to_suites(unsigned int key_mgmt_suites, u32 suites[],
+                        int max_suites)
+{
+    int num_suites = 0;
+
+#define __AKM_TO_SUITES_ARRAY(a, b) \
+    if (num_suites < max_suites && \
+        (key_mgmt_suites & (WPA_KEY_MGMT_ ## a))) \
+        suites[num_suites++] = (RSN_AUTH_KEY_MGMT_ ## b)
+    __AKM_TO_SUITES_ARRAY(PSK, PSK_OVER_802_1X);
+    __AKM_TO_SUITES_ARRAY(SAE, SAE);
+#undef __AKM_TO_SUITES_ARRAY
+
+    return num_suites;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
 #ifdef CONFIG_DRIVER_NL80211_QCA
 static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
 				  const u8 *key, size_t key_len)
@@ -3285,7 +3303,7 @@
 	if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM) ||
 	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
-				BRCM_VENDOR_SUBCMD_SET_PMK) ||
+				BRCM_VENDOR_SCMD_SET_PMK) ||
           !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
             nla_put(msg, BRCM_ATTR_DRIVER_KEY_PMK, key_len, key)) {
                 nl80211_nlmsg_clear(msg);
@@ -3675,10 +3693,11 @@
 int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
 			    const u8 *addr, int cmd, u16 reason_code,
 			    int local_state_change,
-			    struct nl_sock *nl_connect)
+			    struct i802_bss *bss)
 {
 	int ret;
 	struct nl_msg *msg;
+	struct nl_sock *nl_connect = get_connect_handle(bss);
 
 	if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
 	    nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
@@ -3690,8 +3709,8 @@
 	}
 
 	if (nl_connect)
-		ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL,
-				    NULL, NULL);
+		ret = send_and_recv(drv->global, nl_connect, msg,
+				    process_bss_event, bss, NULL, NULL);
 	else
 		ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
 	if (ret) {
@@ -3705,7 +3724,7 @@
 
 static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
 					 u16 reason_code,
-					 struct nl_sock *nl_connect)
+					 struct i802_bss *bss)
 {
 	int ret;
 	int drv_associated = drv->associated;
@@ -3714,7 +3733,7 @@
 	nl80211_mark_disconnected(drv);
 	/* Disconnect command doesn't need BSSID - it uses cached value */
 	ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
-				      reason_code, 0, nl_connect);
+				      reason_code, 0, bss);
 	/*
 	 * For locally generated disconnect, supplicant already generates a
 	 * DEAUTH event, so ignore the event from NL80211.
@@ -3737,14 +3756,13 @@
 		return nl80211_leave_ibss(drv, 1);
 	}
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
-		return wpa_driver_nl80211_disconnect(drv, reason_code,
-						     get_connect_handle(bss));
+		return wpa_driver_nl80211_disconnect(drv, reason_code, bss);
 	}
 	wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
 		   __func__, MAC2STR(addr), reason_code);
 	nl80211_mark_disconnected(drv);
 	ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
-				      reason_code, 0, get_connect_handle(bss));
+				      reason_code, 0, bss);
 	/*
 	 * For locally generated deauthenticate, supplicant already generates a
 	 * DEAUTH event, so ignore the event from NL80211.
@@ -4157,6 +4175,19 @@
 		}
 	}
 
+#ifdef CONFIG_PASN
+	if (is_sta_interface(drv->nlmode) &&
+	    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+	     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_DEAUTH) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: send_mlme: allow Deauthentication frame for PASN");
+
+		use_cookie = 0;
+		offchanok = 1;
+		goto send_frame_cmd;
+	}
+#endif /* CONFIG_PASN */
+
 	if (freq == 0 && drv->nlmode == NL80211_IFTYPE_ADHOC) {
 		freq = nl80211_get_assoc_freq(drv);
 		wpa_printf(MSG_DEBUG,
@@ -4169,7 +4200,7 @@
 		freq = bss->freq;
 	}
 
-	if (drv->use_monitor) {
+	if (drv->use_monitor && is_ap_interface(drv->nlmode)) {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor",
 			   freq, bss->freq);
@@ -4255,6 +4286,7 @@
 	struct nl_msg *acl;
 	unsigned int i;
 	int ret;
+	size_t acl_nla_sz, acl_nlmsg_sz, nla_sz, nlmsg_sz;
 
 	if (!(drv->capa.max_acl_mac_addrs))
 		return -ENOTSUP;
@@ -4265,7 +4297,9 @@
 	wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
 		   params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
 
-	acl = nlmsg_alloc();
+	acl_nla_sz = nla_total_size(ETH_ALEN) * params->num_mac_acl;
+	acl_nlmsg_sz = nlmsg_total_size(acl_nla_sz);
+	acl = nlmsg_alloc_size(acl_nlmsg_sz);
 	if (!acl)
 		return -ENOMEM;
 	for (i = 0; i < params->num_mac_acl; i++) {
@@ -4275,7 +4309,19 @@
 		}
 	}
 
-	if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MAC_ACL)) ||
+	/*
+	 * genetlink message header (Length of user header is 0) +
+	 * u32 attr: NL80211_ATTR_IFINDEX +
+	 * u32 attr: NL80211_ATTR_ACL_POLICY +
+	 * nested acl attr
+	 */
+	nla_sz = GENL_HDRLEN +
+		nla_total_size(4) * 2 +
+		nla_total_size(acl_nla_sz);
+	nlmsg_sz = nlmsg_total_size(nla_sz);
+	if (!(msg = nl80211_ifindex_msg_build(drv, nlmsg_alloc_size(nlmsg_sz),
+					      drv->ifindex, 0,
+					      NL80211_CMD_SET_MAC_ACL)) ||
 	    nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
 			NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
 			NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) ||
@@ -4893,8 +4939,7 @@
 		goto fail;
 #endif /* CONFIG_FILS */
 
-	ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1,
-				       NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
 			   ret, strerror(-ret));
@@ -5227,7 +5272,7 @@
 			/*
 			 * cfg80211 validates that AID is non-zero, so we have
 			 * to make this a non-zero value for the TDLS case where
-			 * a dummy STA entry is used for now and for a station
+			 * a stub STA entry is used for now and for a station
 			 * that is still not associated.
 			 */
 			wpa_printf(MSG_DEBUG, "  * aid=1 (%s workaround)",
@@ -5894,6 +5939,7 @@
 {
 	struct i802_bss *bss = priv;
 	struct nl_msg *msg;
+	int ret;
 
 	wpa_printf(MSG_DEBUG,
 		   "nl80211: Set STA airtime weight - ifname=%s addr=" MACSTR
@@ -5904,7 +5950,13 @@
 	    nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight))
 		goto fail;
 
-	return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
+	if (ret) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: SET_STATION[AIRTIME_WEIGHT] failed: ret=%d (%s)",
+			   ret, strerror(-ret));
+	}
+	return ret;
 fail:
 	nlmsg_free(msg);
 	return -ENOBUFS;
@@ -5948,9 +6000,7 @@
 	int ret;
 
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
-	ret = send_and_recv_msgs_owner(drv, msg,
-				       get_connect_handle(drv->first_bss), 1,
-				       NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
@@ -6008,6 +6058,14 @@
 	}
 #endif /* CONFIG_VHT_OVERRIDES */
 
+#ifdef CONFIG_HE_OVERRIDES
+	if (params->disable_he) {
+		wpa_printf(MSG_DEBUG, "  * HE disabled");
+		if (nla_put_flag(msg, NL80211_ATTR_DISABLE_HE))
+			return -1;
+	}
+#endif /* CONFIG_HE_OVERRIDES */
+
 	return 0;
 }
 
@@ -6082,9 +6140,7 @@
 	if (ret < 0)
 		goto fail;
 
-	ret = send_and_recv_msgs_owner(drv, msg,
-				       get_connect_handle(drv->first_bss), 1,
-				       NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
@@ -6345,6 +6401,22 @@
 			return -1;
 	}
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	if (IS_CROSS_AKM_ROAM_KEY_MGMT(params->key_mgmt_suite)) {
+		int num_suites;
+		u32 suites[NL80211_MAX_NR_AKM_SUITES];
+
+		wpa_printf(MSG_INFO, "nl80211: key_mgmt_suites=0x%x",
+			params->key_mgmt_suite);
+		num_suites = wpa_cross_akm_key_mgmt_to_suites(params->key_mgmt_suite,
+			suites, ARRAY_SIZE(suites));
+		if (num_suites &&
+			nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), suites)) {
+			wpa_printf(MSG_ERROR, "Updating multi akm_suite failed");
+			return -1;
+		}
+	}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 	if (params->req_handshake_offload &&
 	    (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) {
 		    wpa_printf(MSG_DEBUG, "  * WANT_1X_4WAY_HS");
@@ -6407,7 +6479,12 @@
 	    nl80211_put_fils_connect_params(drv, params, msg) != 0)
 		return -1;
 
-	if ((params->key_mgmt_suite == WPA_KEY_MGMT_SAE ||
+	if ((
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	     (params->key_mgmt_suite & WPA_KEY_MGMT_SAE) ||
+#else
+	     params->key_mgmt_suite == WPA_KEY_MGMT_SAE ||
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 	     params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) &&
 	    (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) &&
 	    nla_put_flag(msg, NL80211_ATTR_EXTERNAL_AUTH_SUPPORT))
@@ -6420,7 +6497,7 @@
 static int wpa_driver_nl80211_try_connect(
 	struct wpa_driver_nl80211_data *drv,
 	struct wpa_driver_associate_params *params,
-	struct nl_sock *nl_connect)
+	struct i802_bss *bss)
 {
 	struct nl_msg *msg;
 	enum nl80211_auth_type type;
@@ -6458,7 +6535,12 @@
 		goto fail;
 
 #ifdef CONFIG_SAE
-	if ((params->key_mgmt_suite == WPA_KEY_MGMT_SAE ||
+	if ((
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	     (params->key_mgmt_suite & WPA_KEY_MGMT_SAE) ||
+#else
+	     params->key_mgmt_suite == WPA_KEY_MGMT_SAE ||
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 	     params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) &&
 	    nl80211_put_sae_pwe(msg, params->sae_pwe) < 0)
 		goto fail;
@@ -6492,8 +6574,7 @@
 	if (ret)
 		goto fail;
 
-	ret = send_and_recv_msgs_owner(drv, msg, nl_connect, 1, NULL,
-				       NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
@@ -6517,7 +6598,7 @@
 static int wpa_driver_nl80211_connect(
 	struct wpa_driver_nl80211_data *drv,
 	struct wpa_driver_associate_params *params,
-	struct nl_sock *nl_connect)
+	struct i802_bss *bss)
 {
 	int ret;
 
@@ -6527,7 +6608,7 @@
 	else
 		os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
 
-	ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
+	ret = wpa_driver_nl80211_try_connect(drv, params, bss);
 	if (ret == -EALREADY) {
 		/*
 		 * cfg80211 does not currently accept new connections if
@@ -6538,9 +6619,9 @@
 			   "disconnecting before reassociation "
 			   "attempt");
 		if (wpa_driver_nl80211_disconnect(
-			    drv, WLAN_REASON_PREV_AUTH_NOT_VALID, nl_connect))
+			    drv, WLAN_REASON_PREV_AUTH_NOT_VALID, bss))
 			return -1;
-		ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
+		ret = wpa_driver_nl80211_try_connect(drv, params, bss);
 	}
 	return ret;
 }
@@ -6568,14 +6649,18 @@
 
 		if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
 			return -1;
-		if (params->key_mgmt_suite == WPA_KEY_MGMT_SAE ||
+		if (
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+		    (params->key_mgmt_suite & WPA_KEY_MGMT_SAE) ||
+#else
+		    params->key_mgmt_suite == WPA_KEY_MGMT_SAE ||
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 		    params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE)
 			bss->use_nl_connect = 1;
 		else
 			bss->use_nl_connect = 0;
 
-		return wpa_driver_nl80211_connect(drv, params,
-						  get_connect_handle(bss));
+		return wpa_driver_nl80211_connect(drv, params, bss);
 	}
 
 	nl80211_mark_disconnected(drv);
@@ -6610,9 +6695,7 @@
 			goto fail;
 	}
 
-	ret = send_and_recv_msgs_owner(drv, msg,
-				       get_connect_handle(drv->first_bss), 1,
-				       NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
 	msg = NULL;
 	if (ret) {
 		wpa_dbg(drv->ctx, MSG_DEBUG,
@@ -7103,6 +7186,7 @@
 		[NL80211_STA_INFO_ACK_SIGNAL] = { .type = NLA_U8 },
 		[NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 },
 		[NL80211_STA_INFO_TX_DURATION] = { .type = NLA_U64 },
+		[NL80211_STA_INFO_CONNECTED_TIME] = { .type = NLA_U32 },
 	};
 	struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
 	static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
@@ -7177,6 +7261,12 @@
 		data->flags |= STA_DRV_DATA_LAST_ACK_RSSI;
 	}
 
+	if (stats[NL80211_STA_INFO_CONNECTED_TIME]) {
+		data->connected_sec =
+			nla_get_u32(stats[NL80211_STA_INFO_CONNECTED_TIME]);
+		data->flags |= STA_DRV_DATA_CONN_TIME;
+	}
+
 	if (stats[NL80211_STA_INFO_TX_BITRATE] &&
 	    nla_parse_nested(rate, NL80211_RATE_INFO_MAX,
 			     stats[NL80211_STA_INFO_TX_BITRATE],
@@ -9281,6 +9371,28 @@
 
 #ifdef CONFIG_TDLS
 
+static int nl80211_add_peer_capab(struct nl_msg *msg,
+				  enum tdls_peer_capability capa)
+{
+	u32 peer_capab = 0;
+
+	if (!capa)
+		return 0;
+
+	if (capa & TDLS_PEER_HT)
+		peer_capab |= NL80211_TDLS_PEER_HT;
+	if (capa & TDLS_PEER_VHT)
+		peer_capab |= NL80211_TDLS_PEER_VHT;
+	if (capa & TDLS_PEER_WMM)
+		peer_capab |= NL80211_TDLS_PEER_WMM;
+	if (capa & TDLS_PEER_HE)
+		peer_capab |= NL80211_TDLS_PEER_HE;
+
+	return nla_put_u32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY,
+			   peer_capab);
+}
+
+
 static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
 				  u8 dialog_token, u16 status_code,
 				  u32 peer_capab, int initiator, const u8 *buf,
@@ -9300,21 +9412,9 @@
 	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
 	    nla_put_u8(msg, NL80211_ATTR_TDLS_ACTION, action_code) ||
 	    nla_put_u8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token) ||
-	    nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status_code))
-		goto fail;
-	if (peer_capab) {
-		/*
-		 * The internal enum tdls_peer_capability definition is
-		 * currently identical with the nl80211 enum
-		 * nl80211_tdls_peer_capability, so no conversion is needed
-		 * here.
-		 */
-		if (nla_put_u32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY,
-				peer_capab))
-			goto fail;
-	}
-	if ((initiator &&
-	     nla_put_flag(msg, NL80211_ATTR_TDLS_INITIATOR)) ||
+	    nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status_code) ||
+	    nl80211_add_peer_capab(msg, peer_capab) ||
+	    (initiator && nla_put_flag(msg, NL80211_ATTR_TDLS_INITIATOR)) ||
 	    nla_put(msg, NL80211_ATTR_IE, len, buf))
 		goto fail;
 
@@ -9856,11 +9956,18 @@
 	int csa_off_len = 0;
 	int i;
 
-	wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)",
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d%s%s%s)",
 		   settings->cs_count, settings->block_tx,
-		   settings->freq_params.freq, settings->freq_params.bandwidth,
+		   settings->freq_params.freq,
+		   settings->freq_params.channel,
+		   settings->freq_params.sec_channel_offset,
+		   settings->freq_params.bandwidth,
 		   settings->freq_params.center_freq1,
-		   settings->freq_params.center_freq2);
+		   settings->freq_params.center_freq2,
+		   settings->freq_params.ht_enabled ? " ht" : "",
+		   settings->freq_params.vht_enabled ? " vht" : "",
+		   settings->freq_params.he_enabled ? " he" : "");
 
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) {
 		wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
@@ -10458,7 +10565,7 @@
 		if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_VENDOR)) ||
 			nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM) ||
 			nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
-				BRCM_VENDOR_SUBCMD_SET_MAC) ||
+				BRCM_VENDOR_SCMD_SET_MAC) ||
 			!(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
 			nla_put(msg, BRCM_ATTR_DRIVER_MAC_ADDR, ETH_ALEN, addr)) {
 			wpa_printf(MSG_ERROR, "failed to put p2p randmac");
@@ -10550,6 +10657,9 @@
 	if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
 	     nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
 			params->auto_plinks)) ||
+	    ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_FORWARDING) &&
+	     nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
+			params->forwarding)) ||
 	    ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) &&
 	     nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
 			 params->max_peer_links)) ||
@@ -10634,8 +10744,7 @@
 	if (nl80211_put_mesh_config(msg, &params->conf) < 0)
 		goto fail;
 
-	ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1,
-				       NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
@@ -10692,17 +10801,18 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
-	ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 0,
-				       NULL, NULL, NULL, NULL);
+	ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 0);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
 			   ret, strerror(-ret));
 	} else {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: mesh leave request send successfully");
+		drv->first_bss->freq = 0;
 	}
 
-	if (wpa_driver_nl80211_set_mode(drv->first_bss,
+	if (drv->start_mode_sta &&
+	    wpa_driver_nl80211_set_mode(drv->first_bss,
 					NL80211_IFTYPE_STATION)) {
 		wpa_printf(MSG_INFO,
 			   "nl80211: Failed to set interface into station mode");
@@ -11062,7 +11172,8 @@
 		 * compatibility.
 		 */
 		if (!(freq >= 2412 && freq <= 2484) &&
-		    !(freq >= 5180 && freq <= 5900))
+		    !(freq >= 5180 && freq <= 5900) &&
+		    !(freq >= 5945 && freq <= 7115))
 			continue;
 		hw_mode = ieee80211_freq_to_chan(freq, &ch_list[num_channels]);
 		if (hw_mode != NUM_HOSTAPD_MODES)
@@ -11098,10 +11209,9 @@
 }
 
 
-static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
+static int nl80211_qca_do_acs(struct wpa_driver_nl80211_data *drv,
+			      struct drv_acs_params *params)
 {
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
 	struct nlattr *data;
 	int ret;
@@ -11777,6 +11887,26 @@
 
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
+static int nl80211_do_acs(void *priv, struct drv_acs_params *params)
+{
+#if defined(CONFIG_DRIVER_NL80211_QCA) || defined(CONFIG_DRIVER_NL80211_BRCM)
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+#endif /* CONFIG_DRIVER_NL80211_QCA || CONFIG_DRIVER_NL80211_BRCM */
+
+#ifdef CONFIG_DRIVER_NL80211_QCA
+	if (drv->qca_do_acs)
+		return nl80211_qca_do_acs(drv, params);
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	if (drv->brcm_do_acs)
+		return wpa_driver_do_broadcom_acs(drv, params);
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
+	return -1;
+}
+
 
 static int nl80211_write_to_file(const char *name, unsigned int val)
 {
@@ -11939,6 +12069,19 @@
 	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME)
 		return 0;
 
+	/* Handle any connection param update here which might receive kernel handling in future */
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	if (mask & WPA_DRV_UPDATE_TD_POLICY) {
+		ret = nl80211_set_td_policy(priv, params->td_policy);
+		if (ret) {
+			wpa_dbg(drv->ctx, MSG_DEBUG,
+				"nl80211: Update connect params command failed: ret=%d (%s)",
+				ret, strerror(-ret));
+		}
+		return ret;
+	}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_UPDATE_CONNECT_PARAMS);
 	if (!msg)
 		goto fail;
@@ -12092,6 +12235,81 @@
 }
 #endif /* CONFIG_DPP */
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+static int nl80211_set_td_policy(void *priv, u32 td_policy)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	int ret;
+	struct nlattr *params;
+
+	if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, BRCM_VENDOR_SCMD_SET_TD_POLICY) ||
+	    !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+	    (nla_put_u32(msg, BRCM_ATTR_DRIVER_TD_POLICY, td_policy))) {
+		nl80211_nlmsg_clear(msg);
+		nlmsg_free(msg);
+		return -ENOBUFS;
+	}
+	nla_nest_end(msg, params);
+	wpa_printf(MSG_DEBUG, "nl80211: Transition Disable Policy %d\n", td_policy);
+
+	ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "nl80211: Transition Disable setting failed: ret=%d (%s)",
+		ret, strerror(-ret));
+	}
+
+	return ret;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
+#ifdef CONFIG_TESTING_OPTIONS
+
+static int testing_nl80211_register_frame(void *priv, u16 type,
+					  const u8 *match, size_t match_len,
+					  bool multicast)
+{
+	struct i802_bss *bss = priv;
+	struct nl_sock *handle;
+
+	if (!bss->nl_mgmt)
+		return -1;
+	handle = (void *) (((intptr_t) bss->nl_mgmt) ^ ELOOP_SOCKET_INVALID);
+	return nl80211_register_frame(bss, handle, type, match, match_len,
+				      multicast);
+}
+
+
+static int testing_nl80211_radio_disable(void *priv, int disabled)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+
+	/* For now, this is supported only partially in station mode with
+	 * SME-in-wpa_supplicant case where the NL80211_ATTR_LOCAL_STATE_CHANGE
+	 * attribute can be used to avoid sending out the Deauthentication frame
+	 * to the currently associated AP. */
+
+	if (!disabled)
+		return 0;
+
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
+		return -1;
+
+	if (!drv->associated)
+		return 0;
+
+	return wpa_driver_nl80211_mlme(drv, drv->bssid,
+				       NL80211_CMD_DEAUTHENTICATE,
+				       WLAN_REASON_PREV_AUTH_NOT_VALID, 1,
+				       drv->first_bss);
+}
+
+#endif /* CONFIG_TESTING_OPTIONS */
+
 
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.name = "nl80211",
@@ -12208,7 +12426,6 @@
 #ifdef CONFIG_DRIVER_NL80211_QCA
 	.roaming = nl80211_roaming,
 	.disable_fils = nl80211_disable_fils,
-	.do_acs = wpa_driver_do_acs,
 	.set_band = nl80211_set_band,
 	.get_pref_freq_list = nl80211_get_pref_freq_list,
 	.set_prob_oper_freq = nl80211_set_prob_oper_freq,
@@ -12223,10 +12440,8 @@
 	.set_bssid_tmp_disallow = nl80211_set_bssid_tmp_disallow,
 	.add_sta_node = nl80211_add_sta_node,
 #endif /* CONFIG_DRIVER_NL80211_QCA */
+	.do_acs = nl80211_do_acs,
 	.configure_data_frame_filters = nl80211_configure_data_frame_filters,
-#if defined(CONFIG_DRIVER_NL80211_BRCM)
-	.do_acs = wpa_driver_do_broadcom_acs,
-#endif /* CONFIG_DRIVER_NL80211_BRCM */
 	.get_ext_capab = nl80211_get_ext_capab,
 	.update_connect_params = nl80211_update_connection_params,
 	.send_external_auth_status = nl80211_send_external_auth_status,
@@ -12234,4 +12449,8 @@
 #ifdef CONFIG_DPP
 	.dpp_listen = nl80211_dpp_listen,
 #endif /* CONFIG_DPP */
+#ifdef CONFIG_TESTING_OPTIONS
+	.register_frame = testing_nl80211_register_frame,
+	.radio_disable = testing_nl80211_radio_disable,
+#endif /* CONFIG_TESTING_OPTIONS */
 };
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index e7fe180..dcf482a 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -32,6 +32,7 @@
 	struct nl_cb *nl_cb;
 	struct nl_sock *nl;
 	int nl80211_id;
+	int nlctrl_id;
 	int ioctl_sock; /* socket for ioctl() use */
 	struct nl_sock *nl_event;
 	u8 p2p_perm_addr[ETH_ALEN];
@@ -149,7 +150,7 @@
 	unsigned int ignore_next_local_disconnect:1;
 	unsigned int ignore_next_local_deauth:1;
 	unsigned int hostapd:1;
-	unsigned int start_mode_ap:1;
+	unsigned int start_mode_sta:1;
 	unsigned int start_iface_up:1;
 	unsigned int test_use_roc_tx:1;
 	unsigned int ignore_deauth_event:1;
@@ -177,6 +178,8 @@
 	unsigned int get_sta_info_vendor_cmd_avail:1;
 	unsigned int fils_discovery:1;
 	unsigned int unsol_bcast_probe_resp:1;
+	unsigned int qca_do_acs:1;
+	unsigned int brcm_do_acs:1;
 
 	u64 vendor_scan_cookie;
 	u64 remain_on_chan_cookie;
@@ -275,7 +278,7 @@
 int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
 			    const u8 *addr, int cmd, u16 reason_code,
 			    int local_state_change,
-			    struct nl_sock *nl_connect);
+			    struct i802_bss *bss);
 
 int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
 void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 8208762..392b0c6 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -16,10 +16,8 @@
 #include "common/wpa_common.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
-#include "driver_nl80211.h"
-#ifdef CONFIG_DRIVER_NL80211_BRCM
 #include "common/brcm_vendor.h"
-#endif /* CONFIG_DRIVER_NL80211_BRCM */
+#include "driver_nl80211.h"
 
 static int protocol_feature_handler(struct nl_msg *msg, void *arg)
 {
@@ -892,7 +890,7 @@
 
 	if (tb[NL80211_ATTR_MAC_ACL_MAX])
 		capa->max_acl_mac_addrs =
-			nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
+			nla_get_u32(tb[NL80211_ATTR_MAC_ACL_MAX]);
 
 	wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
 	wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
@@ -997,6 +995,7 @@
 				case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
 					drv->capa.flags |=
 						WPA_DRIVER_FLAGS_ACS_OFFLOAD;
+					drv->qca_do_acs = 1;
 					break;
 				case QCA_NL80211_VENDOR_SUBCMD_SETBAND:
 					drv->setband_vendor_cmd_avail = 1;
@@ -1021,25 +1020,26 @@
 					break;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 				}
-			}
 #ifdef CONFIG_DRIVER_NL80211_BRCM
-			if (vinfo->vendor_id == OUI_BRCM) {
-				wpa_printf(MSG_MSGDUMP, "vendor:%x cmd:0x%x\n",
-						vinfo->vendor_id, vinfo->subcmd);
+			} else if (vinfo->vendor_id == OUI_BRCM) {
 				switch (vinfo->subcmd) {
-					case BRCM_VENDOR_SCMD_ACS:
-						drv->capa.flags |= WPA_DRIVER_FLAGS_ACS_OFFLOAD;
-						drv->capa.flags |=
-							WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY;
-						break;
-					case BRCM_VENDOR_SUBCMD_SET_PMK:
-						drv->vendor_set_pmk = 1;
-						break;
-					default:
-						break;
+				case BRCM_VENDOR_SCMD_ACS:
+					drv->capa.flags |=
+						WPA_DRIVER_FLAGS_ACS_OFFLOAD;
+				    drv->capa.flags |=
+						WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY;
+					wpa_printf(MSG_DEBUG,
+						   "Enabled BRCM ACS");
+					drv->brcm_do_acs = 1;
+					break;
+				case BRCM_VENDOR_SCMD_SET_PMK:
+					drv->vendor_set_pmk = 1;
+					break;
+				default:
+					break;
 				}
-			}
 #endif /* CONFIG_DRIVER_NL80211_BRCM */
+			}
 			wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
 				   vinfo->vendor_id, vinfo->subcmd);
 		}
@@ -1394,7 +1394,7 @@
 		WPA_DRIVER_AUTH_SHARED |
 		WPA_DRIVER_AUTH_LEAP;
 
-	drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
+	drv->capa.flags |= WPA_DRIVER_FLAGS_VALID_ERROR_CODES;
 	drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
 	drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
 
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 81f688a..177c31d 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -15,12 +15,10 @@
 #include "utils/eloop.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
+#include "common/brcm_vendor.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "driver_nl80211.h"
-#ifdef CONFIG_DRIVER_NL80211_BRCM
-#include "common/brcm_vendor.h"
-#endif /* CONFIG_DRIVER_NL80211_BRCM */
 
 static void
 nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
@@ -139,19 +137,45 @@
 	C2S(NL80211_CMD_SET_QOS_MAP)
 	C2S(NL80211_CMD_ADD_TX_TS)
 	C2S(NL80211_CMD_DEL_TX_TS)
+	C2S(NL80211_CMD_GET_MPP)
+	C2S(NL80211_CMD_JOIN_OCB)
+	C2S(NL80211_CMD_LEAVE_OCB)
+	C2S(NL80211_CMD_CH_SWITCH_STARTED_NOTIFY)
+	C2S(NL80211_CMD_TDLS_CHANNEL_SWITCH)
+	C2S(NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH)
 	C2S(NL80211_CMD_WIPHY_REG_CHANGE)
+	C2S(NL80211_CMD_ABORT_SCAN)
+	C2S(NL80211_CMD_START_NAN)
+	C2S(NL80211_CMD_STOP_NAN)
+	C2S(NL80211_CMD_ADD_NAN_FUNCTION)
+	C2S(NL80211_CMD_DEL_NAN_FUNCTION)
+	C2S(NL80211_CMD_CHANGE_NAN_CONFIG)
+	C2S(NL80211_CMD_NAN_MATCH)
+	C2S(NL80211_CMD_SET_MULTICAST_TO_UNICAST)
+	C2S(NL80211_CMD_UPDATE_CONNECT_PARAMS)
+	C2S(NL80211_CMD_SET_PMK)
+	C2S(NL80211_CMD_DEL_PMK)
 	C2S(NL80211_CMD_PORT_AUTHORIZED)
+	C2S(NL80211_CMD_RELOAD_REGDB)
 	C2S(NL80211_CMD_EXTERNAL_AUTH)
 	C2S(NL80211_CMD_STA_OPMODE_CHANGED)
 	C2S(NL80211_CMD_CONTROL_PORT_FRAME)
+	C2S(NL80211_CMD_GET_FTM_RESPONDER_STATS)
+	C2S(NL80211_CMD_PEER_MEASUREMENT_START)
+	C2S(NL80211_CMD_PEER_MEASUREMENT_RESULT)
+	C2S(NL80211_CMD_PEER_MEASUREMENT_COMPLETE)
+	C2S(NL80211_CMD_NOTIFY_RADAR)
 	C2S(NL80211_CMD_UPDATE_OWE_INFO)
+	C2S(NL80211_CMD_PROBE_MESH_LINK)
+	C2S(NL80211_CMD_SET_TID_CONFIG)
 	C2S(NL80211_CMD_UNPROT_BEACON)
 	C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS)
-
-	default:
-		return "NL80211_CMD_UNKNOWN";
+	C2S(NL80211_CMD_SET_SAR_SPECS)
+	C2S(__NL80211_CMD_AFTER_LAST)
 	}
 #undef C2S
+
+	return "NL80211_CMD_UNKNOWN";
 }
 
 
@@ -639,8 +663,10 @@
 	case CHAN_WIDTH_160:
 		freq1 = cf1 - 70;
 		break;
-	case CHAN_WIDTH_UNKNOWN:
 	case CHAN_WIDTH_80P80:
+		freq1 = cf1 - 30;
+		break;
+	case CHAN_WIDTH_UNKNOWN:
 	case CHAN_WIDTH_2160:
 	case CHAN_WIDTH_4320:
 	case CHAN_WIDTH_6480:
@@ -702,6 +728,8 @@
 						    nla_get_u32(freq),
 						    nla_get_u32(cf1),
 						    cf2 ? nla_get_u32(cf2) : 0);
+		wpa_printf(MSG_DEBUG, "nl80211: Calculated channel offset: %d",
+			   chan_offset);
 	} else {
 		wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
 	}
@@ -1300,7 +1328,7 @@
 	struct nlattr *nl;
 	int rem;
 	struct scan_info *info;
-#define MAX_REPORT_FREQS 50
+#define MAX_REPORT_FREQS 100
 	int freqs[MAX_REPORT_FREQS];
 	int num_freqs = 0;
 
@@ -1332,7 +1360,7 @@
 		}
 	}
 	if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
-		char msg[300], *pos, *end;
+		char msg[500], *pos, *end;
 		int res;
 
 		pos = msg;
@@ -1838,96 +1866,6 @@
 	wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
 }
 
-#ifdef CONFIG_DRIVER_NL80211_BRCM
-static void brcm_nl80211_acs_select_ch(struct wpa_driver_nl80211_data
-	*drv, const u8 *data, size_t len)
-{
-	struct nlattr *tb[BRCM_VENDOR_ATTR_ACS_LAST + 1];
-	union wpa_event_data event;
-
-	wpa_printf(MSG_DEBUG, "nl80211: vendor ACS channel selection vendor even received");
-
-	if (nla_parse(tb, BRCM_VENDOR_ATTR_ACS_LAST, (struct nlattr*) data, len, NULL)
-		|| (!tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ])
-			|| (!tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ])) {
-			return;
-		}
-
-	os_memset(&event, 0, sizeof(event));
-	if (tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ]) {
-		event.acs_selected_channels.pri_freq =
-				nla_get_u32(tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ]);
-	}
-
-	wpa_printf(MSG_MSGDUMP, "got pri_freq=%d\n",
-		event.acs_selected_channels.pri_freq );
-
-	if (tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ]) {
-		event.acs_selected_channels.sec_freq =
-			nla_get_u32(tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ]);
-	}
-
-	wpa_printf(MSG_MSGDUMP, "got sec_freq=%d\n",
-		event.acs_selected_channels.sec_freq );
-	if (tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) {
-		event.acs_selected_channels.vht_seg0_center_ch =
-			nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]);
-	}
-
-	if (tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) {
-		event.acs_selected_channels.vht_seg1_center_ch =
-			nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]);
-	}
-	if (tb[BRCM_VENDOR_ATTR_ACS_CHWIDTH]) {
-		event.acs_selected_channels.ch_width =
-			nla_get_u16(tb[BRCM_VENDOR_ATTR_ACS_CHWIDTH]);
-	}
-	if (tb[BRCM_VENDOR_ATTR_ACS_HW_MODE]) {
-		event.acs_selected_channels.hw_mode =
-		nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_HW_MODE]);
-		if ((event.acs_selected_channels.hw_mode == NUM_HOSTAPD_MODES)
-			|| (event.acs_selected_channels.hw_mode
-				== HOSTAPD_MODE_IEEE80211ANY)) {
-			wpa_printf(MSG_ERROR, "nl80211: Invalid hw_mode %d in ACS selection event",
-				event.acs_selected_channels.hw_mode);
-			return;
-		}
-	}
-
-	wpa_printf(MSG_INFO, "nl80211: ACS Results: PCH: %d SCH: %d BW: %d"
-		" VHT0: %d VHT1: %d HW_MODE: %d",
-		event.acs_selected_channels.pri_freq,
-		event.acs_selected_channels.sec_freq,
-		event.acs_selected_channels.ch_width,
-		event.acs_selected_channels.vht_seg0_center_ch,
-		event.acs_selected_channels.vht_seg1_center_ch,
-		event.acs_selected_channels.hw_mode);
-	wpa_supplicant_event(drv->ctx, EVENT_ACS_CHANNEL_SELECTED,
-		&event);
-	return;
-}
-
-static void nl80211_vendor_event_brcm( struct wpa_driver_nl80211_data *drv,
-	u32 subcmd, u8 *data, size_t len)
-{
-	union wpa_event_data event;
-        const struct nlattr *iter;
-        int rem = len;
-
-	wpa_printf(MSG_MSGDUMP, "got vendor event %d", subcmd);
-	memset(&event, 0, sizeof(event));
-	switch (subcmd) {
-	case BRCM_VENDOR_EVENT_ACS:
-		wpa_printf(MSG_DEBUG, "nl80211: Received VENDOR_EVENT_ACS");
-		brcm_nl80211_acs_select_ch(drv, data, len);
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event %u", subcmd);
-		break;
-	}
-
-}
-#endif /* CONFIG_DRIVER_NL80211_BRCM */
 #ifdef CONFIG_DRIVER_NL80211_QCA
 
 static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data *drv,
@@ -2333,7 +2271,7 @@
 	}
 
 	if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) {
-		char msg[300], *pos, *end;
+		char msg[500], *pos, *end;
 		int res;
 
 		pos = msg;
@@ -2472,6 +2410,87 @@
 }
 
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+
+static void brcm_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
+				       const u8 *data, size_t len)
+{
+	struct nlattr *tb[BRCM_VENDOR_ATTR_ACS_LAST + 1];
+	union wpa_event_data event;
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: BRCM ACS channel selection vendor event received");
+
+	if (nla_parse(tb, BRCM_VENDOR_ATTR_ACS_LAST, (struct nlattr *) data,
+		      len, NULL) ||
+	    !tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ] ||
+	    !tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ])
+		return;
+
+	os_memset(&event, 0, sizeof(event));
+	if (tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ])
+		event.acs_selected_channels.pri_freq =
+			nla_get_u32(tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ]);
+	if (tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ])
+		event.acs_selected_channels.sec_freq =
+			nla_get_u32(tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ]);
+	if (tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
+		event.acs_selected_channels.vht_seg0_center_ch =
+			nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]);
+	if (tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
+		event.acs_selected_channels.vht_seg1_center_ch =
+			nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]);
+	if (tb[BRCM_VENDOR_ATTR_ACS_CHWIDTH])
+		event.acs_selected_channels.ch_width =
+			nla_get_u16(tb[BRCM_VENDOR_ATTR_ACS_CHWIDTH]);
+	if (tb[BRCM_VENDOR_ATTR_ACS_HW_MODE]) {
+		event.acs_selected_channels.hw_mode = nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_HW_MODE]);
+		if (event.acs_selected_channels.hw_mode == NUM_HOSTAPD_MODES ||
+		    event.acs_selected_channels.hw_mode ==
+		    HOSTAPD_MODE_IEEE80211ANY) {
+			wpa_printf(MSG_DEBUG,
+				   "nl80211: Invalid hw_mode %d in ACS selection event",
+				   event.acs_selected_channels.hw_mode);
+			return;
+		}
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
+		   event.acs_selected_channels.pri_freq,
+		   event.acs_selected_channels.sec_freq,
+		   event.acs_selected_channels.ch_width,
+		   event.acs_selected_channels.vht_seg0_center_ch,
+		   event.acs_selected_channels.vht_seg1_center_ch,
+		   event.acs_selected_channels.hw_mode);
+	wpa_supplicant_event(drv->ctx, EVENT_ACS_CHANNEL_SELECTED, &event);
+}
+
+
+static void nl80211_vendor_event_brcm(struct wpa_driver_nl80211_data *drv,
+				      u32 subcmd, u8 *data, size_t len)
+{
+	wpa_printf(MSG_DEBUG, "nl80211: Got BRCM vendor event %u", subcmd);
+	switch (subcmd) {
+	case BRCM_VENDOR_EVENT_PRIV_STR:
+	case BRCM_VENDOR_EVENT_HANGED:
+		/* Dump the event on to the console */
+		wpa_msg(NULL, MSG_INFO, "%s", data);
+		break;
+	case BRCM_VENDOR_EVENT_ACS:
+		brcm_nl80211_acs_select_ch(drv, data, len);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG,
+			   "%s: Ignore unsupported BRCM vendor event %u",
+			   __func__, subcmd);
+		break;
+	}
+}
+
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
+
 static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
 				 struct nlattr **tb)
 {
@@ -2518,8 +2537,8 @@
 		break;
 #ifdef CONFIG_DRIVER_NL80211_BRCM
 	case OUI_BRCM:
-	        nl80211_vendor_event_brcm(drv, subcmd, data, len);
-	        break;
+		nl80211_vendor_event_brcm(drv, subcmd, data, len);
+		break;
 #endif /* CONFIG_DRIVER_NL80211_BRCM */
 	default:
 		wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
@@ -2834,6 +2853,40 @@
 }
 
 
+static void nl80211_frame_wait_cancel(struct wpa_driver_nl80211_data *drv,
+				      struct nlattr *cookie_attr)
+{
+	unsigned int i;
+	u64 cookie;
+	bool match = false;
+
+	if (!cookie_attr)
+		return;
+	cookie = nla_get_u64(cookie_attr);
+
+	for (i = 0; i < drv->num_send_frame_cookies; i++) {
+		if (cookie == drv->send_frame_cookies[i]) {
+			match = true;
+			break;
+		}
+	}
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: TX frame wait expired for cookie 0x%llx%s",
+		   (long long unsigned int) cookie,
+		   match ? " (match)" : "");
+	if (!match)
+		return;
+
+	if (i < drv->num_send_frame_cookies - 1)
+		os_memmove(&drv->send_frame_cookies[i],
+			   &drv->send_frame_cookies[i + 1],
+			   (drv->num_send_frame_cookies - i - 1) * sizeof(u64));
+	drv->num_send_frame_cookies--;
+
+	wpa_supplicant_event(drv->ctx, EVENT_TX_WAIT_EXPIRE, NULL);
+}
+
+
 static void do_process_drv_event(struct i802_bss *bss, int cmd,
 				 struct nlattr **tb)
 {
@@ -3080,6 +3133,9 @@
 						     tb[NL80211_ATTR_ACK],
 						     tb[NL80211_ATTR_COOKIE]);
 		break;
+	case NL80211_CMD_FRAME_WAIT_CANCEL:
+		nl80211_frame_wait_cancel(drv, tb[NL80211_ATTR_COOKIE]);
+		break;
 	default:
 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
 			"(cmd=%d)", cmd);
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 233175d..1316084 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -870,7 +870,7 @@
 		wpa_driver_nl80211_mlme(drv, addr,
 					NL80211_CMD_DEAUTHENTICATE,
 					WLAN_REASON_PREV_AUTH_NOT_VALID, 1,
-					get_connect_handle(drv->first_bss));
+					drv->first_bss);
 	}
 }
 
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index ac78da9..f962c06 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -655,6 +655,9 @@
  *	When a security association was established on an 802.1X network using
  *	fast transition, this event should be followed by an
  *	%NL80211_CMD_PORT_AUTHORIZED event.
+ *	Following a %NL80211_CMD_ROAM event userspace can issue
+ *	%NL80211_CMD_GET_SCAN in order to obtain the scan information for the
+ *	new BSS the card/driver roamed to.
  * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
  *	userspace that a connection was dropped by the AP or due to other
  *	reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
@@ -5937,6 +5940,16 @@
  * @NL80211_EXT_FEATURE_BEACON_RATE_HE: Driver supports beacon rate
  *	configuration (AP/mesh) with HE rates.
  *
+ * @NL80211_EXT_FEATURE_SECURE_LTF: Device supports secure LTF measurement
+ *      exchange protocol.
+ *
+ * @NL80211_EXT_FEATURE_SECURE_RTT: Device supports secure RTT measurement
+ *      exchange protocol.
+ *
+ * @NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE: Device supports management
+ *      frame protection for all management frames exchanged during the
+ *      negotiation and range measurement procedure.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -5998,6 +6011,9 @@
 	NL80211_EXT_FEATURE_FILS_DISCOVERY,
 	NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP,
 	NL80211_EXT_FEATURE_BEACON_RATE_HE,
+	NL80211_EXT_FEATURE_SECURE_LTF,
+	NL80211_EXT_FEATURE_SECURE_RTT,
+	NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
@@ -6295,11 +6311,13 @@
  * @NL80211_TDLS_PEER_HT: TDLS peer is HT capable.
  * @NL80211_TDLS_PEER_VHT: TDLS peer is VHT capable.
  * @NL80211_TDLS_PEER_WMM: TDLS peer is WMM capable.
+ * @NL80211_TDLS_PEER_HE: TDLS peer is HE capable.
  */
 enum nl80211_tdls_peer_capability {
 	NL80211_TDLS_PEER_HT = 1<<0,
 	NL80211_TDLS_PEER_VHT = 1<<1,
 	NL80211_TDLS_PEER_WMM = 1<<2,
+	NL80211_TDLS_PEER_HE = 1<<3,
 };
 
 /**
@@ -6891,6 +6909,9 @@
  *      if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor
  *	%NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based
  *	ranging will be used.
+ * @NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK: negotiate for LMR feedback. Only
+ *	valid if either %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED or
+ *	%NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
  *
  * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
  * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
@@ -6909,6 +6930,7 @@
 	NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC,
 	NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED,
 	NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED,
+	NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK,
 
 	/* keep last */
 	NUM_NL80211_PMSR_FTM_REQ_ATTR,
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index 2b2b8ef..0e3a7b2 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -127,7 +127,8 @@
 	u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
 	u8 x_bin[MAX_ECC_PRIME_LEN];
 	u8 prime_bin[MAX_ECC_PRIME_LEN];
-	struct crypto_bignum *tmp2 = NULL;
+	u8 x_y[2 * MAX_ECC_PRIME_LEN];
+	struct crypto_bignum *tmp2 = NULL, *y = NULL;
 	struct crypto_hash *hash;
 	unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
 	int ret = 0, res;
@@ -139,6 +140,7 @@
 	u8 found_ctr = 0, is_odd = 0;
 	int cmp_prime;
 	unsigned int in_range;
+	unsigned int is_eq;
 
 	if (grp->pwe)
 		return -1;
@@ -151,11 +153,6 @@
 	if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
 				 primebytelen) < 0)
 		return -1;
-	grp->pwe = crypto_ec_point_init(grp->group);
-	if (!grp->pwe) {
-		wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
-		goto fail;
-	}
 
 	if ((prfbuf = os_malloc(primebytelen)) == NULL) {
 		wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
@@ -261,10 +258,37 @@
 	 */
 	crypto_bignum_deinit(x_candidate, 1);
 	x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
-	if (!x_candidate ||
-	    crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
-					  is_odd) != 0) {
-		wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
+	if (!x_candidate)
+		goto fail;
+
+	/* y = sqrt(x^3 + ax + b) mod p
+	 * if LSB(y) == LSB(pwd-seed): PWE = (x, y)
+	 * else: PWE = (x, p - y)
+	 *
+	 * Calculate y and the two possible values for PWE and after that,
+	 * use constant time selection to copy the correct alternative.
+	 */
+	y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate);
+	if (!y ||
+	    dragonfly_sqrt(grp->group, y, y) < 0 ||
+	    crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 ||
+	    crypto_bignum_sub(prime, y, y) < 0 ||
+	    crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN,
+				 MAX_ECC_PRIME_LEN, primebytelen) < 0) {
+		wpa_printf(MSG_DEBUG, "EAP-pwd: Could not solve y");
+		goto fail;
+	}
+
+	/* Constant time selection of the y coordinate from the two
+	 * options */
+	is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01);
+	const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN,
+			      primebytelen, x_y + primebytelen);
+	os_memcpy(x_y, x_bin, primebytelen);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen);
+	grp->pwe = crypto_ec_point_from_bin(grp->group, x_y);
+	if (!grp->pwe) {
+		wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE");
 		goto fail;
 	}
 
@@ -289,6 +313,7 @@
 	/* cleanliness and order.... */
 	crypto_bignum_deinit(x_candidate, 1);
 	crypto_bignum_deinit(tmp2, 1);
+	crypto_bignum_deinit(y, 1);
 	crypto_bignum_deinit(qr, 1);
 	crypto_bignum_deinit(qnr, 1);
 	bin_clear_free(prfbuf, primebytelen);
@@ -296,6 +321,7 @@
 	os_memset(qnr_bin, 0, sizeof(qnr_bin));
 	os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
 	os_memset(pwe_digest, 0, sizeof(pwe_digest));
+	forced_memzero(x_y, sizeof(x_y));
 
 	return ret;
 }
diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile
index bdbead6..076d8c0 100644
--- a/src/eap_peer/Makefile
+++ b/src/eap_peer/Makefile
@@ -5,9 +5,3 @@
 	eap_methods.o
 
 include ../lib.rules
-
-install:
-	if ls *.so >/dev/null 2>&1; then \
-		install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \
-		cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \
-	; fi
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 74c2ad3..5fd370f 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -429,6 +429,17 @@
 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
 		"EAP vendor %u method %u (%s) selected",
 		sm->reqVendor, method, sm->m->name);
+
+	if (sm->eapol_cb->notify_eap_method_selected) {
+		char *format_str = "EAP vendor %u method %u (%s) selected";
+		int msg_len = snprintf(NULL, 0, format_str,
+			sm->reqVendor, method, sm->m->name) + 1;
+		char *msg = os_malloc(msg_len);
+		snprintf(msg, msg_len, format_str,
+			sm->reqVendor, method, sm->m->name);
+		sm->eapol_cb->notify_eap_method_selected(sm->eapol_ctx, msg);
+		os_free(msg);
+	}
 	return;
 
 nak:
@@ -1069,6 +1080,20 @@
 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
 		"EAP authentication completed successfully");
 
+	if (!config || !sm->m) {
+		/*
+		 * This should not happen under normal conditions, but be more
+		 * careful here since there was an earlier case where
+		 * EAP-Success could end up getting delivered to the state
+		 * machine for processing after the state had been cleaned with
+		 * a call to eap_invalidate_cached_session() (and also
+		 * eapol_sm_notify_config() having been used to clear EAP
+		 * configuration in the EAPOL state machine).
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "EAP: State machine not configured - cannot initialize ERP");
+		return;
+	}
 	if (config->erp && sm->m->get_emsk && sm->eapSessionId &&
 	    sm->m->isKeyAvailable &&
 	    sm->m->isKeyAvailable(sm, sm->eap_method_priv))
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index a40d007..aae1a41 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -281,6 +281,20 @@
 	 * @len: Length of anonymous identity in octets
 	 */
 	void (*set_anon_id)(void *ctx, const u8 *id, size_t len);
+
+	/**
+	 * notify_eap_method_selected - Report that the EAP method was selected
+	 * @ctx: eapol_ctx from eap_peer_sm_init() call
+	 * @reason_string: Information to log about the event
+	 */
+	void (*notify_eap_method_selected)(void *ctx, const char* reason_string);
+
+	/**
+	 * notify_open_ssl_failure - Report that an OpenSSL failure occurred
+	 * @ctx: eapol_ctx from eap_peer_sm_init() call
+	 * @reason_string: Information to log about the event
+	 */
+	void (*notify_open_ssl_failure)(void *ctx, const char* reason_string);
 };
 
 /**
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index 8c475f1..ee7010d 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -385,6 +385,7 @@
 		size_t identity_len = 0;
 		const u8 *realm = NULL;
 		size_t realm_len = 0;
+		struct eap_peer_config *config = eap_get_config(sm);
 
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
@@ -400,6 +401,17 @@
 					break;
 			}
 		}
+		// If no realm from the permanent identity, look for the
+		// realm of the anonymous identity.
+		if (realm_len == 0 && config && config->anonymous_identity
+		    && config->anonymous_identity_len > 0) {
+			for (realm = config->anonymous_identity,
+			    realm_len = config->anonymous_identity_len;
+			    realm_len > 0; realm_len--, realm++) {
+				if (*realm == '@')
+					break;
+			}
+		}
 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
 					    realm_len);
 		if (data->pseudonym == NULL) {
diff --git a/src/eap_peer/eap_proxy_dummy.c b/src/eap_peer/eap_proxy_dummy.c
index 2cc05c9..181e8cc 100644
--- a/src/eap_peer/eap_proxy_dummy.c
+++ b/src/eap_peer/eap_proxy_dummy.c
@@ -1,5 +1,5 @@
 /*
- * EAP proxy - dummy implementation for build testing
+ * EAP proxy - stub implementation for build testing
  * Copyright (c) 2013 Qualcomm Atheros, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index 0986627..de423e8 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -407,6 +407,7 @@
 		size_t identity_len = 0;
 		const u8 *realm = NULL;
 		size_t realm_len = 0;
+		struct eap_peer_config *config = eap_get_config(sm);
 
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
@@ -422,6 +423,17 @@
 					break;
 			}
 		}
+		// If no realm from the permanent identity, look for the
+		// realm of the anonymous identity.
+		if (realm_len == 0 && config && config->anonymous_identity
+		    && config->anonymous_identity_len > 0) {
+			for (realm = config->anonymous_identity,
+			    realm_len = config->anonymous_identity_len;
+			    realm_len > 0; realm_len--, realm++) {
+				if (*realm == '@')
+					break;
+			}
+		}
 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
 					    realm_len);
 		if (data->pseudonym == NULL) {
diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c
index e8cc784..bc7f6f4 100644
--- a/src/eap_peer/eap_teap.c
+++ b/src/eap_peer/eap_teap.c
@@ -1760,8 +1760,8 @@
 
 
 #ifdef CONFIG_TESTING_OPTIONS
-static struct wpabuf * eap_teap_add_dummy_outer_tlvs(struct eap_teap_data *data,
-						     struct wpabuf *resp)
+static struct wpabuf * eap_teap_add_stub_outer_tlvs(struct eap_teap_data *data,
+						    struct wpabuf *resp)
 {
 	struct wpabuf *resp2;
 	u16 len;
@@ -1775,11 +1775,11 @@
 		return NULL;
 	}
 
-	/* Outer TLVs (dummy Vendor-Specific TLV for testing) */
+	/* Outer TLVs (stub Vendor-Specific TLV for testing) */
 	wpabuf_put_be16(data->peer_outer_tlvs, TEAP_TLV_VENDOR_SPECIFIC);
 	wpabuf_put_be16(data->peer_outer_tlvs, 4);
 	wpabuf_put_be32(data->peer_outer_tlvs, EAP_VENDOR_HOSTAP);
-	wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: TESTING - Add dummy Outer TLVs",
+	wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: TESTING - Add stub Outer TLVs",
 			data->peer_outer_tlvs);
 
 	wpa_hexdump_buf(MSG_DEBUG,
@@ -1986,7 +1986,7 @@
 #ifdef CONFIG_TESTING_OPTIONS
 	if (data->test_outer_tlvs && res == 0 && resp &&
 	    (flags & EAP_TLS_FLAGS_START) && wpabuf_len(resp) >= 6)
-		resp = eap_teap_add_dummy_outer_tlvs(data, resp);
+		resp = eap_teap_add_stub_outer_tlvs(data, resp);
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	return resp;
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 0e00801..1aaca36 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -778,6 +778,10 @@
 		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
 			   "report error (len=%u)",
 			   (unsigned int) wpabuf_len(data->tls_out));
+		if (sm->eapol_cb->notify_open_ssl_failure) {
+			sm->eapol_cb->notify_open_ssl_failure(sm->eapol_ctx,
+				"TLS processing has failed");
+		}
 		ret = -1;
 		/* TODO: clean pin if engine used? */
 		if (wpabuf_len(data->tls_out) == 0) {
diff --git a/src/eap_peer/eap_tls_common.h b/src/eap_peer/eap_tls_common.h
index 183b7de..9ac0012 100644
--- a/src/eap_peer/eap_tls_common.h
+++ b/src/eap_peer/eap_tls_common.h
@@ -92,7 +92,7 @@
  /* could be up to 128 bytes, but only the first 64 bytes are used */
 #define EAP_TLS_KEY_LEN 64
 
-/* dummy type used as a flag for UNAUTH-TLS */
+/* stub type used as a flag for UNAUTH-TLS */
 #define EAP_UNAUTH_TLS_TYPE 255
 #define EAP_WFA_UNAUTH_TLS_TYPE 254
 
diff --git a/src/eap_server/eap_server_wsc.c b/src/eap_server/eap_server_wsc.c
index fc70cf1..a162deb 100644
--- a/src/eap_server/eap_server_wsc.c
+++ b/src/eap_server/eap_server_wsc.c
@@ -132,9 +132,11 @@
 	cfg.peer_addr = sm->peer_addr;
 #ifdef CONFIG_P2P
 	if (sm->assoc_p2p_ie) {
-		wpa_printf(MSG_DEBUG, "EAP-WSC: Prefer PSK format for P2P "
-			   "client");
-		cfg.use_psk_key = 1;
+		if (!sm->cfg->wps->use_passphrase) {
+			wpa_printf(MSG_DEBUG,
+				   "EAP-WSC: Prefer PSK format for non-6 GHz P2P client");
+			cfg.use_psk_key = 1;
+		}
 		cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
 	}
 #endif /* CONFIG_P2P */
diff --git a/src/eap_server/eap_tls_common.h b/src/eap_server/eap_tls_common.h
index b0b7361..b0723a1 100644
--- a/src/eap_server/eap_tls_common.h
+++ b/src/eap_server/eap_tls_common.h
@@ -68,7 +68,7 @@
  /* could be up to 128 bytes, but only the first 64 bytes are used */
 #define EAP_TLS_KEY_LEN 64
 
-/* dummy type used as a flag for UNAUTH-TLS */
+/* stub type used as a flag for UNAUTH-TLS */
 #define EAP_UNAUTH_TLS_TYPE 255
 #define EAP_WFA_UNAUTH_TLS_TYPE 254
 
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index 861eea2..4e66369 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -2075,6 +2075,27 @@
 }
 
 
+static void
+eapol_sm_notify_eap_method_selected(void *ctx,
+				     const char* reason_string)
+{
+	struct eapol_sm *sm = ctx;
+
+	if (sm->ctx->eap_method_selected_cb)
+		sm->ctx->eap_method_selected_cb(sm->ctx->ctx, reason_string);
+}
+
+
+static void
+eapol_sm_notify_open_ssl_failure(void *ctx,
+				     const char* reason_string)
+{
+	struct eapol_sm *sm = ctx;
+
+	if (sm->ctx->open_ssl_failure_cb)
+		sm->ctx->open_ssl_failure_cb(sm->ctx->ctx, reason_string);
+}
+
 static const struct eapol_callbacks eapol_cb =
 {
 	eapol_sm_get_config,
@@ -2095,7 +2116,9 @@
 	eapol_sm_eap_proxy_notify_sim_status,
 	eapol_sm_get_eap_proxy_imsi,
 #endif /* CONFIG_EAP_PROXY */
-	eapol_sm_set_anon_id
+	eapol_sm_set_anon_id,
+	eapol_sm_notify_eap_method_selected,
+	eapol_sm_notify_open_ssl_failure
 };
 
 
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index 753b947..630a38e 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -307,6 +307,20 @@
 	 * Automatically triggers a reconnect when not.
 	 */
 	int (*confirm_auth_cb)(void *ctx);
+
+	/**
+	 * eap_method_selected_cb - Notification of EAP method selection
+	 * @ctx: eapol_ctx from eap_peer_sm_init() call
+	 * @reason_string: Information to log about the event
+	 */
+	void (*eap_method_selected_cb)(void *ctx, const char* reason_string);
+
+	/**
+	 * open_ssl_failure_cb - Notification of an OpenSSL failure
+	 * @ctx: eapol_ctx from eap_peer_sm_init() call
+	 * @reason_string: Information to log about the event
+	 */
+	void (*open_ssl_failure_cb)(void *ctx, const char* reason_string);
 };
 
 
diff --git a/src/l2_packet/l2_packet_none.c b/src/l2_packet/l2_packet_none.c
index bc7a4e8..6783d73 100644
--- a/src/l2_packet/l2_packet_none.c
+++ b/src/l2_packet/l2_packet_none.c
@@ -1,5 +1,5 @@
 /*
- * WPA Supplicant - Layer2 packet handling example with dummy functions
+ * WPA Supplicant - Layer2 packet handling example with stub functions
  * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 8b443d6..cd04008 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -429,7 +429,9 @@
 			oldest = dev;
 	}
 	if (count + 1 > p2p->cfg->max_peers && oldest) {
-		p2p_dbg(p2p, "Remove oldest peer entry to make room for a new peer");
+		p2p_dbg(p2p,
+			"Remove oldest peer entry to make room for a new peer "
+			MACSTR, MAC2STR(oldest->info.p2p_device_addr));
 		dl_list_del(&oldest->list);
 		p2p_device_free(p2p, oldest);
 	}
@@ -1036,7 +1038,7 @@
 
 	res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
 				 p2p->num_req_dev_types, p2p->req_dev_types,
-				 p2p->find_dev_id, pw_id);
+				 p2p->find_dev_id, pw_id, p2p->include_6ghz);
 	if (res < 0) {
 		p2p_dbg(p2p, "Scan request schedule failed");
 		p2p_continue_find(p2p);
@@ -1160,7 +1162,7 @@
 	     enum p2p_discovery_type type,
 	     unsigned int num_req_dev_types, const u8 *req_dev_types,
 	     const u8 *dev_id, unsigned int search_delay,
-	     u8 seek_count, const char **seek, int freq)
+	     u8 seek_count, const char **seek, int freq, bool include_6ghz)
 {
 	int res;
 	struct os_reltime start;
@@ -1185,7 +1187,7 @@
 		p2p->find_dev_id = p2p->find_dev_id_buf;
 	} else
 		p2p->find_dev_id = NULL;
-
+	p2p->include_6ghz = p2p_wfd_enabled(p2p) && include_6ghz;
 	if (seek_count == 0 || !seek) {
 		/* Not an ASP search */
 		p2p->p2ps_seek = 0;
@@ -1261,7 +1263,8 @@
 						 P2P_SCAN_SPECIFIC, freq,
 						 p2p->num_req_dev_types,
 						 p2p->req_dev_types, dev_id,
-						 DEV_PW_DEFAULT);
+						 DEV_PW_DEFAULT,
+						 p2p->include_6ghz);
 			break;
 		}
 		/* fall through */
@@ -1269,13 +1272,13 @@
 		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
 					 p2p->num_req_dev_types,
 					 p2p->req_dev_types, dev_id,
-					 DEV_PW_DEFAULT);
+					 DEV_PW_DEFAULT, p2p->include_6ghz);
 		break;
 	case P2P_FIND_ONLY_SOCIAL:
 		res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
 					 p2p->num_req_dev_types,
 					 p2p->req_dev_types, dev_id,
-					 DEV_PW_DEFAULT);
+					 DEV_PW_DEFAULT, p2p->include_6ghz);
 		break;
 	default:
 		return -1;
@@ -1326,7 +1329,9 @@
 
 void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
 {
-	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
+	if (freq > 0 &&
+	    ((p2p->drv_in_listen == freq && p2p->in_listen) ||
+	     p2p->pending_listen_freq == (unsigned int) freq)) {
 		p2p_dbg(p2p, "Skip stop_listen since we are on correct channel for response");
 		return;
 	}
@@ -1397,8 +1402,8 @@
 		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
 		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
 	} else {
-		os_memcpy(&p2p->channels, &p2p->cfg->channels,
-			  sizeof(struct p2p_channels));
+		p2p_copy_channels(&p2p->channels, &p2p->cfg->channels,
+				  p2p->allow_6ghz);
 	}
 
 	return 0;
@@ -1412,6 +1417,7 @@
 	const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
 	const int op_classes_vht[] = { 128, 0 };
 	const int op_classes_edmg[] = { 181, 182, 183, 0 };
+	const int op_classes_6ghz[] = { 131, 0 };
 
 	p2p_dbg(p2p, "Prepare channel best");
 
@@ -1448,6 +1454,12 @@
 		   0) {
 		p2p_dbg(p2p, "Select possible EDMG channel (op_class %u channel %u) as operating channel preference",
 			p2p->op_reg_class, p2p->op_channel);
+	} else if (p2p->allow_6ghz &&
+		   (p2p_channel_select(&p2p->cfg->channels, op_classes_6ghz,
+				       &p2p->op_reg_class, &p2p->op_channel) ==
+		    0)) {
+		p2p_dbg(p2p, "Select possible 6 GHz channel (op_class %u channel %u) as operating channel preference",
+			p2p->op_reg_class, p2p->op_channel);
 	} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_vht,
 				      &p2p->op_reg_class, &p2p->op_channel) ==
 		   0) {
@@ -1485,8 +1497,7 @@
 			p2p->op_channel, p2p->op_reg_class);
 	}
 
-	os_memcpy(&p2p->channels, &p2p->cfg->channels,
-		  sizeof(struct p2p_channels));
+	p2p_copy_channels(&p2p->channels, &p2p->cfg->channels, p2p->allow_6ghz);
 }
 
 
@@ -1569,9 +1580,10 @@
 	p2p_dbg(p2p, "Request to start group negotiation - peer=" MACSTR
 		"  GO Intent=%d  Intended Interface Address=" MACSTR
 		" wps_method=%d persistent_group=%d pd_before_go_neg=%d "
-		"oob_pw_id=%u",
+		"oob_pw_id=%u allow_6ghz=%d",
 		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
-		wps_method, persistent_group, pd_before_go_neg, oob_pw_id);
+		wps_method, persistent_group, pd_before_go_neg, oob_pw_id,
+		p2p->allow_6ghz);
 
 	dev = p2p_get_device(p2p, peer_addr);
 	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
@@ -1669,9 +1681,9 @@
 
 	p2p_dbg(p2p, "Request to authorize group negotiation - peer=" MACSTR
 		"  GO Intent=%d  Intended Interface Address=" MACSTR
-		" wps_method=%d  persistent_group=%d oob_pw_id=%u",
+		" wps_method=%d  persistent_group=%d oob_pw_id=%u allow_6ghz=%d",
 		MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
-		wps_method, persistent_group, oob_pw_id);
+		wps_method, persistent_group, oob_pw_id, p2p->allow_6ghz);
 
 	dev = p2p_get_device(p2p, peer_addr);
 	if (dev == NULL) {
@@ -4000,6 +4012,10 @@
 
 	p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation");
 	p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
+	if (p2p->pending_listen_freq) {
+		p2p_dbg(p2p, "Clear pending_listen_freq for %s", __func__);
+		p2p->pending_listen_freq = 0;
+	}
 	p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
 	p2p_listen_in_find(p2p, 0);
 }
@@ -5577,3 +5593,69 @@
 
 	return buf;
 }
+
+
+bool p2p_is_peer_6ghz_capab(struct p2p_data *p2p, const u8 *addr)
+{
+	struct p2p_device *dev;
+
+	dev = p2p_get_device(p2p, addr);
+	if (!dev)
+		return false;
+
+	return !!(dev->info.dev_capab & P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE);
+}
+
+
+void p2p_set_6ghz_dev_capab(struct p2p_data *p2p, bool allow_6ghz)
+{
+	p2p->p2p_6ghz_capable = allow_6ghz;
+	p2p->allow_6ghz = allow_6ghz;
+	p2p_dbg(p2p, "Set 6 GHz capability to %d", allow_6ghz);
+
+	if (allow_6ghz)
+		p2p->dev_capab |= P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE;
+	else
+		p2p->dev_capab &= ~P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE;
+}
+
+
+bool is_p2p_6ghz_capable(struct p2p_data *p2p)
+{
+	return p2p->p2p_6ghz_capable;
+}
+
+
+bool p2p_wfd_enabled(struct p2p_data *p2p)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+	return p2p->wfd_ie_probe_req != NULL;
+#else /* CONFIG_WIFI_DISPLAY */
+	return false;
+#endif /* CONFIG_WIFI_DISPLAY */
+}
+
+
+bool p2p_peer_wfd_enabled(struct p2p_data *p2p, const u8 *peer_addr)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+	struct p2p_device *dev;
+
+	dev = p2p_get_device(p2p, peer_addr);
+	return dev && dev->info.wfd_subelems != NULL;
+#else /* CONFIG_WIFI_DISPLAY */
+	return false;
+#endif /* CONFIG_WIFI_DISPLAY */
+}
+
+
+bool is_p2p_allow_6ghz(struct p2p_data *p2p)
+{
+	return p2p->allow_6ghz;
+}
+
+
+void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
+{
+	p2p->allow_6ghz = value;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 762bd40..f606fbb 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -612,6 +612,7 @@
 	 * @req_dev_types: Array containing requested device types
 	 * @dev_id: Device ID to search for or %NULL to find all devices
 	 * @pw_id: Device Password ID
+	 * @include_6ghz: Include 6 GHz channels in P2P scan
 	 * Returns: 0 on success, -1 on failure
 	 *
 	 * This callback function is used to request a P2P scan or search
@@ -635,7 +636,8 @@
 	 */
 	int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq,
 			unsigned int num_req_dev_types,
-			const u8 *req_dev_types, const u8 *dev_id, u16 pw_id);
+			const u8 *req_dev_types, const u8 *dev_id, u16 pw_id,
+			bool include_6ghz);
 
 	/**
 	 * send_probe_resp - Transmit a Probe Response frame
@@ -1243,13 +1245,15 @@
  *	P2P_FIND_START_WITH_FULL behavior. 0 = Use normal full scan.
  *	If p2p_find is already in progress, this parameter is ignored and full
  *	scan will be executed.
+ * @include_6ghz: Include 6 GHz channels in P2P find
  * Returns: 0 on success, -1 on failure
  */
 int p2p_find(struct p2p_data *p2p, unsigned int timeout,
 	     enum p2p_discovery_type type,
 	     unsigned int num_req_dev_types, const u8 *req_dev_types,
 	     const u8 *dev_id, unsigned int search_delay,
-	     u8 seek_count, const char **seek_string, int freq);
+	     u8 seek_count, const char **seek_string, int freq,
+	     bool include_6ghz);
 
 /**
  * p2p_notify_scan_trigger_status - Indicate scan trigger status
@@ -2411,4 +2415,13 @@
 struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
 					      unsigned int freq);
 
+void p2p_set_6ghz_dev_capab(struct p2p_data *p2p, bool allow_6ghz);
+bool is_p2p_6ghz_capable(struct p2p_data *p2p);
+bool p2p_is_peer_6ghz_capab(struct p2p_data *p2p, const u8 *addr);
+bool p2p_peer_wfd_enabled(struct p2p_data *p2p, const u8 *peer_addr);
+bool p2p_wfd_enabled(struct p2p_data *p2p);
+bool is_p2p_allow_6ghz(struct p2p_data *p2p);
+void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
+int p2p_remove_6ghz_channels(unsigned int *pref_freq_list, int size);
+
 #endif /* P2P_H */
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index 63eb2e8..4229d9b 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -111,7 +111,7 @@
 
 
 void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
-				   const u32 *preferred_freq_list,
+				   const unsigned int *preferred_freq_list,
 				   unsigned int size)
 {
 	unsigned int i, count = 0;
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 1133461..1d53d52 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -582,8 +582,8 @@
 					&op_channel) < 0)
 			continue; /* cannot happen due to earlier check */
 		for (j = 0; j < msg->channel_list_len; j++) {
-
-			if (op_channel != msg->channel_list[j])
+			if (!msg->channel_list ||
+			    op_channel != msg->channel_list[j])
 				continue;
 
 			p2p->op_reg_class = op_class;
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 2b168e8..b5e5c2b 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -559,6 +559,9 @@
 	/* Override option for preferred operating channel in GO Negotiation */
 	u8 override_pref_op_class;
 	u8 override_pref_channel;
+	bool p2p_6ghz_capable;
+	bool include_6ghz;
+	bool allow_6ghz;
 };
 
 /**
@@ -709,6 +712,8 @@
 			      u8 *op_channel,
 			      struct wpa_freq_range_list *avoid_list,
 			      struct wpa_freq_range_list *disallow_list);
+void p2p_copy_channels(struct p2p_channels *dst, const struct p2p_channels *src,
+		       bool allow_6ghz);
 
 /* p2p_parse.c */
 void p2p_copy_filter_devname(char *dst, size_t dst_len,
@@ -795,7 +800,8 @@
 int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
 		     int all_attr);
 void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
-				   const u32 *preferred_freq_list, u32 size);
+				   const unsigned int *preferred_freq_list,
+				   unsigned int size);
 
 /* p2p_sd.c */
 struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p,
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 77d662a..ab00722 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -653,8 +653,9 @@
 	struct p2p_device *dev;
 
 	p2p_dbg(p2p, "Request to invite peer " MACSTR " role=%d persistent=%d "
-		"force_freq=%u",
-		MAC2STR(peer), role, persistent_group, force_freq);
+		"force_freq=%u allow_6ghz=%d",
+		MAC2STR(peer), role, persistent_group, force_freq,
+		p2p->allow_6ghz);
 	if (bssid)
 		p2p_dbg(p2p, "Invitation for BSSID " MACSTR, MAC2STR(bssid));
 	if (go_dev_addr) {
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index 05fd593..338b47e 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -1425,7 +1425,7 @@
 		 * Save the reported channel list and operating frequency.
 		 * Note that the specification mandates that the responder
 		 * should include in the channel list only channels reported by
-		 * the initiator, so this is only a sanity check, and if this
+		 * the initiator, so this is only a validity check, and if this
 		 * fails the flow would continue, although it would probably
 		 * fail. Same is true for the operating channel.
 		 */
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index 1a62a44..7d21f68 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -496,3 +496,42 @@
 
 	return idx;
 }
+
+
+void p2p_copy_channels(struct p2p_channels *dst,
+		       const struct p2p_channels *src, bool allow_6ghz)
+{
+	size_t i, j;
+
+	if (allow_6ghz) {
+		os_memcpy(dst, src, sizeof(struct p2p_channels));
+		return;
+	}
+
+	for (i = 0, j = 0; i < P2P_MAX_REG_CLASSES; i++) {
+		if (is_6ghz_op_class(src->reg_class[i].reg_class))
+			continue;
+		os_memcpy(&dst->reg_class[j], &src->reg_class[i],
+			  sizeof(struct p2p_reg_class));
+		j++;
+	}
+	dst->reg_classes = j;
+}
+
+
+int p2p_remove_6ghz_channels(unsigned int *pref_freq_list, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (is_6ghz_freq(pref_freq_list[i])) {
+			wpa_printf(MSG_DEBUG, "P2P: Remove 6 GHz channel %d",
+				   pref_freq_list[i]);
+			size--;
+			os_memmove(&pref_freq_list[i], &pref_freq_list[i + 1],
+				   (size - i) * sizeof(pref_freq_list[0]));
+			i--;
+		}
+	}
+	return i;
+}
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index 2fe88ac..657de93 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -3057,12 +3057,12 @@
 
 
 /**
- * ieee802_1x_kay_mkpdu_sanity_check -
- * Sanity checks specified in IEEE Std 802.1X-2010, 11.11.2 (Validation of
+ * ieee802_1x_kay_mkpdu_validity_check -
+ * Validity checks specified in IEEE Std 802.1X-2010, 11.11.2 (Validation of
  * MKPDUs)
  */
-static int ieee802_1x_kay_mkpdu_sanity_check(struct ieee802_1x_kay *kay,
-					     const u8 *buf, size_t len)
+static int ieee802_1x_kay_mkpdu_validity_check(struct ieee802_1x_kay *kay,
+					       const u8 *buf, size_t len)
 {
 	struct ieee8023_hdr *eth_hdr;
 	struct ieee802_1x_hdr *eapol_hdr;
@@ -3215,7 +3215,7 @@
 
 	wpa_printf(MSG_DEBUG, "KaY: Decode received MKPDU (ifname=%s)",
 		   kay->if_name);
-	if (ieee802_1x_kay_mkpdu_sanity_check(kay, buf, len))
+	if (ieee802_1x_kay_mkpdu_validity_check(kay, buf, len))
 		return -1;
 
 	/* handle basic parameter set */
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index bfcb944..ee9e46d 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -7,6 +7,7 @@
  */
 
 #include "includes.h"
+#include <net/if.h>
 
 #include "common.h"
 #include "radius.h"
@@ -814,7 +815,7 @@
 {
 	struct radius_client_data *radius = eloop_ctx;
 	struct hostapd_radius_servers *conf = radius->conf;
-	RadiusType msg_type = (RadiusType) sock_ctx;
+	RadiusType msg_type = (uintptr_t) sock_ctx;
 	int len, roundtrip;
 	unsigned char buf[RADIUS_MAX_MSG_LEN];
 	struct msghdr msghdr = {0};
@@ -1168,6 +1169,29 @@
 		return -1;
 	}
 
+	/* Force a reconnect by disconnecting the socket first */
+	if (connect(sel_sock, (struct sockaddr *) &disconnect_addr,
+		    sizeof(disconnect_addr)) < 0)
+		wpa_printf(MSG_INFO, "disconnect[radius]: %s", strerror(errno));
+
+#ifdef __linux__
+	if (conf->force_client_dev && conf->force_client_dev[0]) {
+		if (setsockopt(sel_sock, SOL_SOCKET, SO_BINDTODEVICE,
+			       conf->force_client_dev,
+			       os_strlen(conf->force_client_dev)) < 0) {
+			wpa_printf(MSG_ERROR,
+				   "RADIUS: setsockopt[SO_BINDTODEVICE]: %s",
+				   strerror(errno));
+			/* Probably not a critical error; continue on and hope
+			 * for the best. */
+		} else {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS: Bound client socket to device: %s",
+				   conf->force_client_dev);
+		}
+	}
+#endif /* __linux__ */
+
 	if (conf->force_client_addr) {
 		switch (conf->client_addr.af) {
 		case AF_INET:
@@ -1200,11 +1224,6 @@
 		}
 	}
 
-	/* Force a reconnect by disconnecting the socket first */
-	if (connect(sel_sock, (struct sockaddr *) &disconnect_addr,
-		    sizeof(disconnect_addr)) < 0)
-		wpa_printf(MSG_INFO, "disconnect[radius]: %s", strerror(errno));
-
 	if (connect(sel_sock, addr, addrlen) < 0) {
 		wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
 		return -1;
diff --git a/src/radius/radius_client.h b/src/radius/radius_client.h
index 8ca0874..687cd81 100644
--- a/src/radius/radius_client.h
+++ b/src/radius/radius_client.h
@@ -174,6 +174,11 @@
 	 * force_client_addr - Whether to force client (local) address
 	 */
 	int force_client_addr;
+
+	/**
+	 * force_client_dev - Bind the socket to a specified interface, if set
+	 */
+	char *force_client_dev;
 };
 
 
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index b124dd9..93cc9a7 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -28,6 +28,8 @@
 
 	void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx,
 			enum pmksa_free_reason reason);
+	bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry,
+			      void *ctx);
 	void *ctx;
 };
 
@@ -59,14 +61,35 @@
 {
 	struct rsn_pmksa_cache *pmksa = eloop_ctx;
 	struct os_reltime now;
+	struct rsn_pmksa_cache_entry *prev = NULL, *tmp;
+	struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
 
 	os_get_reltime(&now);
-	while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
-		struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
-		pmksa->pmksa = entry->next;
+	while (entry && entry->expiration <= now.sec) {
+		if (wpa_key_mgmt_sae(entry->akmp) &&
+		    pmksa->is_current_cb(entry, pmksa->ctx)) {
+			/* Do not expire the currently used PMKSA entry for SAE
+			 * since there is no convenient mechanism for
+			 * reauthenticating during an association with SAE. The
+			 * expired entry will be removed after this association
+			 * has been lost. */
+			wpa_printf(MSG_DEBUG,
+				   "RSN: postpone PMKSA cache entry expiration for SAE with "
+				   MACSTR, MAC2STR(entry->aa));
+			prev = entry;
+			entry = entry->next;
+			continue;
+		}
+
 		wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
 			   MACSTR, MAC2STR(entry->aa));
-		pmksa_cache_free_entry(pmksa, entry, PMKSA_EXPIRE);
+		if (prev)
+			prev->next = entry->next;
+		else
+			pmksa->pmksa = entry->next;
+		tmp = entry;
+		entry = entry->next;
+		pmksa_cache_free_entry(pmksa, tmp, PMKSA_EXPIRE);
 	}
 
 	pmksa_cache_set_expiration(pmksa);
@@ -93,13 +116,32 @@
 		return;
 	os_get_reltime(&now);
 	sec = pmksa->pmksa->expiration - now.sec;
-	if (sec < 0)
+	if (sec < 0) {
 		sec = 0;
+		if (wpa_key_mgmt_sae(pmksa->pmksa->akmp) &&
+		    pmksa->is_current_cb(pmksa->pmksa, pmksa->ctx)) {
+			/* Do not continue polling for the current PMKSA entry
+			 * from SAE to expire every second. Use the expiration
+			 * time to the following entry, if any, and wait at
+			 * maximum 10 minutes to check again.
+			 */
+			entry = pmksa->pmksa->next;
+			if (entry) {
+				sec = entry->expiration - now.sec;
+				if (sec < 0)
+					sec = 0;
+				else if (sec > 600)
+					sec = 600;
+			} else {
+				sec = 600;
+			}
+		}
+	}
 	eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
 
 	entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
 		pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, 0);
-	if (entry) {
+	if (entry && !wpa_key_mgmt_sae(entry->akmp)) {
 		sec = pmksa->pmksa->reauth_time - now.sec;
 		if (sec < 0)
 			sec = 0;
@@ -214,7 +256,8 @@
 				   "that was based on the old PMK");
 			if (!pos->opportunistic)
 				pmksa_cache_flush(pmksa, entry->network_ctx,
-						  pos->pmk, pos->pmk_len);
+						  pos->pmk, pos->pmk_len,
+						  false);
 			pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
 			break;
 		}
@@ -285,9 +328,11 @@
  * @network_ctx: Network configuration context or %NULL to flush all entries
  * @pmk: PMK to match for or %NULL to match all PMKs
  * @pmk_len: PMK length
+ * @external_only: Flush only PMKSA cache entries configured by external
+ * applications
  */
 void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
-		       const u8 *pmk, size_t pmk_len)
+		       const u8 *pmk, size_t pmk_len, bool external_only)
 {
 	struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp;
 	int removed = 0;
@@ -298,7 +343,8 @@
 		     network_ctx == NULL) &&
 		    (pmk == NULL ||
 		     (pmk_len == entry->pmk_len &&
-		      os_memcmp(pmk, entry->pmk, pmk_len) == 0))) {
+		      os_memcmp(pmk, entry->pmk, pmk_len) == 0)) &&
+		    (!external_only || entry->external)) {
 			wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry "
 				   "for " MACSTR, MAC2STR(entry->aa));
 			if (prev)
@@ -377,9 +423,11 @@
 {
 	struct rsn_pmksa_cache_entry *new_entry;
 	os_time_t old_expiration = old_entry->expiration;
+	os_time_t old_reauth_time = old_entry->reauth_time;
 	const u8 *pmkid = NULL;
 
-	if (wpa_key_mgmt_sae(old_entry->akmp))
+	if (wpa_key_mgmt_sae(old_entry->akmp) ||
+	    wpa_key_mgmt_fils(old_entry->akmp))
 		pmkid = old_entry->pmkid;
 	new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
 				    pmkid, NULL, 0,
@@ -392,6 +440,7 @@
 
 	/* TODO: reorder entries based on expiration time? */
 	new_entry->expiration = old_expiration;
+	new_entry->reauth_time = old_reauth_time;
 	new_entry->opportunistic = 1;
 
 	return new_entry;
@@ -649,6 +698,8 @@
 struct rsn_pmksa_cache *
 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
 				 void *ctx, enum pmksa_free_reason reason),
+		 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry,
+				       void *ctx),
 		 void *ctx, struct wpa_sm *sm)
 {
 	struct rsn_pmksa_cache *pmksa;
@@ -656,6 +707,7 @@
 	pmksa = os_zalloc(sizeof(*pmksa));
 	if (pmksa) {
 		pmksa->free_cb = free_cb;
+		pmksa->is_current_cb = is_current_cb;
 		pmksa->ctx = ctx;
 		pmksa->sm = sm;
 	}
@@ -663,4 +715,37 @@
 	return pmksa;
 }
 
+
+void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa)
+{
+	struct rsn_pmksa_cache_entry *entry;
+	struct os_reltime now;
+
+	if (!pmksa || !pmksa->pmksa)
+		return;
+
+	os_get_reltime(&now);
+	for (entry = pmksa->pmksa; entry; entry = entry->next) {
+		u32 life_time;
+		u8 reauth_threshold;
+
+		if (entry->expiration - now.sec < 1 ||
+		    entry->reauth_time - now.sec < 1)
+			continue;
+
+		life_time = entry->expiration - now.sec;
+		reauth_threshold = (entry->reauth_time - now.sec) * 100 /
+			life_time;
+		if (!reauth_threshold)
+			continue;
+
+		wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa,
+				 entry->pmkid,
+				 entry->fils_cache_id_set ?
+				 entry->fils_cache_id : NULL,
+				 entry->pmk, entry->pmk_len, life_time,
+				 reauth_threshold, entry->akmp);
+	}
+}
+
 #endif /* IEEE8021X_EAPOL */
diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h
index 83faa05..b801268 100644
--- a/src/rsn_supp/pmksa_cache.h
+++ b/src/rsn_supp/pmksa_cache.h
@@ -43,6 +43,7 @@
 	 */
 	void *network_ctx;
 	int opportunistic;
+	bool external;
 };
 
 struct rsn_pmksa_cache;
@@ -58,6 +59,8 @@
 struct rsn_pmksa_cache *
 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
 				 void *ctx, enum pmksa_free_reason reason),
+		 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry,
+				       void *ctx),
 		 void *ctx, struct wpa_sm *sm);
 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
@@ -84,13 +87,16 @@
 pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
 			      void *network_ctx, const u8 *aa, int akmp);
 void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
-		       const u8 *pmk, size_t pmk_len);
+		       const u8 *pmk, size_t pmk_len, bool external_only);
+void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa);
 
 #else /* IEEE8021X_EAPOL */
 
 static inline struct rsn_pmksa_cache *
 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
 				 void *ctx, enum pmksa_free_reason reason),
+		 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry,
+				       void *ctx),
 		 void *ctx, struct wpa_sm *sm)
 {
 	return (void *) -1;
@@ -157,7 +163,12 @@
 
 static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa,
 				     void *network_ctx,
-				     const u8 *pmk, size_t pmk_len)
+				     const u8 *pmk, size_t pmk_len,
+				     bool external_only)
+{
+}
+
+static inline void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa)
 {
 }
 
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 7c4ef19..c26a63d 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -136,6 +136,9 @@
 
 	struct ieee80211_ht_capabilities *ht_capabilities;
 	struct ieee80211_vht_capabilities *vht_capabilities;
+	struct ieee80211_he_capabilities *he_capabilities;
+	size_t he_capab_len;
+	struct ieee80211_he_6ghz_band_cap *he_6ghz_band_capabilities;
 
 	u8 qos_info;
 
@@ -703,6 +706,10 @@
 	peer->ht_capabilities = NULL;
 	os_free(peer->vht_capabilities);
 	peer->vht_capabilities = NULL;
+	os_free(peer->he_capabilities);
+	peer->he_capabilities = NULL;
+	os_free(peer->he_6ghz_band_capabilities);
+	peer->he_6ghz_band_capabilities = NULL;
 	os_free(peer->ext_capab);
 	peer->ext_capab = NULL;
 	os_free(peer->supp_channels);
@@ -1414,6 +1421,8 @@
 
 skip_ies:
 
+	if (peer->he_capabilities)
+		peer_capab |= TDLS_PEER_HE;
 	if (peer->vht_capabilities)
 		peer_capab |= TDLS_PEER_VHT;
 	if (peer->ht_capabilities)
@@ -1652,6 +1661,56 @@
 }
 
 
+static int copy_peer_he_capab(const struct wpa_eapol_ie_parse *kde,
+			      struct wpa_tdls_peer *peer)
+{
+	if (!kde->he_capabilities) {
+		wpa_printf(MSG_DEBUG, "TDLS: No HE capabilities received");
+		return 0;
+	}
+
+	os_free(peer->he_capabilities);
+	peer->he_capab_len = 0;
+	peer->he_capabilities = os_memdup(kde->he_capabilities,
+					  kde->he_capab_len);
+	if (!peer->he_capabilities)
+		return -1;
+
+	peer->he_capab_len = kde->he_capab_len;
+	wpa_hexdump(MSG_DEBUG, "TDLS: Peer HE capabilities",
+		    peer->he_capabilities, peer->he_capab_len);
+
+	return 0;
+}
+
+
+static int copy_peer_he_6ghz_band_capab(const struct wpa_eapol_ie_parse *kde,
+					struct wpa_tdls_peer *peer)
+{
+	if (!kde->he_6ghz_capabilities) {
+		wpa_printf(MSG_DEBUG,
+			   "TDLS: No HE 6 GHz band capabilities received");
+		return 0;
+	}
+
+	if (!peer->he_6ghz_band_capabilities) {
+		peer->he_6ghz_band_capabilities =
+			os_zalloc(sizeof(struct ieee80211_he_6ghz_band_cap));
+		if (peer->he_6ghz_band_capabilities == NULL)
+			return -1;
+	}
+
+	os_memcpy(peer->he_6ghz_band_capabilities, kde->he_6ghz_capabilities,
+		  sizeof(struct ieee80211_he_6ghz_band_cap));
+
+	wpa_hexdump(MSG_DEBUG, "TDLS: Peer 6 GHz band HE capabilities",
+		    peer->he_6ghz_band_capabilities,
+		    sizeof(struct ieee80211_he_6ghz_band_cap));
+
+	return 0;
+}
+
+
 static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
 			       struct wpa_tdls_peer *peer)
 {
@@ -1761,6 +1820,9 @@
 				       peer->supp_rates, peer->supp_rates_len,
 				       peer->ht_capabilities,
 				       peer->vht_capabilities,
+				       peer->he_capabilities,
+				       peer->he_capab_len,
+				       peer->he_6ghz_band_capabilities,
 				       peer->qos_info, peer->wmm_capable,
 				       peer->ext_capab, peer->ext_capab_len,
 				       peer->supp_channels,
@@ -1896,7 +1958,9 @@
 	if (copy_peer_ht_capab(&kde, peer) < 0)
 		goto error;
 
-	if (copy_peer_vht_capab(&kde, peer) < 0)
+	if (copy_peer_vht_capab(&kde, peer) < 0 ||
+	    copy_peer_he_capab(&kde, peer) < 0 ||
+	    copy_peer_he_6ghz_band_capab(&kde, peer) < 0)
 		goto error;
 
 	if (copy_peer_ext_capab(&kde, peer) < 0)
@@ -1925,7 +1989,8 @@
 			   "TDLS setup - send own request");
 		peer->initiator = 1;
 		wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
-					NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0);
+					NULL, NULL, 0, NULL, 0, 0, NULL, 0,
+					NULL, 0, NULL, 0);
 		if (wpa_tdls_send_tpk_m1(sm, peer) == -2) {
 			peer = NULL;
 			goto error;
@@ -2303,7 +2368,9 @@
 	if (copy_peer_ht_capab(&kde, peer) < 0)
 		goto error;
 
-	if (copy_peer_vht_capab(&kde, peer) < 0)
+	if (copy_peer_vht_capab(&kde, peer) < 0 ||
+	    copy_peer_he_capab(&kde, peer) < 0 ||
+	    copy_peer_he_6ghz_band_capab(&kde, peer) < 0)
 		goto error;
 
 	if (copy_peer_ext_capab(&kde, peer) < 0)
@@ -2690,7 +2757,8 @@
 
 	/* add the peer to the driver as a "setup in progress" peer */
 	if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
-				    NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
+				    NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0,
+				    NULL, 0)) {
 		wpa_tdls_disable_peer_link(sm, peer);
 		return -1;
 	}
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index ede782c..5ff11bd 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -452,6 +452,10 @@
 		buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
 					 NULL, 0, &buflen, NULL);
 		if (buf) {
+			/* Set and reset eapFail to allow EAP state machine to
+			 * proceed with new authentication. */
+			eapol_sm_notify_eap_fail(sm->eapol, true);
+			eapol_sm_notify_eap_fail(sm->eapol, false);
 			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
 					  buf, buflen);
 			os_free(buf);
@@ -606,8 +610,8 @@
 #endif /* CONFIG_OWE */
 
 	if (sm->force_kdk_derivation ||
-	    (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
-	     sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+	    (sm->secure_ltf &&
+	     ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
 		kdk_len = WPA_KDK_MAX_LEN;
 	else
 		kdk_len = 0;
@@ -2342,6 +2346,16 @@
 }
 
 
+void wpa_sm_aborted_external_cached(struct wpa_sm *sm)
+{
+	if (sm && sm->cur_pmksa && sm->cur_pmksa->external) {
+		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+			"RSN: Cancelling external PMKSA caching attempt");
+		sm->cur_pmksa = NULL;
+	}
+}
+
+
 static void wpa_eapol_key_dump(struct wpa_sm *sm,
 			       const struct wpa_eapol_key *key,
 			       unsigned int key_data_len,
@@ -2890,6 +2904,15 @@
 }
 
 
+static bool wpa_sm_pmksa_is_current_cb(struct rsn_pmksa_cache_entry *entry,
+				       void *ctx)
+{
+	struct wpa_sm *sm = ctx;
+
+	return sm->cur_pmksa == entry;
+}
+
+
 /**
  * wpa_sm_init - Initialize WPA state machine
  * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
@@ -2913,7 +2936,8 @@
 	sm->dot11RSNAConfigPMKReauthThreshold = 70;
 	sm->dot11RSNAConfigSATimeout = 60;
 
-	sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm);
+	sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb,
+				     wpa_sm_pmksa_is_current_cb, sm, sm);
 	if (sm->pmksa == NULL) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
 			"RSN: PMKSA cache initialization failed");
@@ -3109,9 +3133,11 @@
 #endif /* CONFIG_IEEE80211R */
 
 	if (bssid) {
-		pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
-				bssid, sm->own_addr,
-				sm->network_ctx, sm->key_mgmt, NULL);
+		sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len,
+						pmkid, NULL, 0, bssid,
+						sm->own_addr,
+						sm->network_ctx, sm->key_mgmt,
+						NULL);
 	}
 }
 
@@ -3862,7 +3888,13 @@
 
 void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
 {
-	pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
+	pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, false);
+}
+
+
+void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
+{
+	pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, true);
 }
 
 #ifdef CONFIG_DRIVER_NL80211_BRCM
@@ -4413,8 +4445,8 @@
 	}
 
 	if (sm->force_kdk_derivation ||
-	    (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
-	     sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+	    (sm->secure_ltf &&
+	     ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
 		kdk_len = WPA_KDK_MAX_LEN;
 	else
 		kdk_len = 0;
@@ -5267,3 +5299,10 @@
 					key_mgmt, 0);
 }
 #endif /* CONFIG_PASN */
+
+
+void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm)
+{
+	if (sm)
+		pmksa_cache_reconfig(sm->pmksa);
+}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 95c58f6..3d5e883 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -69,6 +69,9 @@
 				size_t supp_rates_len,
 				const struct ieee80211_ht_capabilities *ht_capab,
 				const struct ieee80211_vht_capabilities *vht_capab,
+				const struct ieee80211_he_capabilities *he_capab,
+				size_t he_capab_len,
+				const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
 				u8 qosinfo, int wmm, const u8 *ext_capab,
 				size_t ext_capab_len, const u8 *supp_channels,
 				size_t supp_channels_len,
@@ -178,6 +181,7 @@
 		     struct wpa_ie_data *data);
 
 void wpa_sm_aborted_cached(struct wpa_sm *sm);
+void wpa_sm_aborted_external_cached(struct wpa_sm *sm);
 int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 		    const u8 *buf, size_t len);
 int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data);
@@ -203,6 +207,7 @@
 void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr);
 
 void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx);
+void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx);
 
 int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf);
 
@@ -216,6 +221,7 @@
 			    const u8 *ptk_kck, size_t ptk_kck_len,
 			    const u8 *ptk_kek, size_t ptk_kek_len);
 int wpa_fils_is_completed(struct wpa_sm *sm);
+void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm);
 
 #else /* CONFIG_NO_WPA */
 
@@ -356,6 +362,10 @@
 {
 }
 
+static inline void wpa_sm_aborted_external_cached(struct wpa_sm *sm)
+{
+}
+
 static inline int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 				  const u8 *buf, size_t len)
 {
@@ -395,6 +405,11 @@
 {
 }
 
+static inline void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm,
+						     void *network_ctx)
+{
+}
+
 static inline void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm,
 					    void *network_ctx)
 {
@@ -416,6 +431,10 @@
 	return 0;
 }
 
+static inline void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm)
+{
+}
+
 #endif /* CONFIG_NO_WPA */
 
 #ifdef CONFIG_IEEE80211R
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index caad760..2b172b7 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -69,8 +69,8 @@
 	wpa_ft_pasn_store_r1kh(sm, src_addr);
 
 	if (sm->force_kdk_derivation ||
-	    (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
-	     sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+	    (sm->secure_ltf &&
+	     ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
 		kdk_len = WPA_KDK_MAX_LEN;
 	else
 		kdk_len = 0;
@@ -672,8 +672,8 @@
 	wpa_ft_pasn_store_r1kh(sm, bssid);
 
 	if (sm->force_kdk_derivation ||
-	    (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
-	     sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+	    (sm->secure_ltf &&
+	     ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
 		kdk_len = WPA_KDK_MAX_LEN;
 	else
 		kdk_len = 0;
@@ -1221,7 +1221,7 @@
 					 ci.seg1_idx) != OCI_SUCCESS) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
 				"addr=" MACSTR " frame=ft-assoc error=%s",
-				MAC2STR(sm->bssid), ocv_errorstr);
+				MAC2STR(src_addr), ocv_errorstr);
 			return -1;
 		}
 	}
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 1dc9639..6cdce32 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -398,6 +398,9 @@
 			size_t supp_rates_len,
 			const struct ieee80211_ht_capabilities *ht_capab,
 			const struct ieee80211_vht_capabilities *vht_capab,
+			const struct ieee80211_he_capabilities *he_capab,
+			size_t he_capab_len,
+			const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
 			u8 qosinfo, int wmm, const u8 *ext_capab,
 			size_t ext_capab_len, const u8 *supp_channels,
 			size_t supp_channels_len, const u8 *supp_oper_classes,
@@ -407,7 +410,9 @@
 		return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
 						 aid, capability, supp_rates,
 						 supp_rates_len, ht_capab,
-						 vht_capab, qosinfo, wmm,
+						 vht_capab,
+						 he_capab, he_capab_len,
+						 he_6ghz_capab, qosinfo, wmm,
 						 ext_capab, ext_capab_len,
 						 supp_channels,
 						 supp_channels_len,
diff --git a/src/tls/asn1.c b/src/tls/asn1.c
index 2da7b4a..04d5320 100644
--- a/src/tls/asn1.c
+++ b/src/tls/asn1.c
@@ -129,6 +129,41 @@
 		return 1;
 	if (hdr->tag == ASN1_TAG_BOOLEAN && !asn1_valid_der_boolean(hdr))
 		return 0;
+	if (hdr->tag == ASN1_TAG_NULL && hdr->length != 0)
+		return 0;
+
+	/* Check for allowed primitive/constructed values */
+	if (hdr->constructed &&
+	    (hdr->tag == ASN1_TAG_BOOLEAN ||
+	     hdr->tag == ASN1_TAG_INTEGER ||
+	     hdr->tag == ASN1_TAG_NULL ||
+	     hdr->tag == ASN1_TAG_OID ||
+	     hdr->tag == ANS1_TAG_RELATIVE_OID ||
+	     hdr->tag == ASN1_TAG_REAL ||
+	     hdr->tag == ASN1_TAG_ENUMERATED ||
+	     hdr->tag == ASN1_TAG_BITSTRING ||
+	     hdr->tag == ASN1_TAG_OCTETSTRING ||
+	     hdr->tag == ASN1_TAG_NUMERICSTRING ||
+	     hdr->tag == ASN1_TAG_PRINTABLESTRING ||
+	     hdr->tag == ASN1_TAG_T61STRING ||
+	     hdr->tag == ASN1_TAG_VIDEOTEXSTRING ||
+	     hdr->tag == ASN1_TAG_VISIBLESTRING ||
+	     hdr->tag == ASN1_TAG_IA5STRING ||
+	     hdr->tag == ASN1_TAG_GRAPHICSTRING ||
+	     hdr->tag == ASN1_TAG_GENERALSTRING ||
+	     hdr->tag == ASN1_TAG_UNIVERSALSTRING ||
+	     hdr->tag == ASN1_TAG_UTF8STRING ||
+	     hdr->tag == ASN1_TAG_BMPSTRING ||
+	     hdr->tag == ASN1_TAG_CHARACTERSTRING ||
+	     hdr->tag == ASN1_TAG_UTCTIME ||
+	     hdr->tag == ASN1_TAG_GENERALIZEDTIME ||
+	     hdr->tag == ASN1_TAG_TIME))
+		return 0;
+	if (!hdr->constructed &&
+	    (hdr->tag == ASN1_TAG_SEQUENCE ||
+	     hdr->tag == ASN1_TAG_SET))
+		return 0;
+
 	return 1;
 }
 
@@ -151,18 +186,35 @@
 	hdr->constructed = !!(hdr->identifier & (1 << 5));
 
 	if ((hdr->identifier & 0x1f) == 0x1f) {
+		size_t ext_len = 0;
+
 		hdr->tag = 0;
+		if (pos == end || (*pos & 0x7f) == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "ASN.1: Invalid extended tag (first octet has to be included with at least one nonzero bit for the tag value)");
+			return -1;
+		}
 		do {
 			if (pos >= end) {
 				wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
 					   "underflow");
 				return -1;
 			}
+			ext_len++;
 			tmp = *pos++;
 			wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
 				   "0x%02x", tmp);
 			hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
 		} while (tmp & 0x80);
+		wpa_printf(MSG_MSGDUMP, "ASN.1: Extended Tag: 0x%x (len=%zu)",
+			   hdr->tag, ext_len);
+		if ((hdr->class != ASN1_CLASS_PRIVATE && hdr->tag < 31) ||
+		    ext_len * 7 > sizeof(hdr->tag) * 8) {
+			wpa_printf(MSG_DEBUG,
+				   "ASN.1: Invalid or unsupported (too large) extended Tag: 0x%x (len=%zu)",
+				   hdr->tag, ext_len);
+			return -1;
+		}
 	} else
 		hdr->tag = hdr->identifier & 0x1f;
 
@@ -179,6 +231,11 @@
 		}
 		tmp &= 0x7f; /* number of subsequent octets */
 		hdr->length = 0;
+		if (tmp == 0 || pos == end || *pos == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "ASN.1: Definite long form of the length does not start with a nonzero value");
+			return -1;
+		}
 		if (tmp > 4) {
 			wpa_printf(MSG_DEBUG, "ASN.1: Too long length field");
 			return -1;
@@ -191,6 +248,11 @@
 			}
 			hdr->length = (hdr->length << 8) | *pos++;
 		}
+		if (hdr->length < 128) {
+			wpa_printf(MSG_DEBUG,
+				   "ASN.1: Definite long form of the length used with too short length");
+			return -1;
+		}
 	} else {
 		/* Short form - length 0..127 in one octet */
 		hdr->length = tmp;
@@ -203,7 +265,25 @@
 
 	hdr->payload = pos;
 
-	return asn1_valid_der(hdr) ? 0 : -1;
+	if (!asn1_valid_der(hdr)) {
+		asn1_print_hdr(hdr, "ASN.1: Invalid DER encoding: ");
+		return -1;
+	}
+	return 0;
+}
+
+
+void asn1_print_hdr(const struct asn1_hdr *hdr, const char *title)
+{
+	wpa_printf(MSG_DEBUG, "%sclass %d constructed %d tag 0x%x",
+		   title, hdr->class, hdr->constructed, hdr->tag);
+}
+
+
+void asn1_unexpected(const struct asn1_hdr *hdr, const char *title)
+{
+	wpa_printf(MSG_DEBUG, "%s - found class %d constructed %d tag 0x%x",
+		   title, hdr->class, hdr->constructed, hdr->tag);
 }
 
 
@@ -256,12 +336,9 @@
 {
 	struct asn1_hdr hdr;
 
-	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
-		return -1;
-
-	if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
-		wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
-			   "tag 0x%x", hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0 ||
+	    !asn1_is_oid(&hdr)) {
+		asn1_unexpected(&hdr, "ASN.1: Expected OID");
 		return -1;
 	}
 
@@ -360,13 +437,9 @@
 	const u8 *pos;
 	int value;
 
-	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
-		return -1;
-
-	if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG,
-			   "ASN.1: Expected INTEGER - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0 ||
+	    !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "ASN.1: Expected INTEGER");
 		return -1;
 	}
 
@@ -393,12 +466,8 @@
 int asn1_get_sequence(const u8 *buf, size_t len, struct asn1_hdr *hdr,
 		      const u8 **next)
 {
-	if (asn1_get_next(buf, len, hdr) < 0 ||
-	    hdr->class != ASN1_CLASS_UNIVERSAL ||
-	    hdr->tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "ASN.1: Expected SEQUENCE - found class %d tag 0x%x",
-			   hdr->class, hdr->tag);
+	if (asn1_get_next(buf, len, hdr) < 0 || !asn1_is_sequence(hdr)) {
+		asn1_unexpected(hdr, "ASN.1: Expected SEQUENCE");
 		return -1;
 	}
 
diff --git a/src/tls/asn1.h b/src/tls/asn1.h
index 6878a4f..a4d1be4 100644
--- a/src/tls/asn1.h
+++ b/src/tls/asn1.h
@@ -23,11 +23,12 @@
 #define ASN1_TAG_EMBEDDED_PDV	0x0B /* not yet parsed */
 #define ASN1_TAG_UTF8STRING	0x0C /* not yet parsed */
 #define ANS1_TAG_RELATIVE_OID	0x0D
+#define ASN1_TAG_TIME		0x0E
 #define ASN1_TAG_SEQUENCE	0x10 /* shall be constructed */
 #define ASN1_TAG_SET		0x11
 #define ASN1_TAG_NUMERICSTRING	0x12 /* not yet parsed */
 #define ASN1_TAG_PRINTABLESTRING	0x13
-#define ASN1_TAG_TG1STRING	0x14 /* not yet parsed */
+#define ASN1_TAG_T61STRING	0x14 /* not yet parsed */
 #define ASN1_TAG_VIDEOTEXSTRING	0x15 /* not yet parsed */
 #define ASN1_TAG_IA5STRING	0x16
 #define ASN1_TAG_UTCTIME	0x17
@@ -59,6 +60,8 @@
 
 
 int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr);
+void asn1_print_hdr(const struct asn1_hdr *hdr, const char *title);
+void asn1_unexpected(const struct asn1_hdr *hdr, const char *title);
 int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid);
 int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
 		 const u8 **next);
@@ -82,6 +85,108 @@
 				  const struct wpabuf *params);
 struct wpabuf * asn1_encaps(struct wpabuf *buf, u8 class, u8 tag);
 
+static inline bool asn1_is_oid(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_OID;
+}
+
+static inline bool asn1_is_boolean(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_BOOLEAN;
+}
+
+static inline bool asn1_is_integer(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_INTEGER;
+}
+
+static inline bool asn1_is_enumerated(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_ENUMERATED;
+}
+
+static inline bool asn1_is_sequence(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_SEQUENCE;
+}
+
+static inline bool asn1_is_set(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_SET;
+}
+
+static inline bool asn1_is_octetstring(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_OCTETSTRING;
+}
+
+static inline bool asn1_is_bitstring(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_BITSTRING;
+}
+
+static inline bool asn1_is_utctime(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_UTCTIME;
+}
+
+static inline bool asn1_is_generalizedtime(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_GENERALIZEDTIME;
+}
+
+static inline bool asn1_is_string_type(const struct asn1_hdr *hdr)
+{
+	if (hdr->class != ASN1_CLASS_UNIVERSAL || hdr->constructed)
+		return false;
+	return hdr->tag == ASN1_TAG_UTF8STRING ||
+		hdr->tag == ASN1_TAG_NUMERICSTRING ||
+		hdr->tag == ASN1_TAG_PRINTABLESTRING ||
+		hdr->tag == ASN1_TAG_T61STRING ||
+		hdr->tag == ASN1_TAG_VIDEOTEXSTRING ||
+		hdr->tag == ASN1_TAG_IA5STRING ||
+		hdr->tag == ASN1_TAG_GRAPHICSTRING ||
+		hdr->tag == ASN1_TAG_VISIBLESTRING ||
+		hdr->tag == ASN1_TAG_GENERALSTRING ||
+		hdr->tag == ASN1_TAG_UNIVERSALSTRING ||
+		hdr->tag == ASN1_TAG_CHARACTERSTRING ||
+		hdr->tag == ASN1_TAG_BMPSTRING;
+}
+
+static inline bool asn1_is_bmpstring(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_BMPSTRING;
+}
+
+static inline bool asn1_is_utf8string(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_UTF8STRING;
+}
+
+static inline bool asn1_is_null(const struct asn1_hdr *hdr)
+{
+	return hdr->class == ASN1_CLASS_UNIVERSAL &&
+		hdr->tag == ASN1_TAG_NULL;
+}
+
+static inline bool asn1_is_cs_tag(const struct asn1_hdr *hdr, unsigned int tag)
+{
+	return hdr->class == ASN1_CLASS_CONTEXT_SPECIFIC &&
+		hdr->tag == tag;
+}
+
 extern const struct asn1_oid asn1_sha1_oid;
 extern const struct asn1_oid asn1_sha256_oid;
 extern const struct asn1_oid asn1_ec_public_key_oid;
diff --git a/src/tls/pkcs1.c b/src/tls/pkcs1.c
index 654c01b..49e439d 100644
--- a/src/tls/pkcs1.c
+++ b/src/tls/pkcs1.c
@@ -236,14 +236,14 @@
 	 *
 	 */
 	if (asn1_get_next(decrypted, decrypted_len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #1: Expected SEQUENCE (DigestInfo) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #1: Expected SEQUENCE (DigestInfo)");
 		os_free(decrypted);
 		return -1;
 	}
+	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: DigestInfo",
+		    hdr.payload, hdr.length);
 
 	pos = hdr.payload;
 	end = pos + hdr.length;
@@ -257,14 +257,14 @@
 	 */
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #1: Expected SEQUENCE (AlgorithmIdentifier) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #1: Expected SEQUENCE (AlgorithmIdentifier)");
 		os_free(decrypted);
 		return -1;
 	}
+	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: DigestAlgorithmIdentifier",
+		    hdr.payload, hdr.length);
 	da_end = hdr.payload + hdr.length;
 
 	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) {
@@ -273,6 +273,23 @@
 		os_free(decrypted);
 		return -1;
 	}
+	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: Digest algorithm parameters",
+		    next, da_end - next);
+
+	/*
+	 * RFC 5754: The correct encoding for the SHA2 algorithms would be to
+	 * omit the parameters, but there are implementation that encode these
+	 * as a NULL element. Allow these two cases and reject anything else.
+	 */
+	if (da_end > next &&
+	    (asn1_get_next(next, da_end - next, &hdr) < 0 ||
+	     !asn1_is_null(&hdr) ||
+	     hdr.payload + hdr.length != da_end)) {
+		wpa_printf(MSG_DEBUG,
+			   "PKCS #1: Unexpected digest algorithm parameters");
+		os_free(decrypted);
+		return -1;
+	}
 
 	if (!asn1_oid_equal(&oid, hash_alg)) {
 		char txt[100], txt2[100];
@@ -287,14 +304,11 @@
 
 	/* Digest ::= OCTET STRING */
 	pos = da_end;
-	end = decrypted + decrypted_len;
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #1: Expected OCTETSTRING (Digest) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #1: Expected OCTETSTRING (Digest)");
 		os_free(decrypted);
 		return -1;
 	}
@@ -310,13 +324,14 @@
 
 	os_free(decrypted);
 
-	if (hdr.payload + hdr.length != end) {
+	if (hdr.payload + hdr.length != decrypted + decrypted_len) {
 		wpa_printf(MSG_INFO,
 			   "PKCS #1: Extra data after signature - reject");
 
 		wpa_hexdump(MSG_DEBUG, "PKCS #1: Extra data",
 			    hdr.payload + hdr.length,
-			    end - hdr.payload - hdr.length);
+			    decrypted + decrypted_len - hdr.payload -
+			    hdr.length);
 		return -1;
 	}
 
diff --git a/src/tls/pkcs5.c b/src/tls/pkcs5.c
index a2ad83b..7bef89b 100644
--- a/src/tls/pkcs5.c
+++ b/src/tls/pkcs5.c
@@ -107,22 +107,18 @@
 	 */
 
 	if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #5: Expected SEQUENCE (PBES2-params) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected SEQUENCE (PBES2-params)");
 		return -1;
 	}
 	pos = hdr.payload;
 	end = hdr.payload + hdr.length;
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #5: Expected SEQUENCE (keyDerivationFunc) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected SEQUENCE (keyDerivationFunc)");
 		return -1;
 	}
 
@@ -161,11 +157,9 @@
 	 */
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #5: Expected SEQUENCE (PBKDF2-params) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected SEQUENCE (PBKDF2-params)");
 		return -1;
 	}
 
@@ -174,12 +168,10 @@
 
 	/* For now, only support the salt CHOICE specified (OCTET STRING) */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING ||
+	    !asn1_is_octetstring(&hdr) ||
 	    hdr.length > sizeof(params->salt)) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #5: Expected OCTET STRING (salt.specified) - found class %d tag 0x%x size %d",
-			   hdr.class, hdr.tag, hdr.length);
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected OCTET STRING (salt.specified)");
 		return -1;
 	}
 	pos = hdr.payload + hdr.length;
@@ -188,11 +180,8 @@
 	wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", params->salt, params->salt_len);
 
 	/* iterationCount INTEGER */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #5: Expected INTEGER - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #5: Expected INTEGER");
 		return -1;
 	}
 	if (hdr.length == 1) {
@@ -222,11 +211,9 @@
 	/* encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} */
 
 	if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #5: Expected SEQUENCE (encryptionScheme) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected SEQUENCE (encryptionScheme)");
 		return -1;
 	}
 
@@ -258,12 +245,9 @@
 	 * specifying the initialization vector for CBC mode.
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING ||
-	    hdr.length != 8) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #5: Expected OCTET STRING (SIZE(8)) (IV) - found class %d tag 0x%x size %d",
-			   hdr.class, hdr.tag, hdr.length);
+	    !asn1_is_octetstring(&hdr) || hdr.length != 8) {
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected OCTET STRING (SIZE(8)) (IV)");
 		return -1;
 	}
 	os_memcpy(params->iv, hdr.payload, hdr.length);
@@ -323,11 +307,9 @@
 	 */
 
 	if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE "
-			   "(PBEParameter) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected SEQUENCE (PBEParameter)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -335,12 +317,9 @@
 
 	/* salt OCTET STRING SIZE(8) (PKCS #5) or OCTET STRING (PKCS #12) */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING ||
-	    hdr.length > sizeof(params->salt)) {
-		wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) "
-			   "(salt) - found class %d tag 0x%x size %d",
-			   hdr.class, hdr.tag, hdr.length);
+	    !asn1_is_octetstring(&hdr) || hdr.length > sizeof(params->salt)) {
+		asn1_unexpected(&hdr,
+				"PKCS #5: Expected OCTETSTRING SIZE(8) (salt)");
 		return -1;
 	}
 	pos = hdr.payload + hdr.length;
@@ -351,9 +330,8 @@
 
 	/* iterationCount INTEGER */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found "
-			   "class %d tag 0x%x", hdr.class, hdr.tag);
+	    !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #5: Expected INTEGER");
 		return -1;
 	}
 	if (hdr.length == 1)
diff --git a/src/tls/pkcs8.c b/src/tls/pkcs8.c
index 52e43a4..75bbd12 100644
--- a/src/tls/pkcs8.c
+++ b/src/tls/pkcs8.c
@@ -27,22 +27,17 @@
 	/* PKCS #8, Chapter 6 */
 
 	/* PrivateKeyInfo ::= SEQUENCE */
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
-			   "header (SEQUENCE); assume PKCS #8 not used");
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #8: Does not start with PKCS #8 header (SEQUENCE)");
 		return NULL;
 	}
 	pos = hdr.payload;
 	end = pos + hdr.length;
 
 	/* version Version (Version ::= INTEGER) */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
-			   "class %d tag 0x%x; assume PKCS #8 not used",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #8: Expected INTEGER");
 		return NULL;
 	}
 
@@ -68,13 +63,9 @@
 
 	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
 	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
-			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
-			   "assume PKCS #8 not used",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #8: Expected SEQUENCE (AlgorithmIdentifier); assume PKCS #8 not used");
 		return NULL;
 	}
 
@@ -104,11 +95,9 @@
 
 	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
-			   "(privateKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #8: Expected OCTETSTRING (privateKey)");
 		return NULL;
 	}
 	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
@@ -139,12 +128,9 @@
 	 * EncryptedData ::= OCTET STRING
 	 */
 
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
-			   "header (SEQUENCE); assume encrypted PKCS #8 not "
-			   "used");
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #8: Does not start with PKCS #8 header (SEQUENCE); assume encrypted PKCS #8 not used");
 		return NULL;
 	}
 	pos = hdr.payload;
@@ -152,12 +138,9 @@
 
 	/* encryptionAlgorithm EncryptionAlgorithmIdentifier */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
-			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
-			   "assume encrypted PKCS #8 not used",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #8: Expected SEQUENCE (AlgorithmIdentifier); assume encrypted PKCS #8 not used");
 		return NULL;
 	}
 	enc_alg = hdr.payload;
@@ -166,11 +149,9 @@
 
 	/* encryptedData EncryptedData */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
-			   "(encryptedData) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #8: Expected OCTETSTRING (encryptedData)");
 		return NULL;
 	}
 
diff --git a/src/tls/rsa.c b/src/tls/rsa.c
index 1b01f58..56ae7d7 100644
--- a/src/tls/rsa.c
+++ b/src/tls/rsa.c
@@ -37,9 +37,8 @@
 		return NULL;
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "RSA: Expected INTEGER - found class %d "
-			   "tag 0x%x", hdr.class, hdr.tag);
+	    !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "RSA: Expected INTEGER");
 		return NULL;
 	}
 
@@ -84,12 +83,8 @@
 	 * }
 	 */
 
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE "
-			   "(public key) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "RSA: Expected SEQUENCE (public key)");
 		goto error;
 	}
 	pos = hdr.payload;
@@ -191,12 +186,8 @@
 	 *
 	 * Version ::= INTEGER -- shall be 0 for this version of the standard
 	 */
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE "
-			   "(public key) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "RSA: Expected SEQUENCE (public key)");
 		goto error;
 	}
 	pos = hdr.payload;
diff --git a/src/tls/tlsv1_client.c b/src/tls/tlsv1_client.c
index a147a54..486da16 100644
--- a/src/tls/tlsv1_client.c
+++ b/src/tls/tlsv1_client.c
@@ -38,9 +38,33 @@
 }
 
 
-int tls_derive_pre_master_secret(u8 *pre_master_secret)
+u16 tls_client_highest_ver(struct tlsv1_client *conn)
 {
-	WPA_PUT_BE16(pre_master_secret, TLS_VERSION);
+	u16 tls_version = TLS_VERSION;
+
+	/* Pick the highest locally enabled TLS version */
+#ifdef CONFIG_TLSV12
+	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
+	    tls_version == TLS_VERSION_1_2)
+		tls_version = TLS_VERSION_1_1;
+#endif /* CONFIG_TLSV12 */
+#ifdef CONFIG_TLSV11
+	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
+	    tls_version == TLS_VERSION_1_1)
+		tls_version = TLS_VERSION_1;
+#endif /* CONFIG_TLSV11 */
+	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
+	    tls_version == TLS_VERSION_1)
+		return 0;
+
+	return tls_version;
+}
+
+
+int tls_derive_pre_master_secret(struct tlsv1_client *conn,
+				 u8 *pre_master_secret)
+{
+	WPA_PUT_BE16(pre_master_secret, tls_client_highest_ver(conn));
 	if (os_get_random(pre_master_secret + 2,
 			  TLS_PRE_MASTER_SECRET_LEN - 2))
 		return -1;
@@ -844,6 +868,7 @@
 void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags)
 {
 	conn->flags = flags;
+	conn->rl.tls_version = tls_client_highest_ver(conn);
 }
 
 
diff --git a/src/tls/tlsv1_client_i.h b/src/tls/tlsv1_client_i.h
index 12ec8df..ccb2e15 100644
--- a/src/tls/tlsv1_client_i.h
+++ b/src/tls/tlsv1_client_i.h
@@ -78,7 +78,9 @@
 
 void tls_alert(struct tlsv1_client *conn, u8 level, u8 description);
 void tlsv1_client_free_dh(struct tlsv1_client *conn);
-int tls_derive_pre_master_secret(u8 *pre_master_secret);
+u16 tls_client_highest_ver(struct tlsv1_client *conn);
+int tls_derive_pre_master_secret(struct tlsv1_client *conn,
+				 u8 *pre_master_secret);
 int tls_derive_keys(struct tlsv1_client *conn,
 		    const u8 *pre_master_secret, size_t pre_master_secret_len);
 u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len);
diff --git a/src/tls/tlsv1_client_ocsp.c b/src/tls/tlsv1_client_ocsp.c
index 1d7b68c..128f4b5 100644
--- a/src/tls/tlsv1_client_ocsp.c
+++ b/src/tls/tlsv1_client_ocsp.c
@@ -138,12 +138,8 @@
 	 */
 
 	/* CertID ::= SEQUENCE */
-	if (asn1_get_next(resp, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (CertID) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "OCSP: Expected SEQUENCE (CertID)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -163,11 +159,9 @@
 
 	/* issuerNameHash  OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected OCTET STRING (issuerNameHash) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected OCTET STRING (issuerNameHash)");
 		return -1;
 	}
 	name_hash = hdr.payload;
@@ -190,11 +184,9 @@
 
 	/* issuerKeyHash  OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected OCTET STRING (issuerKeyHash) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected OCTET STRING (issuerKeyHash)");
 		return -1;
 	}
 	key_hash = hdr.payload;
@@ -214,11 +206,10 @@
 
 	/* serialNumber CertificateSerialNumber ::= INTEGER */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_INTEGER ||
+	    !asn1_is_integer(&hdr) ||
 	    hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) {
-		wpa_printf(MSG_DEBUG, "OCSP: No INTEGER tag found for serialNumber; class=%d tag=0x%x length=%u",
-			   hdr.class, hdr.tag, hdr.length);
+		asn1_unexpected(&hdr,
+				"OCSP: No INTEGER tag found for serialNumber");
 		return -1;
 	}
 	serial_number = hdr.payload;
@@ -240,12 +231,16 @@
 	pos = end;
 	end = resp + len;
 
-	/* certStatus CertStatus ::= CHOICE */
+	/* certStatus CertStatus ::= CHOICE
+	 *
+	 * CertStatus ::= CHOICE {
+	 *     good        [0]     IMPLICIT NULL,
+	 *     revoked     [1]     IMPLICIT RevokedInfo,
+	 *     unknown     [2]     IMPLICIT UnknownInfo }
+	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected CHOICE (CertStatus) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+		asn1_unexpected(&hdr, "OCSP: Expected CHOICE (CertStatus)");
 		return -1;
 	}
 	cert_status = hdr.tag;
@@ -257,8 +252,7 @@
 	os_get_time(&now);
 	/* thisUpdate  GeneralizedTime */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+	    !asn1_is_generalizedtime(&hdr) ||
 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag, &update) < 0) {
 		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse thisUpdate");
 		return -1;
@@ -275,12 +269,11 @@
 	if (pos < end) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0)
 			return -1;
-		if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && hdr.tag == 0) {
+		if (asn1_is_cs_tag(&hdr, 0) && hdr.constructed) {
 			const u8 *next = hdr.payload + hdr.length;
 
 			if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-			    hdr.class != ASN1_CLASS_UNIVERSAL ||
-			    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+			    !asn1_is_generalizedtime(&hdr) ||
 			    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
 					    &update) < 0) {
 				wpa_printf(MSG_DEBUG,
@@ -329,11 +322,9 @@
 	while (pos < end) {
 		/* SingleResponse ::= SEQUENCE */
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: Expected SEQUENCE (SingleResponse) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"OCSP: Expected SEQUENCE (SingleResponse)");
 			return TLS_OCSP_INVALID;
 		}
 		if (tls_process_ocsp_single_response(conn, cert, issuer,
@@ -381,12 +372,9 @@
 	 *    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
 	 */
 
-	if (asn1_get_next(resp, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (BasicOCSPResponse) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (BasicOCSPResponse)");
 		return TLS_OCSP_INVALID;
 	}
 	pos = hdr.payload;
@@ -394,11 +382,9 @@
 
 	/* ResponseData ::= SEQUENCE */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (ResponseData) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (ResponseData)");
 		return TLS_OCSP_INVALID;
 	}
 	resp_data = hdr.payload;
@@ -413,11 +399,9 @@
 
 	/* signature  BIT STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_BITSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected BITSTRING (signature) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_bitstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected BITSTRING (signature)");
 		return TLS_OCSP_INVALID;
 	}
 	if (hdr.length < 1)
@@ -439,11 +423,9 @@
 	/* certs  [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL */
 	if (pos < end) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-		    hdr.tag != 0) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: Expected [0] EXPLICIT (certs) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !hdr.constructed || !asn1_is_cs_tag(&hdr, 0)) {
+			asn1_unexpected(&hdr,
+					"OCSP: Expected [0] EXPLICIT (certs)");
 			return TLS_OCSP_INVALID;
 		}
 		wpa_hexdump(MSG_MSGDUMP, "OCSP: certs",
@@ -454,11 +436,9 @@
 			struct x509_certificate *cert;
 
 			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-			    hdr.class != ASN1_CLASS_UNIVERSAL ||
-			    hdr.tag != ASN1_TAG_SEQUENCE) {
-				wpa_printf(MSG_DEBUG,
-					   "OCSP: Expected SEQUENCE (Certificate) - found class %d tag 0x%x",
-					   hdr.class, hdr.tag);
+			    !asn1_is_sequence(&hdr)) {
+				asn1_unexpected(&hdr,
+						"OCSP: Expected SEQUENCE (Certificate)");
 				goto fail;
 			}
 
@@ -491,16 +471,12 @@
 	 * version [0] EXPLICIT Version DEFAULT v1
 	 * Version ::= INTEGER { v1(0) }
 	 */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 &&
-	    hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
-	    hdr.tag == 0) {
+	if (asn1_get_next(pos, end - pos, &hdr) == 0 && hdr.constructed &&
+	    asn1_is_cs_tag(&hdr, 0)) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_INTEGER ||
-		    hdr.length != 1) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: No INTEGER (len=1) tag found for version field - found class %d tag 0x%x length %d",
-				   hdr.class, hdr.tag, hdr.length);
+		    !asn1_is_integer(&hdr) || hdr.length != 1) {
+			asn1_unexpected(&hdr,
+					"OCSP: No INTEGER (len=1) tag found for version field");
 			goto fail;
 		}
 		wpa_printf(MSG_DEBUG, "OCSP: ResponseData version %u",
@@ -524,9 +500,7 @@
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected CHOICE (ResponderID) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+		asn1_unexpected(&hdr, "OCSP: Expected CHOICE (ResponderID)");
 		goto fail;
 	}
 
@@ -539,11 +513,9 @@
 	} else if (hdr.tag == 2) {
 		/* KeyHash ::= OCTET STRING */
 		if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_OCTETSTRING) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: Expected OCTET STRING (KeyHash) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_octetstring(&hdr)) {
+			asn1_unexpected(&hdr,
+					"OCSP: Expected OCTET STRING (KeyHash)");
 			goto fail;
 		}
 		key_hash = hdr.payload;
@@ -564,8 +536,7 @@
 
 	/* producedAt  GeneralizedTime */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+	    !asn1_is_generalizedtime(&hdr) ||
 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
 			    &produced_at) < 0) {
 		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse producedAt");
@@ -577,11 +548,9 @@
 
 	/* responses  SEQUENCE OF SingleResponse */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (responses) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (responses)");
 		goto fail;
 	}
 	responses = hdr.payload;
@@ -697,12 +666,9 @@
 	 *    responseBytes   [0] EXPLICIT ResponseBytes OPTIONAL }
 	 */
 
-	if (asn1_get_next(resp, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (OCSPResponse) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (OCSPResponse)");
 		return TLS_OCSP_INVALID;
 	}
 	pos = hdr.payload;
@@ -710,12 +676,9 @@
 
 	/* OCSPResponseStatus ::= ENUMERATED */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_ENUMERATED ||
-	    hdr.length != 1) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected ENUMERATED (responseStatus) - found class %d tag 0x%x length %u",
-			   hdr.class, hdr.tag, hdr.length);
+	    !asn1_is_enumerated(&hdr) || hdr.length != 1) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected ENUMERATED (responseStatus)");
 		return TLS_OCSP_INVALID;
 	}
 	resp_status = hdr.payload[0];
@@ -730,12 +693,10 @@
 	if (pos == end)
 		return TLS_OCSP_NO_RESPONSE;
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected [0] EXPLICIT (responseBytes) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected [0] EXPLICIT (responseBytes)");
 		return TLS_OCSP_INVALID;
 	}
 
@@ -746,11 +707,9 @@
 	 */
 
 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (ResponseBytes) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (ResponseBytes)");
 		return TLS_OCSP_INVALID;
 	}
 	pos = hdr.payload;
@@ -771,11 +730,8 @@
 
 	/* response       OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected OCTET STRING (response) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr, "OCSP: Expected OCTET STRING (response)");
 		return TLS_OCSP_INVALID;
 	}
 
diff --git a/src/tls/tlsv1_client_write.c b/src/tls/tlsv1_client_write.c
index 4a1147b..9b12618 100644
--- a/src/tls/tlsv1_client_write.c
+++ b/src/tls/tlsv1_client_write.c
@@ -48,21 +48,9 @@
 	struct os_time now;
 	size_t len, i;
 	u8 *ext_start;
-	u16 tls_version = TLS_VERSION;
+	u16 tls_version = tls_client_highest_ver(conn);
 
-	/* Pick the highest locally enabled TLS version */
-#ifdef CONFIG_TLSV12
-	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
-	    tls_version == TLS_VERSION_1_2)
-		tls_version = TLS_VERSION_1_1;
-#endif /* CONFIG_TLSV12 */
-#ifdef CONFIG_TLSV11
-	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
-	    tls_version == TLS_VERSION_1_1)
-		tls_version = TLS_VERSION_1;
-#endif /* CONFIG_TLSV11 */
-	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
-	    tls_version == TLS_VERSION_1) {
+	if (!tls_version) {
 		wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed");
 		return NULL;
 	}
@@ -474,7 +462,7 @@
 	size_t clen;
 	int res;
 
-	if (tls_derive_pre_master_secret(pre_master_secret) < 0 ||
+	if (tls_derive_pre_master_secret(conn, pre_master_secret) < 0 ||
 	    tls_derive_keys(conn, pre_master_secret,
 			    TLS_PRE_MASTER_SECRET_LEN)) {
 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c
index 01b2f83..1310f4e 100644
--- a/src/tls/tlsv1_cred.c
+++ b/src/tls/tlsv1_cred.c
@@ -455,12 +455,8 @@
 	 * }
 	 */
 
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (CertBag) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #12: Expected SEQUENCE (CertBag)");
 		return -1;
 	}
 
@@ -482,21 +478,17 @@
 			   obuf);
 	}
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (certValue) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (certValue)");
 		return -1;
 	}
 
 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (x509Certificate) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected OCTET STRING (x509Certificate)");
 		return -1;
 	}
 
@@ -534,11 +526,9 @@
 	 * }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_BMPSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected BMPSTRING (friendlyName) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_bmpstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected BMPSTRING (friendlyName)");
 		return 0;
 	}
 	wpa_hexdump_ascii(MSG_DEBUG, "PKCS #12: friendlyName",
@@ -561,11 +551,9 @@
 	 * }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (localKeyID) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected OCTET STRING (localKeyID)");
 		return -1;
 	}
 	wpa_hexdump_key(MSG_DEBUG, "PKCS #12: localKeyID",
@@ -596,12 +584,8 @@
 	asn1_oid_to_str(&a_oid, obuf, sizeof(obuf));
 	wpa_printf(MSG_DEBUG, "PKCS #12: attrId %s", obuf);
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SET (attrValues) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #12: Expected SET (attrValues)");
 		return -1;
 	}
 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: attrValues",
@@ -641,12 +625,10 @@
 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
 	wpa_printf(MSG_DEBUG, "PKCS #12: BAG-TYPE %s", obuf);
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (bagValue) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (bagValue)");
 		return 0;
 	}
 	value = hdr.payload;
@@ -657,11 +639,9 @@
 	if (pos < end) {
 		/* bagAttributes  SET OF PKCS12Attribute OPTIONAL */
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SET) {
-			wpa_printf(MSG_DEBUG,
-				   "PKCS #12: Expected SET (bagAttributes) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_set(&hdr)) {
+			asn1_unexpected(&hdr,
+					"PKCS #12: Expected SET (bagAttributes)");
 			return -1;
 		}
 		wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagAttributes",
@@ -672,11 +652,9 @@
 		while (pos < end) {
 			/* PKCS12Attribute ::= SEQUENCE */
 			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-			    hdr.class != ASN1_CLASS_UNIVERSAL ||
-			    hdr.tag != ASN1_TAG_SEQUENCE) {
-				wpa_printf(MSG_DEBUG,
-					   "PKCS #12: Expected SEQUENCE (PKCS12Attribute) - found class %d tag 0x%x",
-					   hdr.class, hdr.tag);
+			    !asn1_is_sequence(&hdr)) {
+				asn1_unexpected(&hdr,
+						"PKCS #12: Expected SEQUENCE (PKCS12Attribute)");
 				return -1;
 			}
 			if (pkcs12_parse_attr(hdr.payload, hdr.length) < 0)
@@ -705,12 +683,9 @@
 	const u8 *pos, *end;
 
 	/* SafeContents ::= SEQUENCE OF SafeBag */
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (SafeContents) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (SafeContents)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -726,11 +701,9 @@
 
 	while (pos < end) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG,
-				   "PKCS #12: Expected SEQUENCE (SafeBag) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"PKCS #12: Expected SEQUENCE (SafeBag)");
 			return -1;
 		}
 		if (pkcs12_safebag(cred, hdr.payload, hdr.length, passwd) < 0)
@@ -750,11 +723,8 @@
 
 	/* Data ::= OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #12: Expected OCTET STRING (Data)");
 		return -1;
 	}
 
@@ -782,21 +752,17 @@
 	 *   encryptedContentInfo EncryptedContentInfo }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (EncryptedData) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (EncryptedData)");
 		return 0;
 	}
 	pos = hdr.payload;
 
 	/* Version ::= INTEGER */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: No INTEGER tag found for version");
 		return -1;
 	}
 	if (hdr.length != 1 || hdr.payload[0] != 0) {
@@ -815,11 +781,9 @@
 	 *   encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (EncryptedContentInfo) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (EncryptedContentInfo)");
 		return -1;
 	}
 
@@ -845,22 +809,19 @@
 
 	/* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier)");
 		return -1;
 	}
 	enc_alg = hdr.payload;
 	enc_alg_len = hdr.length;
 	pos = hdr.payload + hdr.length;
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] IMPLICIT (encryptedContent) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] IMPLICIT (encryptedContent)");
 		return -1;
 	}
 
@@ -900,12 +861,10 @@
 	asn1_oid_to_str(&oid, txt, sizeof(txt));
 	wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", txt);
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (content)");
 		return 0;
 	}
 	pos = hdr.payload;
@@ -938,23 +897,18 @@
 	 * }
 	 */
 
-	if (asn1_get_next(key, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (PFX) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(key, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (PFX); assume PKCS #12 not used");
 		return -1;
 	}
 
 	pos = hdr.payload;
 	end = pos + hdr.length;
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: No INTEGER tag found for version");
 		return -1;
 	}
 	if (hdr.length != 1 || hdr.payload[0] != 3) {
@@ -970,11 +924,9 @@
 	 */
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (authSafe) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (authSafe); assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -995,12 +947,10 @@
 		return -1;
 	}
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (content); assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -1008,11 +958,9 @@
 
 	/* Data ::= OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected OCTET STRING (Data); assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -1026,11 +974,9 @@
 		    hdr.payload, hdr.length);
 
 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE within Data content - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE within Data content; assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -1039,11 +985,9 @@
 
 	while (end > pos) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG,
-				   "PKCS #12: Expected SEQUENCE (ContentInfo) - found class %d tag 0x%x; assume PKCS #12 not used",
-				   hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"PKCS #12: Expected SEQUENCE (ContentInfo); assume PKCS #12 not used");
 			return -1;
 		}
 		if (pkcs12_parse_content(cred, hdr.payload, hdr.length,
@@ -1141,24 +1085,17 @@
 	 */
 
 	/* DHParamer ::= SEQUENCE */
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a "
-			   "valid SEQUENCE - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"DH: DH parameters did not start with a valid SEQUENCE");
 		return -1;
 	}
 	pos = hdr.payload;
 
 	/* prime INTEGER */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0)
-		return -1;
-
-	if (hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; "
-			   "class=%d tag=0x%x", hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "DH: No INTEGER tag found for p");
 		return -1;
 	}
 
@@ -1173,13 +1110,9 @@
 	pos = hdr.payload + hdr.length;
 
 	/* base INTEGER */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0)
-		return -1;
-
-	if (hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; "
-			   "class=%d tag=0x%x", hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "DH: No INTEGER tag found for g");
 		return -1;
 	}
 
diff --git a/src/tls/x509v3.c b/src/tls/x509v3.c
index d2e685c..b006e99 100644
--- a/src/tls/x509v3.c
+++ b/src/tls/x509v3.c
@@ -192,12 +192,9 @@
 	 * }
 	 */
 
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-			   "(AlgorithmIdentifier) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE (AlgorithmIdentifier)");
 		return -1;
 	}
 	if (hdr.length > buf + len - hdr.payload)
@@ -234,11 +231,9 @@
 	end = buf + len;
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-			   "(SubjectPublicKeyInfo) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE (SubjectPublicKeyInfo)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -253,11 +248,9 @@
 		return -1;
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_BITSTRING) {
-		wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING "
-			   "(subjectPublicKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_bitstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected BITSTRING (subjectPublicKey)");
 		return -1;
 	}
 	if (hdr.length < 1)
@@ -309,12 +302,9 @@
 	 * AttributeValue ::= ANY DEFINED BY AttributeType
 	 */
 
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-			   "(Name / RDNSequencer) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE (Name / RDNSequencer)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -328,11 +318,9 @@
 		enum x509_name_attr_type type;
 
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SET) {
-			wpa_printf(MSG_DEBUG, "X509: Expected SET "
-				   "(RelativeDistinguishedName) - found class "
-				   "%d tag 0x%x", hdr.class, hdr.tag);
+		    !asn1_is_set(&hdr)) {
+			asn1_unexpected(&hdr,
+					"X509: Expected SET (RelativeDistinguishedName)");
 			x509_free_name(name);
 			return -1;
 		}
@@ -341,11 +329,9 @@
 		pos = set_end = hdr.payload + hdr.length;
 
 		if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-				   "(AttributeTypeAndValue) - found class %d "
-				   "tag 0x%x", hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"X509: Expected SEQUENCE (AttributeTypeAndValue)");
 			x509_free_name(name);
 			return -1;
 		}
@@ -366,6 +352,13 @@
 			return -1;
 		}
 
+		if (!asn1_is_string_type(&hdr)) {
+			wpa_printf(MSG_DEBUG,
+				   "X509: Ignore non-string type attribute (tag 0x%x)",
+				   hdr.tag);
+			continue;
+		}
+
 		/* RFC 3280:
 		 * MUST: country, organization, organizational-unit,
 		 * distinguished name qualifier, state or province name,
@@ -709,12 +702,8 @@
 	 * validity dates in 2050 or later MUST be encoded as GeneralizedTime.
 	 */
 
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-			   "(Validity) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "X509: Expected SEQUENCE (Validity)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -726,7 +715,7 @@
 	*next = pos + plen;
 
 	if (asn1_get_next(pos, plen, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    (!asn1_is_utctime(&hdr) && !asn1_is_generalizedtime(&hdr)) ||
 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
 			    &cert->not_before) < 0) {
 		wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore "
@@ -738,7 +727,7 @@
 	plen = *next - pos;
 
 	if (asn1_get_next(pos, plen, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    (!asn1_is_utctime(&hdr) && !asn1_is_generalizedtime(&hdr)) ||
 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
 			    &cert->not_after) < 0) {
 		wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter "
@@ -791,13 +780,9 @@
 	 *     decipherOnly            (8) }
 	 */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_BITSTRING ||
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_bitstring(&hdr) ||
 	    hdr.length < 1) {
-		wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in "
-			   "KeyUsage; found %d tag 0x%x len %d",
-			   hdr.class, hdr.tag, hdr.length);
+		asn1_unexpected(&hdr, "X509: Expected BIT STRING in KeyUsage");
 		return -1;
 	}
 
@@ -824,12 +809,9 @@
 	 * pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
 	 */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
-			   "BasicConstraints; found %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE in BasicConstraints");
 		return -1;
 	}
 
@@ -839,14 +821,13 @@
 		return 0;
 
 	end_seq = hdr.payload + hdr.length;
-	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL) {
+	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0) {
 		wpa_printf(MSG_DEBUG, "X509: Failed to parse "
 			   "BasicConstraints");
 		return -1;
 	}
 
-	if (hdr.tag == ASN1_TAG_BOOLEAN) {
+	if (asn1_is_boolean(&hdr)) {
 		cert->ca = hdr.payload[0];
 
 		pos = hdr.payload + hdr.length;
@@ -856,18 +837,16 @@
 				   cert->ca);
 			return 0;
 		}
-		if (asn1_get_next(pos, end_seq - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL) {
+		if (asn1_get_next(pos, end_seq - pos, &hdr) < 0) {
 			wpa_printf(MSG_DEBUG, "X509: Failed to parse "
 				   "BasicConstraints");
 			return -1;
 		}
 	}
 
-	if (hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in "
-			   "BasicConstraints; found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (!asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected INTEGER in BasicConstraints");
 		return -1;
 	}
 
@@ -1074,12 +1053,9 @@
 
 	/* SubjectAltName ::= GeneralNames */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
-			   "SubjectAltName; found %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE in SubjectAltName");
 		return -1;
 	}
 
@@ -1101,12 +1077,9 @@
 
 	/* IssuerAltName ::= GeneralNames */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
-			   "IssuerAltName; found %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE in IssuerAltName");
 		return -1;
 	}
 
@@ -1187,11 +1160,9 @@
 	 * CertPolicyId ::= OBJECT IDENTIFIER
 	 */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE (certificatePolicies) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE (certificatePolicies)");
 		return -1;
 	}
 	if (hdr.length > pos + len - hdr.payload)
@@ -1207,10 +1178,9 @@
 		char buf[80];
 
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE (PolicyInformation) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"X509: Expected SEQUENCE (PolicyInformation)");
 			return -1;
 		}
 		if (hdr.length > end - hdr.payload)
@@ -1310,12 +1280,9 @@
 	 * KeyPurposeId ::= OBJECT IDENTIFIER
 	 */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-			   "(ExtKeyUsageSyntax) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE (ExtKeyUsageSyntax)");
 		return -1;
 	}
 	if (hdr.length > pos + len - hdr.payload)
@@ -1402,12 +1369,8 @@
 	 * }
 	 */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in "
-			   "Extensions: class %d tag 0x%x; expected SEQUENCE",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "X509: Expected SEQUENCE in Extensions");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -1420,26 +1383,27 @@
 	}
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    (hdr.tag != ASN1_TAG_BOOLEAN &&
-	     hdr.tag != ASN1_TAG_OCTETSTRING)) {
-		wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in "
-			   "Extensions: class %d tag 0x%x; expected BOOLEAN "
-			   "or OCTET STRING", hdr.class, hdr.tag);
+	    (!asn1_is_boolean(&hdr) && !asn1_is_octetstring(&hdr))) {
+		asn1_unexpected(&hdr,
+				"X509: Expected BOOLEAN or OCTETSTRING in Extensions");
 		return -1;
 	}
 
 	if (hdr.tag == ASN1_TAG_BOOLEAN) {
 		critical_ext = hdr.payload[0];
 		pos = hdr.payload;
+		/*
+		 * Number of CA certificates seem to be using Private class in
+		 * one of the X.509v3 extensions, so let's accept that instead
+		 * of rejecting the certificate. asn1_is_octetstring() covers
+		 * the more common case.
+		 */
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    (hdr.class != ASN1_CLASS_UNIVERSAL &&
-		     hdr.class != ASN1_CLASS_PRIVATE) ||
-		    hdr.tag != ASN1_TAG_OCTETSTRING) {
-			wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header "
-				   "in Extensions: class %d tag 0x%x; "
-				   "expected OCTET STRING",
-				   hdr.class, hdr.tag);
+		    (!asn1_is_octetstring(&hdr) &&
+		     !(hdr.class == ASN1_CLASS_PRIVATE &&
+		       hdr.tag == ASN1_TAG_OCTETSTRING))) {
+			asn1_unexpected(&hdr,
+					"X509: Expected OCTETSTRING in Extensions");
 			return -1;
 		}
 	}
@@ -1470,12 +1434,8 @@
 
 	/* Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension */
 
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data "
-			   "for Extensions: class %d tag 0x%x; "
-			   "expected SEQUENCE", hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "X509: Expected SEQUENCE for Extensions");
 		return -1;
 	}
 
@@ -1504,12 +1464,9 @@
 	const u8 *subject_dn;
 
 	/* tbsCertificate TBSCertificate ::= SEQUENCE */
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start "
-			   "with a valid SEQUENCE - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: tbsCertificate did not start with a valid SEQUENCE");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -1523,15 +1480,11 @@
 		return -1;
 	pos = hdr.payload;
 
-	if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) {
-		if (asn1_get_next(pos, end - pos, &hdr) < 0)
-			return -1;
-
-		if (hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_INTEGER) {
-			wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for "
-				   "version field - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+	if (asn1_is_cs_tag(&hdr, 0) && hdr.constructed) {
+		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+		    !asn1_is_integer(&hdr)) {
+			asn1_unexpected(&hdr,
+					"X509: No INTEGER tag found for version field");
 			return -1;
 		}
 		if (hdr.length != 1) {
@@ -1564,12 +1517,10 @@
 	wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1);
 
 	/* serialNumber CertificateSerialNumber ::= INTEGER */
-	if (hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_INTEGER ||
+	if (!asn1_is_integer(&hdr) ||
 	    hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) {
-		wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for "
-			   "serialNumber; class=%d tag=0x%x length=%u",
-			   hdr.class, hdr.tag, hdr.length);
+		asn1_unexpected(&hdr,
+				"X509: No INTEGER tag found for serialNumber");
 		return -1;
 	}
 
@@ -1622,10 +1573,8 @@
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
-		wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific"
-			   " tag to parse optional tbsCertificate "
-			   "field(s); parsed class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+		asn1_unexpected(&hdr,
+				"X509: Expected Context-Specific tag to parse optional tbsCertificate field(s)");
 		return -1;
 	}
 
@@ -1640,10 +1589,8 @@
 
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 		    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
-			wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific"
-				   " tag to parse optional tbsCertificate "
-				   "field(s); parsed class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+			asn1_unexpected(&hdr,
+					"X509: Expected Context-Specific tag to parse optional tbsCertificate field(s)");
 			return -1;
 		}
 	}
@@ -1659,18 +1606,16 @@
 
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 		    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
-			wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific"
-				   " tag to parse optional tbsCertificate "
-				   "field(s); parsed class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+			asn1_unexpected(&hdr,
+					"X509: Expected Context-Specific tag to parse optional tbsCertificate field(s)");
 			return -1;
 		}
 	}
 
 	if (hdr.tag != 3) {
-		wpa_printf(MSG_DEBUG, "X509: Ignored unexpected "
-			   "Context-Specific tag %d in optional "
-			   "tbsCertificate fields", hdr.tag);
+		wpa_printf(MSG_DEBUG,
+			   "X509: Ignored unexpected Context-Specific constructed %d tag %d in optional tbsCertificate fields",
+			   hdr.constructed, hdr.tag);
 		return 0;
 	}
 
@@ -1798,12 +1743,9 @@
 	/* RFC 3280 - X.509 v3 certificate / ASN.1 DER */
 
 	/* Certificate ::= SEQUENCE */
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Certificate did not start with "
-			   "a valid SEQUENCE - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Certificate did not start with a valid SEQUENCE");
 		x509_certificate_free(cert);
 		return NULL;
 	}
@@ -1838,11 +1780,9 @@
 
 	/* signatureValue BIT STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_BITSTRING) {
-		wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING "
-			   "(signatureValue) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_bitstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected BITSTRING (signatureValue)");
 		x509_certificate_free(cert);
 		return NULL;
 	}
@@ -1956,14 +1896,12 @@
 	 *
 	 */
 	if (asn1_get_next(data, data_len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-			   "(DigestInfo) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "X509: Expected SEQUENCE (DigestInfo)");
 		os_free(data);
 		return -1;
 	}
+	wpa_hexdump(MSG_MSGDUMP, "X509: DigestInfo", hdr.payload, hdr.length);
 
 	pos = hdr.payload;
 	end = pos + hdr.length;
@@ -1977,14 +1915,14 @@
 	 */
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
-			   "(AlgorithmIdentifier) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"X509: Expected SEQUENCE (AlgorithmIdentifier)");
 		os_free(data);
 		return -1;
 	}
+	wpa_hexdump(MSG_MSGDUMP, "X509: DigestAlgorithmIdentifier",
+		    hdr.payload, hdr.length);
 	da_end = hdr.payload + hdr.length;
 
 	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) {
@@ -1992,6 +1930,23 @@
 		os_free(data);
 		return -1;
 	}
+	wpa_hexdump(MSG_MSGDUMP, "X509: Digest algorithm parameters",
+		    next, da_end - next);
+
+	/*
+	 * RFC 5754: The correct encoding for the SHA2 algorithms would be to
+	 * omit the parameters, but there are implementation that encode these
+	 * as a NULL element. Allow these two cases and reject anything else.
+	 */
+	if (da_end > next &&
+	    (asn1_get_next(next, da_end - next, &hdr) < 0 ||
+	     !asn1_is_null(&hdr) ||
+	     hdr.payload + hdr.length != da_end)) {
+		wpa_printf(MSG_DEBUG,
+			   "X509: Unexpected digest algorithm parameters");
+		os_free(data);
+		return -1;
+	}
 
 	if (x509_sha1_oid(&oid)) {
 		if (signature->oid.oid[6] != 5 /* sha-1WithRSAEncryption */) {
@@ -2070,14 +2025,10 @@
 skip_digest_oid:
 	/* Digest ::= OCTET STRING */
 	pos = da_end;
-	end = data + data_len;
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING "
-			   "(Digest) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr, "X509: Expected OCTETSTRING (Digest)");
 		os_free(data);
 		return -1;
 	}
diff --git a/src/utils/config.c b/src/utils/config.c
index 22aa221..ba26c2c 100644
--- a/src/utils/config.c
+++ b/src/utils/config.c
@@ -66,12 +66,20 @@
 		 * Remove # comments unless they are within a double quoted
 		 * string.
 		 */
-		sstart = os_strchr(pos, '"');
-		if (sstart)
-			sstart = os_strrchr(sstart + 1, '"');
-		if (!sstart)
-			sstart = pos;
+		sstart = pos;
 		end = os_strchr(sstart, '#');
+		while (end) {
+			sstart = os_strchr(sstart, '"');
+			if (!sstart || sstart > end)
+				break;
+			sstart = os_strchr(sstart + 1, '"');
+			if (!sstart)
+				break;
+			sstart++;
+			if (sstart > end)
+				end = os_strchr(sstart, '#');
+		}
+
 		if (end)
 			*end-- = '\0';
 		else
diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index b353ab0..00b0bef 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -785,21 +785,15 @@
 	}
 	now_sec = timeout->time.sec;
 	timeout->time.sec += secs;
-	if (timeout->time.sec < now_sec) {
-		/*
-		 * Integer overflow - assume long enough timeout to be assumed
-		 * to be infinite, i.e., the timeout would never happen.
-		 */
-		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
-			   "ever happen - ignore it", secs);
-		os_free(timeout);
-		return 0;
-	}
+	if (timeout->time.sec < now_sec)
+		goto overflow;
 	timeout->time.usec += usecs;
 	while (timeout->time.usec >= 1000000) {
 		timeout->time.sec++;
 		timeout->time.usec -= 1000000;
 	}
+	if (timeout->time.sec < now_sec)
+		goto overflow;
 	timeout->eloop_data = eloop_data;
 	timeout->user_data = user_data;
 	timeout->handler = handler;
@@ -817,6 +811,17 @@
 	dl_list_add_tail(&eloop.timeout, &timeout->list);
 
 	return 0;
+
+overflow:
+	/*
+	 * Integer overflow - assume long enough timeout to be assumed
+	 * to be infinite, i.e., the timeout would never happen.
+	 */
+	wpa_printf(MSG_DEBUG,
+		   "ELOOP: Too long timeout (secs=%u usecs=%u) to ever happen - ignore it",
+		   secs,usecs);
+	os_free(timeout);
+	return 0;
 }
 
 
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index a90428f..e721df2 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -490,9 +490,9 @@
 int os_fdatasync(FILE *stream)
 {
 	if (!fflush(stream)) {
-#ifdef __linux__
+#if defined __FreeBSD__ || defined __linux__
 		return fdatasync(fileno(stream));
-#else /* !__linux__ */
+#else /* !__linux__ && !__FreeBSD__ */
 #ifdef F_FULLFSYNC
 		/* OS X does not implement fdatasync(). */
 		return fcntl(fileno(stream), F_FULLFSYNC);
diff --git a/src/utils/wpabuf.h b/src/utils/wpabuf.h
index b2a54b2..eb1db80 100644
--- a/src/utils/wpabuf.h
+++ b/src/utils/wpabuf.h
@@ -133,6 +133,12 @@
 	WPA_PUT_LE32(pos, data);
 }
 
+static inline void wpabuf_put_le64(struct wpabuf *buf, u64 data)
+{
+	u8 *pos = (u8 *) wpabuf_put(buf, 8);
+	WPA_PUT_LE64(pos, data);
+}
+
 static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data)
 {
 	u8 *pos = (u8 *) wpabuf_put(buf, 2);
@@ -151,6 +157,12 @@
 	WPA_PUT_BE32(pos, data);
 }
 
+static inline void wpabuf_put_be64(struct wpabuf *buf, u64 data)
+{
+	u8 *pos = (u8 *) wpabuf_put(buf, 8);
+	WPA_PUT_BE64(pos, data);
+}
+
 static inline void wpabuf_put_data(struct wpabuf *buf, const void *data,
 				   size_t len)
 {
diff --git a/src/wps/wps.c b/src/wps/wps.c
index 484df26..1fe3806 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -17,7 +17,7 @@
 
 #ifdef CONFIG_WPS_TESTING
 int wps_version_number = 0x20;
-int wps_testing_dummy_cred = 0;
+int wps_testing_stub_cred = 0;
 int wps_corrupt_pkhash = 0;
 int wps_force_auth_types_in_use = 0;
 u16 wps_force_auth_types = 0;
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 6a12255..fed3e28 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -841,6 +841,10 @@
 	struct wpabuf *ap_nfc_dh_pubkey;
 	struct wpabuf *ap_nfc_dh_privkey;
 	struct wpabuf *ap_nfc_dev_pw;
+
+	/* Whether to send WPA2-PSK passphrase as a passphrase instead of PSK
+	 * for WPA3-Personal transition mode needs. */
+	bool use_passphrase;
 };
 
 struct wps_registrar *
diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h
index 9fccb4e..ddaeda5 100644
--- a/src/wps/wps_defs.h
+++ b/src/wps/wps_defs.h
@@ -12,7 +12,7 @@
 #ifdef CONFIG_WPS_TESTING
 
 extern int wps_version_number;
-extern int wps_testing_dummy_cred;
+extern int wps_testing_stub_cred;
 extern int wps_corrupt_pkhash;
 extern int wps_force_auth_types_in_use;
 extern u16 wps_force_auth_types;
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 0db9367..9587293 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1320,13 +1320,9 @@
 	}
 
 	beacon = wpabuf_alloc(400 + vendor_len);
-	if (beacon == NULL)
-		return -1;
 	probe = wpabuf_alloc(500 + vendor_len);
-	if (probe == NULL) {
-		wpabuf_free(beacon);
-		return -1;
-	}
+	if (!beacon || !probe)
+		goto fail;
 
 	auth_macs = wps_authorized_macs(reg, &count);
 
@@ -1342,19 +1338,13 @@
 	    (reg->dualband && wps_build_rf_bands(&reg->wps->dev, beacon, 0)) ||
 	    wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) ||
 	    wps_build_vendor_ext(&reg->wps->dev, beacon) ||
-	    wps_build_application_ext(&reg->wps->dev, beacon)) {
-		wpabuf_free(beacon);
-		wpabuf_free(probe);
-		return -1;
-	}
+	    wps_build_application_ext(&reg->wps->dev, beacon))
+		goto fail;
 
 #ifdef CONFIG_P2P
 	if (wps_build_dev_name(&reg->wps->dev, beacon) ||
-	    wps_build_primary_dev_type(&reg->wps->dev, beacon)) {
-		wpabuf_free(beacon);
-		wpabuf_free(probe);
-		return -1;
-	}
+	    wps_build_primary_dev_type(&reg->wps->dev, beacon))
+		goto fail;
 #endif /* CONFIG_P2P */
 
 	wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs");
@@ -1373,22 +1363,20 @@
 	    (reg->dualband && wps_build_rf_bands(&reg->wps->dev, probe, 0)) ||
 	    wps_build_wfa_ext(probe, 0, auth_macs, count, 0) ||
 	    wps_build_vendor_ext(&reg->wps->dev, probe) ||
-	    wps_build_application_ext(&reg->wps->dev, probe)) {
-		wpabuf_free(beacon);
-		wpabuf_free(probe);
-		return -1;
-	}
+	    wps_build_application_ext(&reg->wps->dev, probe))
+		goto fail;
 
 	beacon = wps_ie_encapsulate(beacon);
 	probe = wps_ie_encapsulate(probe);
 
-	if (!beacon || !probe) {
-		wpabuf_free(beacon);
-		wpabuf_free(probe);
-		return -1;
-	}
+	if (!beacon || !probe)
+		goto fail;
 
 	return wps_cb_set_ie(reg, beacon, probe);
+fail:
+	wpabuf_free(beacon);
+	wpabuf_free(probe);
+	return -1;
 }
 
 
@@ -1765,8 +1753,10 @@
 		wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, PMK_LEN);
 		os_memcpy(wps->cred.key, hex, PMK_LEN * 2);
 		wps->cred.key_len = PMK_LEN * 2;
-	} else if (!wps->wps->registrar->force_per_enrollee_psk &&
-		   wps->wps->network_key) {
+	} else if ((!wps->wps->registrar->force_per_enrollee_psk ||
+		    wps->wps->use_passphrase) && wps->wps->network_key) {
+		wpa_printf(MSG_DEBUG,
+			   "WPS: Use passphrase format for Network key");
 		os_memcpy(wps->cred.key, wps->wps->network_key,
 			  wps->wps->network_key_len);
 		wps->cred.key_len = wps->wps->network_key_len;
@@ -1795,23 +1785,23 @@
 
 use_provided:
 #ifdef CONFIG_WPS_TESTING
-	if (wps_testing_dummy_cred)
+	if (wps_testing_stub_cred)
 		cred = wpabuf_alloc(200);
 	else
 		cred = NULL;
 	if (cred) {
-		struct wps_credential dummy;
-		wpa_printf(MSG_DEBUG, "WPS: Add dummy credential");
-		os_memset(&dummy, 0, sizeof(dummy));
-		os_memcpy(dummy.ssid, "dummy", 5);
-		dummy.ssid_len = 5;
-		dummy.auth_type = WPS_AUTH_WPA2PSK;
-		dummy.encr_type = WPS_ENCR_AES;
-		os_memcpy(dummy.key, "dummy psk", 9);
-		dummy.key_len = 9;
-		os_memcpy(dummy.mac_addr, wps->mac_addr_e, ETH_ALEN);
-		wps_build_credential(cred, &dummy);
-		wpa_hexdump_buf(MSG_DEBUG, "WPS: Dummy Credential", cred);
+		struct wps_credential stub;
+		wpa_printf(MSG_DEBUG, "WPS: Add stub credential");
+		os_memset(&stub, 0, sizeof(stub));
+		os_memcpy(stub.ssid, "stub", 5);
+		stub.ssid_len = 5;
+		stub.auth_type = WPS_AUTH_WPA2PSK;
+		stub.encr_type = WPS_ENCR_AES;
+		os_memcpy(stub.key, "stub psk", 9);
+		stub.key_len = 9;
+		os_memcpy(stub.mac_addr, wps->mac_addr_e, ETH_ALEN);
+		wps_build_credential(cred, &stub);
+		wpa_hexdump_buf(MSG_DEBUG, "WPS: Stub Credential", cred);
 
 		wpabuf_put_be16(msg, ATTR_CRED);
 		wpabuf_put_be16(msg, wpabuf_len(cred));
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index ff58cb9..05bb9c5 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -658,7 +658,7 @@
 		/*
 		 * There has been no events before the subscription. However,
 		 * UPnP device architecture specification requires all the
-		 * evented variables to be included, so generate a dummy event
+		 * evented variables to be included, so generate a stub event
 		 * for this particular case using a WSC_ACK and all-zeros
 		 * nonces. The ER (UPnP control point) will ignore this, but at
 		 * least it will learn that WLANEvent variable will be used in
diff --git a/wpa_supplicant/Android.bp b/wpa_supplicant/Android.bp
index 2d4bb2b..0d088bb 100644
--- a/wpa_supplicant/Android.bp
+++ b/wpa_supplicant/Android.bp
@@ -67,16 +67,12 @@
     defaults: ["wpa_supplicant_cflags_defaults"],
     srcs: [":wpa_supplicant_srcs"],
     shared_libs: [
-        "android.hardware.wifi.supplicant@1.0",
-        "android.hardware.wifi.supplicant@1.1",
-        "android.hardware.wifi.supplicant@1.2",
-        "android.hardware.wifi.supplicant@1.3",
-        "android.hardware.wifi.supplicant@1.4",
+        "android.hardware.wifi.supplicant-V1-ndk",
         "libbase",
+        "libbinder_ndk",
         "libc",
         "libcrypto",
         "libcutils",
-        "libhidlbase",
         "libkeystore-engine-wifi-hidl",
         "libkeystore-wifi-hidl",
         "liblog",
@@ -87,11 +83,11 @@
     relative_install_path: "hw",
     soc_specific: true,
     static_libs: [
-        "libwpa_hidl_bp",
+        "libwpa_aidl_bp",
     ],
     header_libs: [
         "wpa_supplicant_headers",
-        "libwpa_hidl_headers",
+        "libwpa_aidl_headers",
     ],
 }
 
@@ -137,7 +133,7 @@
         "-DCONFIG_CTRL_IFACE",
         "-DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/wpa/sockets\"",
         "-DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/wpa/sockets\"",
-        "-DCONFIG_CTRL_IFACE_HIDL",
+        "-DCONFIG_CTRL_IFACE_AIDL",
         "-DCONFIG_CTRL_IFACE_UNIX",
         "-DCONFIG_DPP",
         "-DCONFIG_DPP2",
@@ -147,7 +143,7 @@
         "-DCONFIG_FILS",
         "-DCONFIG_GAS",
         "-DCONFIG_GAS_SERVER",
-        "-DCONFIG_HIDL",
+        "-DCONFIG_AIDL",
         "-DCONFIG_HMAC_SHA256_KDF",
         "-DCONFIG_HMAC_SHA384_KDF",
         "-DCONFIG_HMAC_SHA512_KDF",
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 0f9f83a..cdf8943 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -87,7 +87,7 @@
 L_CFLAGS += -mabi=aapcs-linux
 endif
 
-# C++ flags for hidl interface
+# C++ flags for aidl interface
 L_CPPFLAGS := -Wall -Werror
 # TODO: Remove these allowed warnings later.
 L_CPPFLAGS += -Wno-unused-variable -Wno-unused-parameter
@@ -136,6 +136,7 @@
 OBJS += wmm_ac.c
 OBJS += op_classes.c
 OBJS += rrm.c
+OBJS += twt.c
 OBJS += robust_av.c
 OBJS_p = wpa_passphrase.c
 OBJS_p += src/utils/common.c
@@ -311,6 +312,9 @@
 ifdef CONFIG_DPP2
 L_CFLAGS += -DCONFIG_DPP2
 endif
+ifdef CONFIG_DPP3
+L_CFLAGS += -DCONFIG_DPP3
+endif
 endif
 
 ifdef CONFIG_OWE
@@ -402,12 +406,11 @@
 ifdef CONFIG_P2P_STRICT
 L_CFLAGS += -DCONFIG_P2P_STRICT
 endif
-endif
-
 ifdef CONFIG_WIFI_DISPLAY
 L_CFLAGS += -DCONFIG_WIFI_DISPLAY
 OBJS += wifi_display.c
 endif
+endif
 
 ifdef CONFIG_PASN
 L_CFLAGS += -DCONFIG_PASN
@@ -1525,10 +1528,9 @@
 L_CFLAGS += $(DBUS_INCLUDE)
 endif
 
-ifdef CONFIG_CTRL_IFACE_HIDL
-WPA_SUPPLICANT_USE_HIDL=y
-L_CFLAGS += -DCONFIG_HIDL -DCONFIG_CTRL_IFACE_HIDL
-HIDL_INTERFACE_VERSION := 1.4
+ifdef CONFIG_CTRL_IFACE_AIDL
+WPA_SUPPLICANT_USE_AIDL=y
+L_CFLAGS += -DCONFIG_AIDL -DCONFIG_CTRL_IFACE_AIDL
 endif
 
 ifdef CONFIG_READLINE
@@ -1788,17 +1790,14 @@
 ifeq ($(DBUS), y)
 LOCAL_SHARED_LIBRARIES += libdbus
 endif
-ifeq ($(WPA_SUPPLICANT_USE_HIDL), y)
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant@1.0
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant@1.1
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant@1.2
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant@1.3
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant@1.4
-LOCAL_SHARED_LIBRARIES += libhidlbase libutils libbase
-LOCAL_STATIC_LIBRARIES += libwpa_hidl
-LOCAL_VINTF_FRAGMENTS := hidl/$(HIDL_INTERFACE_VERSION)/android.hardware.wifi.supplicant.xml
+ifeq ($(WPA_SUPPLICANT_USE_AIDL), y)
+LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant-V1-ndk
+LOCAL_SHARED_LIBRARIES += libutils libbase
+LOCAL_SHARED_LIBRARIES += libbinder_ndk
+LOCAL_STATIC_LIBRARIES += libwpa_aidl
+LOCAL_VINTF_FRAGMENTS := aidl/android.hardware.wifi.supplicant.xml
 ifeq ($(WIFI_HIDL_UNIFIED_SUPPLICANT_SERVICE_RC_ENTRY), true)
-LOCAL_INIT_RC=hidl/$(HIDL_INTERFACE_VERSION)/android.hardware.wifi.supplicant-service.rc
+LOCAL_INIT_RC=aidl/android.hardware.wifi.supplicant-service.rc
 endif
 endif
 include $(BUILD_EXECUTABLE)
@@ -1842,11 +1841,11 @@
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/wpa_client_include $(LOCAL_PATH)/wpa_client_include/libwpa_client
 include $(BUILD_SHARED_LIBRARY)
 
-ifeq ($(WPA_SUPPLICANT_USE_HIDL), y)
-### Hidl service library ###
+ifeq ($(WPA_SUPPLICANT_USE_AIDL), y)
+### Aidl service library ###
 ########################
 include $(CLEAR_VARS)
-LOCAL_MODULE := libwpa_hidl
+LOCAL_MODULE := libwpa_aidl
 LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-BSD-3-Clause SPDX-license-identifier-ISC legacy_unencumbered
 LOCAL_LICENSE_CONDITIONS := notice unencumbered
 LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../LICENSE
@@ -1855,26 +1854,22 @@
 LOCAL_CFLAGS := $(L_CFLAGS)
 LOCAL_C_INCLUDES := $(INCLUDES)
 LOCAL_SRC_FILES := \
-    hidl/$(HIDL_INTERFACE_VERSION)/hidl.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/hidl_manager.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/iface_config_utils.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/p2p_iface.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/p2p_network.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/sta_iface.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/sta_network.cpp \
-    hidl/$(HIDL_INTERFACE_VERSION)/supplicant.cpp
+    aidl/aidl.cpp \
+    aidl/aidl_manager.cpp \
+    aidl/iface_config_utils.cpp \
+    aidl/p2p_iface.cpp \
+    aidl/p2p_network.cpp \
+    aidl/sta_iface.cpp \
+    aidl/sta_network.cpp \
+    aidl/supplicant.cpp
 LOCAL_SHARED_LIBRARIES := \
-    android.hardware.wifi.supplicant@1.0 \
-    android.hardware.wifi.supplicant@1.1 \
-    android.hardware.wifi.supplicant@1.2 \
-    android.hardware.wifi.supplicant@1.3 \
-    android.hardware.wifi.supplicant@1.4 \
+    android.hardware.wifi.supplicant-V1-ndk \
+    libbinder_ndk \
     libbase \
-    libhidlbase \
     libutils \
     liblog \
     libssl
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/hidl/$(HIDL_INTERFACE_VERSION)
+    $(LOCAL_PATH)/aidl
 include $(BUILD_STATIC_LIBRARY)
-endif # WPA_SUPPLICANT_USE_HIDL == y
+endif # WPA_SUPPLICANT_USE_AIDL == y
diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog
index a06a93b..efcc6cd 100644
--- a/wpa_supplicant/ChangeLog
+++ b/wpa_supplicant/ChangeLog
@@ -1,5 +1,58 @@
 ChangeLog for wpa_supplicant
 
+2022-01-16 - v2.10
+	* SAE changes
+	  - improved protection against side channel attacks
+	    [https://w1.fi/security/2022-1/]
+	  - added support for the hash-to-element mechanism (sae_pwe=1 or
+	    sae_pwe=2); this is currently disabled by default, but will likely
+	    get enabled by default in the future
+	  - fixed PMKSA caching with OKC
+	  - added support for SAE-PK
+	* EAP-pwd changes
+	  - improved protection against side channel attacks
+	  [https://w1.fi/security/2022-1/]
+	* fixed P2P provision discovery processing of a specially constructed
+	  invalid frame
+	  [https://w1.fi/security/2021-1/]
+	* fixed P2P group information processing of a specially constructed
+	  invalid frame
+	  [https://w1.fi/security/2020-2/]
+	* fixed PMF disconnection protection bypass in AP mode
+	  [https://w1.fi/security/2019-7/]
+	* added support for using OpenSSL 3.0
+	* increased the maximum number of EAP message exchanges (mainly to
+	  support cases with very large certificates)
+	* fixed various issues in experimental support for EAP-TEAP peer
+	* added support for DPP release 2 (Wi-Fi Device Provisioning Protocol)
+	* a number of MKA/MACsec fixes and extensions
+	* added support for SAE (WPA3-Personal) AP mode configuration
+	* added P2P support for EDMG (IEEE 802.11ay) channels
+	* fixed EAP-FAST peer with TLS GCM/CCM ciphers
+	* improved throughput estimation and BSS selection
+	* dropped support for libnl 1.1
+	* added support for nl80211 control port for EAPOL frame TX/RX
+	* fixed OWE key derivation with groups 20 and 21; this breaks backwards
+	  compatibility for these groups while the default group 19 remains
+	  backwards compatible
+	* added support for Beacon protection
+	* added support for Extended Key ID for pairwise keys
+	* removed WEP support from the default build (CONFIG_WEP=y can be used
+	  to enable it, if really needed)
+	* added a build option to remove TKIP support (CONFIG_NO_TKIP=y)
+	* added support for Transition Disable mechanism to allow the AP to
+	  automatically disable transition mode to improve security
+	* extended D-Bus interface
+	* added support for PASN
+	* added a file-based backend for external password storage to allow
+	  secret information to be moved away from the main configuration file
+	  without requiring external tools
+	* added EAP-TLS peer support for TLS 1.3 (disabled by default for now)
+	* added support for SCS, MSCS, DSCP policy
+	* changed driver interface selection to default to automatic fallback
+	  to other compiled in options
+	* a large number of other fixes, cleanup, and extensions
+
 2019-08-07 - v2.9
 	* SAE changes
 	  - disable use of groups using Brainpool curves
@@ -1864,7 +1917,8 @@
 	  generate, e.g., man pages
 	* l2_packet_linux: use socket type SOCK_DGRAM instead of SOCK_RAW for
 	  PF_PACKET in order to prepare for network devices that do not use
-	  Ethernet headers (e.g., network stack with native IEEE 802.11 frames)
+	  Ethernet headers (e.g., network stack that includes IEEE 802.11
+	  header in the frames)
 	* use receipt of EAPOL-Key frame as a lower layer success indication
 	  for EAP state machine to allow recovery from dropped EAP-Success
 	  frame
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 87db2cd..18ffbcb 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -30,9 +30,9 @@
 endif
 endif
 
-export LIBDIR ?= /usr/local/lib/
-export INCDIR ?= /usr/local/include/
-export BINDIR ?= /usr/local/sbin/
+export LIBDIR ?= /usr/local/lib
+export INCDIR ?= /usr/local/include
+export BINDIR ?= /usr/local/sbin
 PKG_CONFIG ?= pkg-config
 
 CFLAGS += $(EXTRA_CFLAGS)
@@ -72,6 +72,10 @@
 	install -m 0644 -D libwpa_client.so $(DESTDIR)/$(LIBDIR)/libwpa_client.so
 	install -m 0644 -D ../src/common/wpa_ctrl.h $(DESTDIR)/$(INCDIR)/wpa_ctrl.h
 endif
+	if ls eap_*.so >/dev/null 2>&1; then \
+		install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \
+		cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \
+	; fi
 
 ifdef CONFIG_FIPS
 CONFIG_NO_RANDOM_POOL=
@@ -91,6 +95,7 @@
 OBJS += ../src/utils/crc32.o
 OBJS += op_classes.o
 OBJS += rrm.o
+OBJS += twt.o
 OBJS += robust_av.o
 OBJS_p = wpa_passphrase.o
 OBJS_p += ../src/utils/common.o
@@ -289,6 +294,9 @@
 ifdef CONFIG_DPP2
 CFLAGS += -DCONFIG_DPP2
 endif
+ifdef CONFIG_DPP3
+CFLAGS += -DCONFIG_DPP3
+endif
 endif
 
 ifdef CONFIG_OWE
@@ -388,12 +396,11 @@
 ifdef CONFIG_P2P_STRICT
 CFLAGS += -DCONFIG_P2P_STRICT
 endif
-endif
-
 ifdef CONFIG_WIFI_DISPLAY
 CFLAGS += -DCONFIG_WIFI_DISPLAY
 OBJS += wifi_display.o
 endif
+endif
 
 ifdef CONFIG_PASN
 CFLAGS += -DCONFIG_PASN
@@ -470,7 +477,7 @@
 # EAP-TLS
 ifeq ($(CONFIG_EAP_TLS), dyn)
 CFLAGS += -DEAP_TLS_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_tls.so
+EAPDYN += eap_tls.so
 else
 CFLAGS += -DEAP_TLS
 OBJS += ../src/eap_peer/eap_tls.o
@@ -491,13 +498,13 @@
 
 ifdef CONFIG_EAP_PEAP
 # EAP-PEAP
+SRC_EAP_PEAP = ../src/eap_peer/eap_peap.c ../src/eap_common/eap_peap_common.c
 ifeq ($(CONFIG_EAP_PEAP), dyn)
 CFLAGS += -DEAP_PEAP_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_peap.so
+EAPDYN += eap_peap.so
 else
 CFLAGS += -DEAP_PEAP
-OBJS += ../src/eap_peer/eap_peap.o
-OBJS += ../src/eap_common/eap_peap_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_PEAP))
 endif
 TLS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
@@ -507,7 +514,7 @@
 # EAP-TTLS
 ifeq ($(CONFIG_EAP_TTLS), dyn)
 CFLAGS += -DEAP_TTLS_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_ttls.so
+EAPDYN += eap_ttls.so
 else
 CFLAGS += -DEAP_TTLS
 OBJS += ../src/eap_peer/eap_ttls.o
@@ -524,7 +531,7 @@
 # EAP-MD5
 ifeq ($(CONFIG_EAP_MD5), dyn)
 CFLAGS += -DEAP_MD5_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_md5.so
+EAPDYN += eap_md5.so
 else
 CFLAGS += -DEAP_MD5
 OBJS += ../src/eap_peer/eap_md5.o
@@ -542,14 +549,13 @@
 
 ifdef CONFIG_EAP_MSCHAPV2
 # EAP-MSCHAPv2
+SRC_EAP_MSCHAPV2 = ../src/eap_peer/eap_mschapv2.c ../src/eap_peer/mschapv2.c
 ifeq ($(CONFIG_EAP_MSCHAPV2), dyn)
 CFLAGS += -DEAP_MSCHAPv2_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_mschapv2.so
-EAPDYN += ../src/eap_peer/mschapv2.so
+EAPDYN += eap_mschapv2.so
 else
 CFLAGS += -DEAP_MSCHAPv2
-OBJS += ../src/eap_peer/eap_mschapv2.o
-OBJS += ../src/eap_peer/mschapv2.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_MSCHAPV2))
 endif
 MS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
@@ -559,7 +565,7 @@
 # EAP-GTC
 ifeq ($(CONFIG_EAP_GTC), dyn)
 CFLAGS += -DEAP_GTC_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_gtc.so
+EAPDYN += eap_gtc.so
 else
 CFLAGS += -DEAP_GTC
 OBJS += ../src/eap_peer/eap_gtc.o
@@ -571,7 +577,7 @@
 # EAP-OTP
 ifeq ($(CONFIG_EAP_OTP), dyn)
 CFLAGS += -DEAP_OTP_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_otp.so
+EAPDYN += eap_otp.so
 else
 CFLAGS += -DEAP_OTP
 OBJS += ../src/eap_peer/eap_otp.o
@@ -583,7 +589,7 @@
 # EAP-SIM
 ifeq ($(CONFIG_EAP_SIM), dyn)
 CFLAGS += -DEAP_SIM_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_sim.so
+EAPDYN += eap_sim.so
 else
 CFLAGS += -DEAP_SIM
 OBJS += ../src/eap_peer/eap_sim.o
@@ -597,7 +603,7 @@
 # EAP-LEAP
 ifeq ($(CONFIG_EAP_LEAP), dyn)
 CFLAGS += -DEAP_LEAP_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_leap.so
+EAPDYN += eap_leap.so
 else
 CFLAGS += -DEAP_LEAP
 OBJS += ../src/eap_peer/eap_leap.o
@@ -608,12 +614,13 @@
 
 ifdef CONFIG_EAP_PSK
 # EAP-PSK
+SRC_EAP_PSK = ../src/eap_peer/eap_psk.c ../src/eap_common/eap_psk_common.c
 ifeq ($(CONFIG_EAP_PSK), dyn)
 CFLAGS += -DEAP_PSK_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_psk.so
+EAPDYN += eap_psk.so
 else
 CFLAGS += -DEAP_PSK
-OBJS += ../src/eap_peer/eap_psk.o ../src/eap_common/eap_psk_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_PSK))
 endif
 CONFIG_IEEE8021X_EAPOL=y
 NEED_AES=y
@@ -625,7 +632,7 @@
 # EAP-AKA
 ifeq ($(CONFIG_EAP_AKA), dyn)
 CFLAGS += -DEAP_AKA_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_aka.so
+EAPDYN += eap_aka.so
 else
 CFLAGS += -DEAP_AKA
 OBJS += ../src/eap_peer/eap_aka.o
@@ -659,14 +666,14 @@
 
 ifdef CONFIG_EAP_FAST
 # EAP-FAST
+SRC_EAP_FAST = ../src/eap_peer/eap_fast.c ../src/eap_peer/eap_fast_pac.c
+SRC_EAP_FAST += ../src/eap_common/eap_fast_common.c
 ifeq ($(CONFIG_EAP_FAST), dyn)
 CFLAGS += -DEAP_FAST_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_fast.so
-EAPDYN += ../src/eap_common/eap_fast_common.o
+EAPDYN += eap_fast.so
 else
 CFLAGS += -DEAP_FAST
-OBJS += ../src/eap_peer/eap_fast.o ../src/eap_peer/eap_fast_pac.o
-OBJS += ../src/eap_common/eap_fast_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_FAST))
 endif
 TLS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
@@ -675,14 +682,14 @@
 
 ifdef CONFIG_EAP_TEAP
 # EAP-TEAP
+SRC_EAP_TEAP = ../src/eap_peer/eap_teap.c ../src/eap_peer/eap_teap_pac.c
+SRC_EAP_TEAP += ../src/eap_common/eap_teap_common.c
 ifeq ($(CONFIG_EAP_TEAP), dyn)
 CFLAGS += -DEAP_TEAP_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_teap.so
-EAPDYN += ../src/eap_common/eap_teap_common.o
+EAPDYN += eap_teap.so
 else
 CFLAGS += -DEAP_TEAP
-OBJS += ../src/eap_peer/eap_teap.o ../src/eap_peer/eap_teap_pac.o
-OBJS += ../src/eap_common/eap_teap_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_TEAP))
 endif
 TLS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
@@ -694,36 +701,39 @@
 
 ifdef CONFIG_EAP_PAX
 # EAP-PAX
+SRC_EAP_PAX = ../src/eap_peer/eap_pax.c ../src/eap_common/eap_pax_common.c
 ifeq ($(CONFIG_EAP_PAX), dyn)
 CFLAGS += -DEAP_PAX_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_pax.so
+EAPDYN += eap_pax.so
 else
 CFLAGS += -DEAP_PAX
-OBJS += ../src/eap_peer/eap_pax.o ../src/eap_common/eap_pax_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_PAX))
 endif
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_SAKE
 # EAP-SAKE
+SRC_EAP_SAKE = ../src/eap_peer/eap_sake.c ../src/eap_common/eap_sake_common.c
 ifeq ($(CONFIG_EAP_SAKE), dyn)
 CFLAGS += -DEAP_SAKE_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_sake.so
+EAPDYN += eap_sake.so
 else
 CFLAGS += -DEAP_SAKE
-OBJS += ../src/eap_peer/eap_sake.o ../src/eap_common/eap_sake_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_SAKE))
 endif
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_GPSK
 # EAP-GPSK
+SRC_EAP_GPSK = ../src/eap_peer/eap_gpsk.c ../src/eap_common/eap_gpsk_common.c
 ifeq ($(CONFIG_EAP_GPSK), dyn)
 CFLAGS += -DEAP_GPSK_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_gpsk.so
+EAPDYN += eap_gpsk.so
 else
 CFLAGS += -DEAP_GPSK
-OBJS += ../src/eap_peer/eap_gpsk.o ../src/eap_common/eap_gpsk_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_GPSK))
 endif
 CONFIG_IEEE8021X_EAPOL=y
 ifdef CONFIG_EAP_GPSK_SHA256
@@ -744,12 +754,13 @@
 
 ifdef CONFIG_EAP_EKE
 # EAP-EKE
+SRC_EAP_EKE = ../src/eap_peer/eap_eke.c ../src/eap_common/eap_eke_common.c
 ifeq ($(CONFIG_EAP_EKE), dyn)
 CFLAGS += -DEAP_EKE_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_eke.so
+EAPDYN += eap_eke.so
 else
 CFLAGS += -DEAP_EKE
-OBJS += ../src/eap_peer/eap_eke.o ../src/eap_common/eap_eke_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_EKE))
 endif
 CONFIG_IEEE8021X_EAPOL=y
 NEED_DH_GROUPS=y
@@ -824,14 +835,16 @@
 
 ifdef CONFIG_EAP_IKEV2
 # EAP-IKEv2
+SRC_EAP_IKEV2 = ../src/eap_peer/eap_ikev2.c
+SRC_EAP_IKEV2 += ../src/eap_peer/ikev2.c
+SRC_EAP_IKEV2 += ../src/eap_common/eap_ikev2_common.c
+SRC_EAP_IKEV2 += ../src/eap_common/ikev2_common.c
 ifeq ($(CONFIG_EAP_IKEV2), dyn)
 CFLAGS += -DEAP_IKEV2_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_ikev2.so ../src/eap_peer/ikev2.o
-EAPDYN += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
+EAPDYN += eap_ikev2.so
 else
 CFLAGS += -DEAP_IKEV2
-OBJS += ../src/eap_peer/eap_ikev2.o ../src/eap_peer/ikev2.o
-OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
+OBJS += $(patsubst %.c, %.o, $(SRC_EAP_IKEV2))
 endif
 CONFIG_IEEE8021X_EAPOL=y
 NEED_DH_GROUPS=y
@@ -843,7 +856,7 @@
 ifdef CONFIG_EAP_VENDOR_TEST
 ifeq ($(CONFIG_EAP_VENDOR_TEST), dyn)
 CFLAGS += -DEAP_VENDOR_TEST_DYNAMIC
-EAPDYN += ../src/eap_peer/eap_vendor_test.so
+EAPDYN += eap_vendor_test.so
 else
 CFLAGS += -DEAP_VENDOR_TEST
 OBJS += ../src/eap_peer/eap_vendor_test.o
@@ -1004,7 +1017,6 @@
 # PC/SC interface for smartcards (USIM, GSM SIM)
 CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC
 OBJS += ../src/utils/pcsc_funcs.o
-# -lpthread may not be needed depending on how pcsc-lite was configured
 ifdef CONFIG_NATIVE_WINDOWS
 #Once MinGW gets support for WinScard, -lwinscard could be used instead of the
 #dynamic symbol loading that is now used in pcsc_funcs.c
@@ -1013,7 +1025,7 @@
 ifdef CONFIG_OSX
 LIBS += -framework PCSC
 else
-LIBS += -lpcsclite -lpthread
+LIBS += $(shell $(PKG_CONFIG) --libs libpcsclite)
 endif
 endif
 endif
@@ -1951,33 +1963,60 @@
 	$(Q)$(LDO) $(LDFLAGS) -o $@ win_if_list.c $(CFLAGS) $(LIBS_w)
 	@$(E) "  LD " $@
 
-eap_psk.so: ../src/eap_peer/eap_psk.c ../src/eap_common/eap_psk_common.c
-	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+eap_psk.so: $(SRC_EAP_PSK)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
 		-Deap_peer_psk_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
 
-eap_pax.so: ../src/eap_peer/eap_pax.c ../src/eap_common/eap_pax_common.c
-	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-		-Deap_peer_pax_register=eap_peer_method_dynamic_init
+eap_pax.so: $(SRC_EAP_PAX)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
 
-eap_sake.so: ../src/eap_peer/eap_sake.c ../src/eap_common/eap_sake_common.c
-	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-		-Deap_peer_sake_register=eap_peer_method_dynamic_init
+eap_peap.so: $(SRC_EAP_PEAP)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
 
-eap_wsc.so: ../src/eap_peer/eap_wsc.c ../src/eap_common/eap_wsc_common.c ../src/wps/wps.c
-	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-		-Deap_peer_wsc_register=eap_peer_method_dynamic_init
+eap_sake.so: $(SRC_EAP_SAKE)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
 
-eap_ikev2.so: ../src/eap_peer/eap_ikev2.c ../src/eap_peer/ikev2.c ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.c
-	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-		-Deap_peer_ikev2_register=eap_peer_method_dynamic_init
+eap_ikev2.so: $(SRC_EAP_IKEV2)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
 
-eap_eke.so: ../src/eap_peer/eap_eke.c ../src/eap_common/eap_eke_common.c
-	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
-		-Deap_peer_eke_register=eap_peer_method_dynamic_init
+eap_eke.so: $(SRC_EAP_EKE)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
 
-%.so: %.c
-	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \
+eap_mschapv2.so: $(SRC_EAP_MSCHAPV2)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
+
+eap_fast.so: $(SRC_EAP_FAST)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
+
+eap_teap.so: $(SRC_EAP_TEAP)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
+
+eap_gpsk.so: $(SRC_EAP_GPSK)
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
+
+%.so: ../src/eap_peer/%.c
+	$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \
 		-D$(*F:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init
+	@$(E) "  CC/LD " $@
 
 %.service: %.service.in
 	$(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index 391912e..c643b26 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -1,7 +1,7 @@
 wpa_supplicant
 ==============
 
-Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors
 All Rights Reserved.
 
 This program is licensed under the BSD license (the one with
@@ -1077,3 +1077,87 @@
 OK
 <3>EXT-RADIO-WORK-START 7
 <3>EXT-RADIO-WORK-TIMEOUT 7
+
+
+DSCP policy procedures
+----------------------
+
+DSCP policy procedures defined in WFA QoS Management-R2 program
+facilitates AP devices to configure DSCP settings for specific uplink
+data streams.
+
+An AP may transmit a DSCP Policy Request frame containing zero or more
+QoS Management IEs to an associated STA which supports DSCP policy
+procedures. Each QoS Management element in a DSCP Policy Request frame
+represents one DSCP policy, and shall include one DSCP Policy attribute
+including a DSCP Policy ID, Request type, and a DSCP value.
+
+wpa_supplicant sends control interface event messages consisting details
+of DSCP policies requested by the AP through a DSCP Policy Request frame
+to external programs. The format of the control interface event messages
+is as shown below:
+
+- Control interface event message format to indicate DSCP request start
+
+  <3>CTRL-EVENT-DSCP-POLICY request_start [clear_all] [more]
+
+  clear_all - AP requested to clear all DSCP policies configured earlier
+  more      - AP may request to configure more DSCP policies with new DSCP
+              request
+
+- Control interface event message format to add new policy
+
+  <3>CTRL-EVENT-DSCP-POLICY add <policy_id> <dscp_value> <ip_version=0|4|6>
+  [protocol] [source ip] [destination_ip]/[domain name] [source port]
+  [[<start_port> <end_port>]/destination port]
+
+  ip_version = 0: Both IPv4 and IPv6
+             = 4: IPv4
+             = 6: IPv6
+  protocol: Internet Protocol Numbers as per IETF RFCs
+	 = 6: TCP
+	 = 17: UDP
+	 = 50: ESP
+
+- Control interface event message format to remove a particular policy,
+  identified by the policy_id attribute.
+
+  <3>CTRL-EVENT-DSCP-POLICY remove <policy_id>
+
+- DSCP policy may get rejected due to invalid policy parameters. Ccontrol
+  interface event message format for rejected policy.
+
+  <3>CTRL-EVENT-DSCP-POLICY reject <policy_id>
+
+- Control interface event message format to indicate end of DSCP request.
+
+  <3>CTRL-EVENT-DSCP-POLICY request_end
+
+- External applications shall clear active DSCP policies upon receiving
+  "CTRL-EVENT-DISCONNECTED" or "CTRL-EVENT-DSCP-POLICY clear_all" events.
+
+- Control interface event message format to indicate wpa_supplicant started
+  a timer to wait until the unsolicited DSCP request from the AP.
+
+  <3>CTRL-EVENT-DSCP-POLICY request_wait start
+
+- Control interface event message format to indicate timeout to receive the
+  unsolicited DSCP request. This event is expected only when an unsolicited
+  DSCP request is not received from the AP before timeout.
+
+  <3>CTRL-EVENT-DSCP-POLICY request_wait end
+
+DSCP Response:
+A QoS Management STA that enables DSCP Policy capability shall respond
+with DSCP response on receipt of a successful DSCP request from its
+associated AP.  wpa_supplicant sends DSCP policy response based on the
+control interface command received from the user is as below:
+
+DSCP_RESP <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
+
+DSCP Query:
+DSCP Policy Query enables a STA to query its associated AP for DSCP
+policies applicable to the STA. Currently, this includes support to send
+a wildcard DSCP query or a DSCP query with a single domain name
+attribute. The command format for the DSCP query command is as follows:
+DSCP_QUERY <wildcard>/<domain_name=<string>>
diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20
index 484e4cb..b076621 100644
--- a/wpa_supplicant/README-HS20
+++ b/wpa_supplicant/README-HS20
@@ -286,6 +286,12 @@
 #
 # sim_num: Identifier for which SIM to use in multi-SIM devices
 #
+# engine: Whether to use an engine for private key operations (0/1)
+# engine_id: String identifying the engine to use
+# ca_cert_id: The CA certificate identifier when using an engine
+# cert_id: The certificate identifier when using an engine
+# key_id: The private key identifier when using an engine
+#
 # for example:
 #
 #cred={
diff --git a/wpa_supplicant/hidl/.clang-format b/wpa_supplicant/aidl/.clang-format
similarity index 100%
rename from wpa_supplicant/hidl/.clang-format
rename to wpa_supplicant/aidl/.clang-format
diff --git a/wpa_supplicant/hidl/1.4/Android.bp b/wpa_supplicant/aidl/Android.bp
similarity index 77%
rename from wpa_supplicant/hidl/1.4/Android.bp
rename to wpa_supplicant/aidl/Android.bp
index b4ddae9..0785fe1 100644
--- a/wpa_supplicant/hidl/1.4/Android.bp
+++ b/wpa_supplicant/aidl/Android.bp
@@ -14,29 +14,28 @@
 
 package {
     // See: http://go/android-license-faq
-    // Inherits SPDX-license-identifier-BSD-3-Clause
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "external_wpa_supplicant_8_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-BSD
     default_applicable_licenses: ["external_wpa_supplicant_8_license"],
 }
 
 cc_library_headers {
-    name: "libwpa_hidl_headers",
+    name: "libwpa_aidl_headers",
     export_include_dirs: ["."],
     soc_specific: true,
 }
 
 cc_library_static {
-    name: "libwpa_hidl_bp",
+    name: "libwpa_aidl_bp",
     srcs: ["*.cpp"],
     defaults: ["wpa_supplicant_cflags_defaults"],
     soc_specific: true,
     shared_libs: [
-        "android.hardware.wifi.supplicant@1.0",
-        "android.hardware.wifi.supplicant@1.1",
-        "android.hardware.wifi.supplicant@1.2",
-        "android.hardware.wifi.supplicant@1.3",
-        "android.hardware.wifi.supplicant@1.4",
+        "android.hardware.wifi.supplicant-V1-ndk",
+        "libbinder_ndk",
         "libbase",
-        "libhidlbase",
         "libutils",
         "liblog",
         "libssl",
@@ -51,7 +50,7 @@
     ],
     header_libs: [
         "wpa_supplicant_headers",
-        "libwpa_hidl_headers",
+        "libwpa_aidl_headers",
     ],
 }
 
diff --git a/wpa_supplicant/aidl/aidl.cpp b/wpa_supplicant/aidl/aidl.cpp
new file mode 100644
index 0000000..a7945cc
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl.cpp
@@ -0,0 +1,1035 @@
+/*
+ * WPA Supplicant - Aidl entry point to wpa_supplicant core
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <android/binder_process.h>
+#include <android/binder_manager.h>
+
+#include "aidl_manager.h"
+
+extern "C"
+{
+#include "aidl.h"
+#include "aidl_i.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+#include "dpp.h"
+}
+
+using aidl::android::hardware::wifi::supplicant::AidlManager;
+using aidl::android::hardware::wifi::supplicant::AuxiliarySupplicantEventCode;
+using aidl::android::hardware::wifi::supplicant::DppEventType;
+using aidl::android::hardware::wifi::supplicant::DppFailureCode;
+using aidl::android::hardware::wifi::supplicant::DppProgressCode;
+
+static void wpas_aidl_notify_dpp_failure(struct wpa_supplicant *wpa_s, DppFailureCode code);
+static void wpas_aidl_notify_dpp_progress(struct wpa_supplicant *wpa_s, DppProgressCode code);
+static void wpas_aidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppEventType code);
+
+void wpas_aidl_sock_handler(
+	int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
+{
+	ABinderProcess_handlePolledCommands();
+}
+
+struct wpas_aidl_priv *wpas_aidl_init(struct wpa_global *global)
+{
+	struct wpas_aidl_priv *priv;
+	AidlManager *aidl_manager;
+
+	priv = (wpas_aidl_priv *)os_zalloc(sizeof(*priv));
+	if (!priv)
+		return NULL;
+	priv->global = global;
+
+	wpa_printf(MSG_DEBUG, "Initing aidl control");
+
+	ABinderProcess_setupPolling(&priv->aidl_fd);
+	if (priv->aidl_fd < 0)
+		goto err;
+
+	wpa_printf(MSG_INFO, "Processing aidl events on FD %d", priv->aidl_fd);
+	// Look for read events from the aidl socket in the eloop.
+	if (eloop_register_read_sock(
+		priv->aidl_fd, wpas_aidl_sock_handler, global, priv) < 0)
+		goto err;
+
+	aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		goto err;
+	if (aidl_manager->registerAidlService(global)) {
+		goto err;
+	}
+	// We may not need to store this aidl manager reference in the
+	// global data strucure because we've made it a singleton class.
+	priv->aidl_manager = (void *)aidl_manager;
+
+	return priv;
+err:
+	wpas_aidl_deinit(priv);
+	return NULL;
+}
+
+void wpas_aidl_deinit(struct wpas_aidl_priv *priv)
+{
+	if (!priv)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Deiniting aidl control");
+
+	AidlManager::destroyInstance();
+	eloop_unregister_read_sock(priv->aidl_fd);
+	os_free(priv);
+}
+
+int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->global->aidl)
+		return 1;
+
+	wpa_printf(
+		MSG_DEBUG, "Registering interface to aidl control: %s",
+		wpa_s->ifname);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return 1;
+
+	return aidl_manager->registerInterface(wpa_s);
+}
+
+int wpas_aidl_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->global->aidl)
+		return 1;
+
+	wpa_printf(
+		MSG_DEBUG, "Deregistering interface from aidl control: %s",
+		wpa_s->ifname);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return 1;
+
+	return aidl_manager->unregisterInterface(wpa_s);
+}
+
+int wpas_aidl_register_network(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !wpa_s->global->aidl || !ssid)
+		return 1;
+
+	wpa_printf(
+		MSG_DEBUG, "Registering network to aidl control: %d", ssid->id);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return 1;
+
+	return aidl_manager->registerNetwork(wpa_s, ssid);
+}
+
+int wpas_aidl_unregister_network(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !wpa_s->global->aidl || !ssid)
+		return 1;
+
+	wpa_printf(
+		MSG_DEBUG, "Deregistering network from aidl control: %d", ssid->id);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return 1;
+
+	return aidl_manager->unregisterNetwork(wpa_s, ssid);
+}
+
+int wpas_aidl_notify_state_changed(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->global->aidl)
+		return 1;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying state change event to aidl control: %d",
+		wpa_s->wpa_state);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return 1;
+
+	return aidl_manager->notifyStateChange(wpa_s);
+}
+
+int wpas_aidl_notify_network_request(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+	enum wpa_ctrl_req_type rtype, const char *default_txt)
+{
+	if (!wpa_s || !wpa_s->global->aidl || !ssid)
+		return 1;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying network request to aidl control: %d",
+		ssid->id);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return 1;
+
+	return aidl_manager->notifyNetworkRequest(
+		wpa_s, ssid, rtype, default_txt);
+}
+
+void wpas_aidl_notify_anqp_query_done(
+	struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+	const struct wpa_bss_anqp *anqp)
+{
+	if (!wpa_s || !wpa_s->global->aidl || !bssid || !result || !anqp)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying ANQP query done to aidl control: " MACSTR "result: %s",
+		MAC2STR(bssid), result);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyAnqpQueryDone(wpa_s, bssid, result, anqp);
+}
+
+void wpas_aidl_notify_hs20_icon_query_done(
+	struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+	const u8 *image, u32 image_length)
+{
+	if (!wpa_s || !wpa_s->global->aidl || !bssid || !file_name || !image)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying HS20 icon query done to aidl control: " MACSTR
+		"file_name: %s",
+		MAC2STR(bssid), file_name);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyHs20IconQueryDone(
+		wpa_s, bssid, file_name, image, image_length);
+}
+
+void wpas_aidl_notify_hs20_rx_subscription_remediation(
+	struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+	if (!wpa_s || !wpa_s->global->aidl || !url)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying HS20 subscription remediation rx to aidl control: %s",
+		url);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyHs20RxSubscriptionRemediation(
+		wpa_s, url, osu_method);
+}
+
+void wpas_aidl_notify_hs20_rx_deauth_imminent_notice(
+	struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+	if (!wpa_s || !wpa_s->global->aidl)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying HS20 deauth imminent notice rx to aidl control: %s",
+		url ? url : "<no URL>");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyHs20RxDeauthImminentNotice(
+		wpa_s, code, reauth_delay, url);
+}
+
+void wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(
+		struct wpa_supplicant *wpa_s, const char *url)
+{
+	if (!wpa_s || !wpa_s->global->aidl || !url)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+			"Notifying HS20 terms and conditions acceptance rx to aidl control: %s",
+			url);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyHs20RxTermsAndConditionsAcceptance(wpa_s, url);
+}
+
+void wpas_aidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying disconnect reason to aidl control: %d",
+		wpa_s->disconnect_reason);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyDisconnectReason(wpa_s);
+}
+
+void wpas_aidl_notify_assoc_reject(struct wpa_supplicant *wpa_s,
+	const u8 *bssid, u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying assoc reject to aidl control: %d",
+		wpa_s->assoc_status_code);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyAssocReject(wpa_s, bssid, timed_out, assoc_resp_ie, assoc_resp_ie_len);
+}
+
+void wpas_aidl_notify_auth_timeout(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying auth timeout to aidl control");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyAuthTimeout(wpa_s);
+}
+
+void wpas_aidl_notify_bssid_changed(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying bssid changed to aidl control");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyBssidChanged(wpa_s);
+}
+
+void wpas_aidl_notify_wps_event_fail(
+	struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+	uint16_t error_indication)
+{
+	if (!wpa_s || !peer_macaddr)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying Wps event fail to aidl control: %d, %d",
+		config_error, error_indication);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyWpsEventFail(
+		wpa_s, peer_macaddr, config_error, error_indication);
+}
+
+void wpas_aidl_notify_wps_event_success(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying Wps event success to aidl control");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyWpsEventSuccess(wpa_s);
+}
+
+void wpas_aidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying Wps event PBC overlap to aidl control");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyWpsEventPbcOverlap(wpa_s);
+}
+
+void wpas_aidl_notify_p2p_device_found(
+	struct wpa_supplicant *wpa_s, const u8 *addr,
+	const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+	u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+	u8 peer_wfd_r2_device_info_len)
+{
+	if (!wpa_s || !addr || !info)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying P2P device found to aidl control " MACSTR,
+		MAC2STR(info->p2p_device_addr));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pDeviceFound(
+		wpa_s, addr, info, peer_wfd_device_info,
+		peer_wfd_device_info_len, peer_wfd_r2_device_info,
+		peer_wfd_r2_device_info_len);
+}
+
+void wpas_aidl_notify_p2p_device_lost(
+	struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{
+	if (!wpa_s || !p2p_device_addr)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying P2P device lost to aidl control " MACSTR,
+		MAC2STR(p2p_device_addr));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pDeviceLost(wpa_s, p2p_device_addr);
+}
+
+void wpas_aidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying P2P find stop to aidl control");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pFindStopped(wpa_s);
+}
+
+void wpas_aidl_notify_p2p_go_neg_req(
+	struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+	u8 go_intent)
+{
+	if (!wpa_s || !src_addr)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P GO negotiation request to aidl control " MACSTR,
+		MAC2STR(src_addr));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pGoNegReq(
+		wpa_s, src_addr, dev_passwd_id, go_intent);
+}
+
+void wpas_aidl_notify_p2p_go_neg_completed(
+	struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{
+	if (!wpa_s || !res)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P GO negotiation completed to aidl control: %d",
+		res->status);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pGoNegCompleted(wpa_s, res);
+}
+
+void wpas_aidl_notify_p2p_group_formation_failure(
+	struct wpa_supplicant *wpa_s, const char *reason)
+{
+	if (!wpa_s || !reason)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P Group formation failure to aidl control: %s",
+		reason);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pGroupFormationFailure(wpa_s, reason);
+}
+
+void wpas_aidl_notify_p2p_group_started(
+	struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
+	int client)
+{
+	if (!wpa_s || !ssid)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying P2P Group start to aidl control: %d",
+		ssid->id);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pGroupStarted(wpa_s, ssid, persistent, client);
+}
+
+void wpas_aidl_notify_p2p_group_removed(
+	struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
+{
+	if (!wpa_s || !ssid || !role)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying P2P Group removed to aidl control: %d",
+		ssid->id);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pGroupRemoved(wpa_s, ssid, role);
+}
+
+void wpas_aidl_notify_p2p_invitation_received(
+	struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+	const u8 *bssid, int id, int op_freq)
+{
+	if (!wpa_s || !sa || !go_dev_addr || !bssid)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P invitation received to aidl control: %d " MACSTR, id,
+		MAC2STR(bssid));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pInvitationReceived(
+		wpa_s, sa, go_dev_addr, bssid, id, op_freq);
+}
+
+void wpas_aidl_notify_p2p_invitation_result(
+	struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{
+	if (!wpa_s)
+		return;
+	if (bssid) {
+		wpa_printf(
+			MSG_DEBUG,
+			"Notifying P2P invitation result to aidl control: " MACSTR,
+			MAC2STR(bssid));
+	} else {
+		wpa_printf(
+			MSG_DEBUG,
+			"Notifying P2P invitation result to aidl control: NULL "
+			"bssid");
+	}
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pInvitationResult(wpa_s, status, bssid);
+}
+
+void wpas_aidl_notify_p2p_provision_discovery(
+	struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+	enum p2p_prov_disc_status status, u16 config_methods,
+	unsigned int generated_pin)
+{
+	if (!wpa_s || !dev_addr)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P provision discovery to aidl control " MACSTR,
+		MAC2STR(dev_addr));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pProvisionDiscovery(
+		wpa_s, dev_addr, request, status, config_methods, generated_pin);
+}
+
+void wpas_aidl_notify_p2p_sd_response(
+	struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+	const u8 *tlvs, size_t tlvs_len)
+{
+	if (!wpa_s || !sa || !tlvs)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P service discovery response to aidl control " MACSTR,
+		MAC2STR(sa));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pSdResponse(
+		wpa_s, sa, update_indic, tlvs, tlvs_len);
+}
+
+void wpas_aidl_notify_ap_sta_authorized(
+	struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_s || !sta)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P AP STA authorized to aidl control " MACSTR,
+		MAC2STR(sta));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyApStaAuthorized(wpa_s, sta, p2p_dev_addr);
+}
+
+void wpas_aidl_notify_ap_sta_deauthorized(
+	struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_s || !sta)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P AP STA deauthorized to aidl control " MACSTR,
+		MAC2STR(sta));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyApStaDeauthorized(wpa_s, sta, p2p_dev_addr);
+}
+
+void wpas_aidl_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying EAP Error: %d ", error_code);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyEapError(wpa_s, error_code);
+}
+
+void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+		struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !ssid)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying DPP configuration received for SSID %d", ssid->id);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyDppConfigReceived(wpa_s, ssid);
+}
+
+void wpas_aidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_success(wpa_s, DppEventType::CONFIGURATION_SENT);
+}
+
+/* DPP Progress notifications */
+void wpas_aidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::AUTHENTICATION_SUCCESS);
+}
+
+void wpas_aidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::RESPONSE_PENDING);
+}
+
+/* DPP Failure notifications */
+void wpas_aidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::NOT_COMPATIBLE);
+}
+
+void wpas_aidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::AUTHENTICATION);
+}
+
+void wpas_aidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::CONFIGURATION);
+}
+
+void wpas_aidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::TIMEOUT);
+}
+
+void wpas_aidl_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::AUTHENTICATION);
+}
+
+void wpas_aidl_notify_dpp_fail(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::FAILURE);
+}
+
+void wpas_aidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::CONFIGURATION_SENT_WAITING_RESPONSE);
+}
+
+/* DPP notification helper functions */
+static void wpas_aidl_notify_dpp_failure(struct wpa_supplicant *wpa_s, DppFailureCode code)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying DPP failure event %d", code);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyDppFailure(wpa_s, code);
+}
+
+static void wpas_aidl_notify_dpp_progress(struct wpa_supplicant *wpa_s, DppProgressCode code)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying DPP progress event %d", code);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyDppProgress(wpa_s, code);
+}
+
+void wpas_aidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::CONFIGURATION_ACCEPTED);
+}
+
+static void wpas_aidl_notify_dpp_config_applied(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_success(wpa_s, DppEventType::CONFIGURATION_APPLIED);
+}
+
+static void wpas_aidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppEventType code)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying DPP progress event %d", code);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyDppSuccess(wpa_s, code);
+}
+
+void wpas_aidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s)
+{
+	wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::CONFIGURATION_REJECTED);
+}
+
+static void wpas_aidl_notify_dpp_no_ap_failure(struct wpa_supplicant *wpa_s,
+		const char *ssid, const char *channel_list, unsigned short band_list[],
+		int size)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+			"Notifying DPP NO AP event for SSID %s\nTried channels: %s",
+			ssid ? ssid : "N/A", channel_list ? channel_list : "N/A");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyDppFailure(wpa_s, DppFailureCode::CANNOT_FIND_NETWORK,
+			ssid, channel_list, band_list, size);
+}
+
+void wpas_aidl_notify_dpp_enrollee_auth_failure(struct wpa_supplicant *wpa_s,
+		const char *ssid, unsigned short band_list[], int size)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+			"Notifying DPP Enrollee authentication failure, SSID %s",
+			ssid ? ssid : "N/A");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyDppFailure(wpa_s, DppFailureCode::ENROLLEE_AUTHENTICATION,
+			ssid, NULL, band_list, size);
+}
+
+
+void wpas_aidl_notify_dpp_conn_status(struct wpa_supplicant *wpa_s, enum dpp_status_error status,
+		const char *ssid, const char *channel_list, unsigned short band_list[], int size)
+{
+	switch (status)
+	{
+	case DPP_STATUS_OK:
+		wpas_aidl_notify_dpp_config_applied(wpa_s);
+		break;
+
+	case DPP_STATUS_NO_AP:
+		wpas_aidl_notify_dpp_no_ap_failure(wpa_s, ssid, channel_list, band_list, size);
+		break;
+
+	case DPP_STATUS_AUTH_FAILURE:
+		wpas_aidl_notify_dpp_enrollee_auth_failure(wpa_s, ssid, band_list, size);
+		break;
+
+	default:
+		break;
+	}
+}
+
+void wpas_aidl_notify_pmk_cache_added(
+	struct wpa_supplicant *wpa_s,
+	struct rsn_pmksa_cache_entry *pmksa_entry)
+{
+	if (!wpa_s || !pmksa_entry)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying PMK cache added event");
+
+	aidl_manager->notifyPmkCacheAdded(wpa_s, pmksa_entry);
+}
+
+void wpas_aidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying BSS transition status");
+
+	aidl_manager->notifyBssTmStatus(wpa_s);
+}
+
+void wpas_aidl_notify_transition_disable(struct wpa_supplicant *wpa_s,
+						struct wpa_ssid *ssid,
+						u8 bitmap)
+{
+	if (!wpa_s || !ssid)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyTransitionDisable(wpa_s, ssid, bitmap);
+}
+
+void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notify network not found");
+
+	aidl_manager->notifyNetworkNotFound(wpa_s);
+}
+
+void wpas_aidl_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency)
+{
+	if (!wpa_s)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_INFO, "Notify %s frequency changed to %d",
+	    wpa_s->ifname, frequency);
+
+	aidl_manager->notifyFrequencyChanged(wpa_s, frequency);
+}
+
+void wpas_aidl_notify_ceritification(struct wpa_supplicant *wpa_s,
+		int depth, const char *subject,
+		const char *altsubject[],
+		int num_altsubject,
+		const char *cert_hash,
+		const struct wpabuf *cert)
+{
+	if (!wpa_s)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notify certification");
+
+	aidl_manager->notifyCertification(wpa_s,
+			depth,
+			subject,
+			altsubject,
+			num_altsubject,
+			cert_hash,
+			cert);
+}
+
+void wpas_aidl_notify_auxiliary_event(struct wpa_supplicant *wpa_s,
+	AuxiliarySupplicantEventCode event_code, const char *reason_string)
+{
+	if (!wpa_s)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notify auxiliary event, code=%d",
+		static_cast<int>(event_code));
+	aidl_manager->notifyAuxiliaryEvent(wpa_s, event_code, reason_string);
+}
+
+void wpas_aidl_notify_eap_method_selected(struct wpa_supplicant *wpa_s,
+	const char *reason_string)
+{
+	wpas_aidl_notify_auxiliary_event(wpa_s,
+		AuxiliarySupplicantEventCode::EAP_METHOD_SELECTED,
+		reason_string);
+}
+
+void wpas_aidl_notify_ssid_temp_disabled(struct wpa_supplicant *wpa_s,
+	const char *reason_string)
+{
+	wpas_aidl_notify_auxiliary_event(wpa_s,
+		AuxiliarySupplicantEventCode::SSID_TEMP_DISABLED,
+		reason_string);
+}
+
+void wpas_aidl_notify_open_ssl_failure(struct wpa_supplicant *wpa_s,
+	const char *reason_string)
+{
+	wpas_aidl_notify_auxiliary_event(wpa_s,
+		AuxiliarySupplicantEventCode::OPEN_SSL_FAILURE,
+		reason_string);
+}
+
+void wpas_aidl_notify_qos_policy_reset(
+	struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+	wpa_printf(
+		MSG_DEBUG, "Notifying Qos Policy Reset");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyQosPolicyReset(wpa_s);
+}
+
+void wpas_aidl_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
+	struct dscp_policy_data *policies, int num_policies)
+{
+	if (!wpa_s || !policies)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG, "Notifying Qos Policy Request");
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyQosPolicyRequest(wpa_s, policies, num_policies);
+}
+
diff --git a/wpa_supplicant/aidl/aidl.h b/wpa_supplicant/aidl/aidl.h
new file mode 100644
index 0000000..2f3c7a0
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl.h
@@ -0,0 +1,325 @@
+/*
+ * WPA Supplicant - Aidl entry point to wpa_supplicant core
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_AIDL_H
+#define WPA_SUPPLICANT_AIDL_AIDL_H
+
+#ifdef _cplusplus
+extern "C"
+{
+#endif  // _cplusplus
+
+	/**
+	 * This is the aidl RPC interface entry point to the wpa_supplicant
+	 * core. This initializes the aidl driver & AidlManager instance and
+	 * then forwards all the notifcations from the supplicant core to the
+	 * AidlManager.
+	 */
+	struct wpas_aidl_priv;
+	struct wpa_global;
+
+	struct wpas_aidl_priv *wpas_aidl_init(struct wpa_global *global);
+	void wpas_aidl_deinit(struct wpas_aidl_priv *priv);
+
+#ifdef CONFIG_CTRL_IFACE_AIDL
+	int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s);
+	int wpas_aidl_unregister_interface(struct wpa_supplicant *wpa_s);
+	int wpas_aidl_register_network(
+		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+	int wpas_aidl_unregister_network(
+		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+	int wpas_aidl_notify_state_changed(struct wpa_supplicant *wpa_s);
+	int wpas_aidl_notify_network_request(
+		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+		enum wpa_ctrl_req_type rtype, const char *default_txt);
+	void wpas_aidl_notify_anqp_query_done(
+		struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+		const struct wpa_bss_anqp *anqp);
+	void wpas_aidl_notify_hs20_icon_query_done(
+		struct wpa_supplicant *wpa_s, const u8 *bssid,
+		const char *file_name, const u8 *image, u32 image_length);
+	void wpas_aidl_notify_hs20_rx_subscription_remediation(
+		struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+	void wpas_aidl_notify_hs20_rx_deauth_imminent_notice(
+		struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
+		const char *url);
+	void wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(
+			struct wpa_supplicant *wpa_s, const char *url);
+	void wpas_aidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_assoc_reject(struct wpa_supplicant *wpa_s, const u8 *bssid,
+		u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len);
+	void wpas_aidl_notify_auth_timeout(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_bssid_changed(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_wps_event_fail(
+		struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
+		uint16_t config_error, uint16_t error_indication);
+	void wpas_aidl_notify_wps_event_success(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_wps_event_pbc_overlap(
+		struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_p2p_device_found(
+		struct wpa_supplicant *wpa_s, const u8 *addr,
+		const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+		u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+		u8 peer_wfd_r2_device_info_len);
+	void wpas_aidl_notify_p2p_device_lost(
+		struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
+	void wpas_aidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_p2p_go_neg_req(
+		struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+		u8 go_intent);
+	void wpas_aidl_notify_p2p_go_neg_completed(
+		struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
+	void wpas_aidl_notify_p2p_group_formation_failure(
+		struct wpa_supplicant *wpa_s, const char *reason);
+	void wpas_aidl_notify_p2p_group_started(
+		struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid,
+		int persistent, int client);
+	void wpas_aidl_notify_p2p_group_removed(
+		struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid,
+		const char *role);
+	void wpas_aidl_notify_p2p_invitation_received(
+		struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+		const u8 *bssid, int id, int op_freq);
+	void wpas_aidl_notify_p2p_invitation_result(
+		struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
+	void wpas_aidl_notify_p2p_provision_discovery(
+		struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+		enum p2p_prov_disc_status status, u16 config_methods,
+		unsigned int generated_pin);
+	void wpas_aidl_notify_p2p_sd_response(
+		struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+		const u8 *tlvs, size_t tlvs_len);
+	void wpas_aidl_notify_ap_sta_authorized(
+		struct wpa_supplicant *wpa_s, const u8 *sta,
+		const u8 *p2p_dev_addr);
+	void wpas_aidl_notify_ap_sta_deauthorized(
+		struct wpa_supplicant *wpa_s, const u8 *sta,
+		const u8 *p2p_dev_addr);
+	void wpas_aidl_notify_eap_error(
+		struct wpa_supplicant *wpa_s, int error_code);
+	void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+			struct wpa_ssid *ssid);
+	void wpas_aidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_invalid_uri(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_fail(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_dpp_conn_status(struct wpa_supplicant *wpa_s,
+		enum dpp_status_error status, const char *ssid,
+		const char *channel_list, unsigned short band_list[], int size);
+	void wpas_aidl_notify_pmk_cache_added(
+		struct wpa_supplicant *wpas, struct rsn_pmksa_cache_entry *pmksa_entry);
+	void wpas_aidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_transition_disable(
+		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, u8 bitmap);
+	void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency);
+	void wpas_aidl_notify_ceritification(struct wpa_supplicant *wpa_s,
+		int depth, const char *subject,
+		const char *altsubject[],
+		int num_altsubject,
+		const char *cert_hash,
+		const struct wpabuf *cert);
+	void wpas_aidl_notify_eap_method_selected(struct wpa_supplicant *wpa_s,
+		const char *reason_string);
+	void wpas_aidl_notify_ssid_temp_disabled(struct wpa_supplicant *wpa_s,
+		const char *reason_string);
+	void wpas_aidl_notify_open_ssl_failure(struct wpa_supplicant *wpa_s,
+		const char *reason_string);
+	void wpas_aidl_notify_qos_policy_reset(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
+		struct dscp_policy_data *policies, int num_policies);
+#else   // CONFIG_CTRL_IFACE_AIDL
+static inline int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+static inline int wpas_aidl_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+static inline int wpas_aidl_register_network(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	return 0;
+}
+static inline int wpas_aidl_unregister_network(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	return 0;
+}
+static inline int wpas_aidl_notify_state_changed(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+static inline int wpas_aidl_notify_network_request(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+	enum wpa_ctrl_req_type rtype, const char *default_txt)
+{
+	return 0;
+}
+static void wpas_aidl_notify_anqp_query_done(
+	struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+	const struct wpa_bss_anqp *anqp)
+{}
+static void wpas_aidl_notify_hs20_icon_query_done(
+	struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+	const u8 *image, u32 image_length)
+{}
+static void wpas_aidl_notify_hs20_rx_subscription_remediation(
+	struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{}
+static void wpas_aidl_notify_hs20_rx_deauth_imminent_notice(
+	struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{}
+void wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(
+		struct wpa_supplicant *wpa_s, const char *url)
+{}
+static void wpas_aidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_assoc_reject(struct wpa_supplicant *wpa_s, const u8 *bssid,
+	u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len) {}
+static void wpas_aidl_notify_auth_timeout(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_wps_event_fail(
+	struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+	uint16_t error_indication)
+{}
+static void wpas_aidl_notify_bssid_changed(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_wps_event_success(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_p2p_device_found(
+	struct wpa_supplicant *wpa_s, const u8 *addr,
+	const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+	u8 peer_wfd_device_info_len)
+{}
+static void wpas_aidl_notify_p2p_device_lost(
+	struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{}
+static void wpas_aidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_p2p_go_neg_req(
+	struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+	u8 go_intent)
+{}
+static void wpas_aidl_notify_p2p_go_neg_completed(
+	struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{}
+static void wpas_aidl_notify_p2p_group_formation_failure(
+	struct wpa_supplicant *wpa_s, const char *reason)
+{}
+static void wpas_aidl_notify_p2p_group_started(
+	struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
+	int client)
+{}
+static void wpas_aidl_notify_p2p_group_removed(
+	struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
+{}
+static void wpas_aidl_notify_p2p_invitation_received(
+	struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+	const u8 *bssid, int id, int op_freq)
+{}
+static void wpas_aidl_notify_p2p_invitation_result(
+	struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{}
+static void wpas_aidl_notify_p2p_provision_discovery(
+	struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+	enum p2p_prov_disc_status status, u16 config_methods,
+	unsigned int generated_pin)
+{}
+static void wpas_aidl_notify_p2p_sd_response(
+	struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+	const u8 *tlvs, size_t tlvs_len)
+{}
+static void wpas_aidl_notify_ap_sta_authorized(
+	struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{}
+static void wpas_aidl_notify_ap_sta_deauthorized(
+	struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{}
+static void wpas_aidl_notify_eap_error(
+	struct wpa_supplicant *wpa_s, int error_code)
+{}
+static void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+		struct wpa_ssid *ssid)
+{}
+static void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+		struct wpa_ssid *ssid);
+static void wpas_aidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_invalid_uri(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_failure(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_applied(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_pmk_cache_added(struct wpa_supplicant *wpas,
+						 struct rsn_pmksa_cache_entry *pmksa_entry)
+{}
+void wpas_aidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_transition_disable(struct wpa_supplicant *wpa_s,
+						struct wpa_ssid *ssid,
+						u8 bitmap)
+{}
+static void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency)
+{}
+void wpas_aidl_notify_ceritification(struct wpa_supplicant *wpa_s,
+	int depth, const char *subject,
+	const char *altsubject[],
+	int num_altsubject,
+	const char *cert_hash,
+	const struct wpabuf *cert)
+{}
+void wpas_aidl_notify_eap_method_selected(struct wpa_supplicant *wpa_s,
+	const char *reason_string)
+{}
+void wpas_aidl_notify_ssid_temp_disabled(struct wpa_supplicant *wpa_s,
+	const char *reason_string)
+{}
+void wpas_aidl_notify_open_ssl_failure(struct wpa_supplicant *wpa_s,
+	const char *reason_string)
+{}
+static void wpas_aidl_notify_qos_policy_reset(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
+						struct dscp_policy_data *policies,
+						int num_policies)
+{}
+#endif  // CONFIG_CTRL_IFACE_AIDL
+
+#ifdef _cplusplus
+}
+#endif  // _cplusplus
+
+#endif  // WPA_SUPPLICANT_AIDL_AIDL_H
diff --git a/wpa_supplicant/aidl/aidl_i.h b/wpa_supplicant/aidl/aidl_i.h
new file mode 100644
index 0000000..7f377cd
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_i.h
@@ -0,0 +1,28 @@
+/*
+ * WPA Supplicant - Global Aidl struct
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AIDL_I_H
+#define AIDL_I_H
+
+#ifdef _cplusplus
+extern "C"
+{
+#endif  // _cplusplus
+
+	struct wpas_aidl_priv
+	{
+		int aidl_fd;
+		struct wpa_global *global;
+		void *aidl_manager;
+	};
+
+#ifdef _cplusplus
+}
+#endif  // _cplusplus
+
+#endif  // AIDL_I_H
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
new file mode 100644
index 0000000..da90c38
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -0,0 +1,2466 @@
+/*
+ * WPA Supplicant - Manager for Aidl interface objects
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <algorithm>
+#include <functional>
+#include <iostream>
+#include <regex>
+
+#include "aidl_manager.h"
+#include "misc_utils.h"
+#include <android/binder_process.h>
+#include <android/binder_manager.h>
+#include <aidl/android/hardware/wifi/supplicant/IpVersion.h>
+
+extern "C" {
+#include "scan.h"
+#include "src/eap_common/eap_sim_common.h"
+#include "list.h"
+}
+
+namespace {
+
+constexpr uint8_t kWfdDeviceInfoLen = 6;
+constexpr uint8_t kWfdR2DeviceInfoLen = 2;
+// GSM-AUTH:<RAND1>:<RAND2>[:<RAND3>]
+constexpr char kGsmAuthRegex2[] = "GSM-AUTH:([0-9a-f]+):([0-9a-f]+)";
+constexpr char kGsmAuthRegex3[] =
+	"GSM-AUTH:([0-9a-f]+):([0-9a-f]+):([0-9a-f]+)";
+// UMTS-AUTH:<RAND>:<AUTN>
+constexpr char kUmtsAuthRegex[] = "UMTS-AUTH:([0-9a-f]+):([0-9a-f]+)";
+constexpr size_t kGsmRandLenBytes = GSM_RAND_LEN;
+constexpr size_t kUmtsRandLenBytes = EAP_AKA_RAND_LEN;
+constexpr size_t kUmtsAutnLenBytes = EAP_AKA_AUTN_LEN;
+const std::vector<uint8_t> kZeroBssid = {0, 0, 0, 0, 0, 0};
+
+using aidl::android::hardware::wifi::supplicant::GsmRand;
+
+/**
+ * Check if the provided |wpa_supplicant| structure represents a P2P iface or
+ * not.
+ */
+constexpr bool isP2pIface(const struct wpa_supplicant *wpa_s)
+{
+	return wpa_s->global->p2p_init_wpa_s == wpa_s;
+}
+
+/**
+ * Creates a unique key for the network using the provided |ifname| and
+ * |network_id| to be used in the internal map of |ISupplicantNetwork| objects.
+ * This is of the form |ifname|_|network_id|. For ex: "wlan0_1".
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ */
+const std::string getNetworkObjectMapKey(
+	const std::string &ifname, int network_id)
+{
+	return ifname + "_" + std::to_string(network_id);
+}
+
+/**
+ * Add callback to the corresponding list after linking to death on the
+ * corresponding aidl object reference.
+ */
+template <class CallbackType>
+int registerForDeathAndAddCallbackAidlObjectToList(
+	AIBinder_DeathRecipient* death_notifier,
+	const std::shared_ptr<CallbackType> &callback,
+	std::vector<std::shared_ptr<CallbackType>> &callback_list)
+{
+	binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+			death_notifier, nullptr /* cookie */);
+	if (status != STATUS_OK) {
+		wpa_printf(
+			MSG_ERROR,
+			"Error registering for death notification for "
+			"supplicant callback object");
+		return 1;
+	}
+	callback_list.push_back(callback);
+	return 0;
+}
+
+template <class ObjectType>
+int addAidlObjectToMap(
+	const std::string &key, const std::shared_ptr<ObjectType> &object,
+	std::map<const std::string, std::shared_ptr<ObjectType>> &object_map)
+{
+	// Return failure if we already have an object for that |key|.
+	if (object_map.find(key) != object_map.end())
+		return 1;
+	object_map[key] = object;
+	if (!object_map[key].get())
+		return 1;
+	return 0;
+}
+
+template <class ObjectType>
+int removeAidlObjectFromMap(
+	const std::string &key,
+	std::map<const std::string, std::shared_ptr<ObjectType>> &object_map)
+{
+	// Return failure if we dont have an object for that |key|.
+	const auto &object_iter = object_map.find(key);
+	if (object_iter == object_map.end())
+		return 1;
+	object_iter->second->invalidate();
+	object_map.erase(object_iter);
+	return 0;
+}
+
+template <class CallbackType>
+int addIfaceCallbackAidlObjectToMap(
+	AIBinder_DeathRecipient* death_notifier,
+	const std::string &ifname, const std::shared_ptr<CallbackType> &callback,
+	std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty())
+		return 1;
+
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == callbacks_map.end())
+		return 1;
+	auto &iface_callback_list = iface_callback_map_iter->second;
+
+	// Register for death notification before we add it to our list.
+	return registerForDeathAndAddCallbackAidlObjectToList<CallbackType>(
+		death_notifier, callback, iface_callback_list);
+}
+
+template <class CallbackType>
+int addNetworkCallbackAidlObjectToMap(
+	AIBinder_DeathRecipient* death_notifier,
+	const std::string &ifname, int network_id,
+	const std::shared_ptr<CallbackType> &callback,
+	std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty() || network_id < 0)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+		getNetworkObjectMapKey(ifname, network_id);
+	auto network_callback_map_iter = callbacks_map.find(network_key);
+	if (network_callback_map_iter == callbacks_map.end())
+		return 1;
+	auto &network_callback_list = network_callback_map_iter->second;
+
+	// Register for death notification before we add it to our list.
+	return registerForDeathAndAddCallbackAidlObjectToList<CallbackType>(
+		death_notifier, callback, network_callback_list);
+}
+
+template <class CallbackType>
+int removeAllIfaceCallbackAidlObjectsFromMap(
+	AIBinder_DeathRecipient* death_notifier,
+	const std::string &ifname,
+	std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&callbacks_map)
+{
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == callbacks_map.end())
+		return 1;
+	const auto &iface_callback_list = iface_callback_map_iter->second;
+	for (const auto &callback : iface_callback_list) {
+		binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+				death_notifier, nullptr /* cookie */);
+		if (status != STATUS_OK) {
+			wpa_printf(
+				MSG_ERROR,
+				"Error deregistering for death notification for "
+				"iface callback object");
+		}
+	}
+	callbacks_map.erase(iface_callback_map_iter);
+	return 0;
+}
+
+template <class CallbackType>
+int removeAllNetworkCallbackAidlObjectsFromMap(
+	AIBinder_DeathRecipient* death_notifier,
+	const std::string &network_key,
+	std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&callbacks_map)
+{
+	auto network_callback_map_iter = callbacks_map.find(network_key);
+	if (network_callback_map_iter == callbacks_map.end())
+		return 1;
+	const auto &network_callback_list = network_callback_map_iter->second;
+	for (const auto &callback : network_callback_list) {
+		binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+				death_notifier, nullptr /* cookie */);
+		if (status != STATUS_OK) {
+			wpa_printf(
+				MSG_ERROR,
+				"Error deregistering for death "
+				"notification for "
+				"network callback object");
+		}
+	}
+	callbacks_map.erase(network_callback_map_iter);
+	return 0;
+}
+
+template <class CallbackType>
+void removeIfaceCallbackAidlObjectFromMap(
+	const std::string &ifname, const std::shared_ptr<CallbackType> &callback,
+	std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty())
+		return;
+
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == callbacks_map.end())
+		return;
+
+	auto &iface_callback_list = iface_callback_map_iter->second;
+	iface_callback_list.erase(
+		std::remove(
+		iface_callback_list.begin(), iface_callback_list.end(),
+		callback),
+		iface_callback_list.end());
+}
+
+template <class CallbackType>
+void removeNetworkCallbackAidlObjectFromMap(
+	const std::string &ifname, int network_id,
+	const std::shared_ptr<CallbackType> &callback,
+	std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty() || network_id < 0)
+		return;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+		getNetworkObjectMapKey(ifname, network_id);
+
+	auto network_callback_map_iter = callbacks_map.find(network_key);
+	if (network_callback_map_iter == callbacks_map.end())
+		return;
+
+	auto &network_callback_list = network_callback_map_iter->second;
+	network_callback_list.erase(
+		std::remove(
+		network_callback_list.begin(), network_callback_list.end(),
+		callback),
+		network_callback_list.end());
+}
+
+template <class CallbackType>
+void callWithEachIfaceCallback(
+	const std::string &ifname,
+	const std::function<ndk::ScopedAStatus(std::shared_ptr<CallbackType>)> &method,
+	const std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&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) {
+		if (!method(callback).isOk()) {
+			wpa_printf(
+				MSG_ERROR, "Failed to invoke AIDL iface callback");
+		}
+	}
+}
+
+template <class CallbackType>
+void callWithEachNetworkCallback(
+	const std::string &ifname, int network_id,
+	const std::function<
+	ndk::ScopedAStatus(std::shared_ptr<CallbackType>)> &method,
+	const std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty() || network_id < 0)
+		return;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+		getNetworkObjectMapKey(ifname, network_id);
+	auto network_callback_map_iter = callbacks_map.find(network_key);
+	if (network_callback_map_iter == callbacks_map.end())
+		return;
+	const auto &network_callback_list = network_callback_map_iter->second;
+	for (const auto &callback : network_callback_list) {
+		if (!method(callback).isOk()) {
+			wpa_printf(
+				MSG_ERROR,
+				"Failed to invoke AIDL network callback");
+		}
+	}
+}
+
+int parseGsmAuthNetworkRequest(
+	const std::string &params_str,
+	std::vector<GsmRand> *out_rands)
+{
+	std::smatch matches;
+	std::regex params_gsm_regex2(kGsmAuthRegex2);
+	std::regex params_gsm_regex3(kGsmAuthRegex3);
+	if (!std::regex_match(params_str, matches, params_gsm_regex3) &&
+		!std::regex_match(params_str, matches, params_gsm_regex2)) {
+		return 1;
+	}
+	for (uint32_t i = 1; i < matches.size(); i++) {
+		GsmRand rand;
+		rand.data = std::vector<uint8_t>(kGsmRandLenBytes);
+		const auto &match = matches[i];
+		WPA_ASSERT(match.size() >= 2 * rand.data.size());
+		if (hexstr2bin(match.str().c_str(), rand.data.data(), rand.data.size())) {
+			wpa_printf(MSG_ERROR, "Failed to parse GSM auth params");
+			return 1;
+		}
+		out_rands->push_back(rand);
+	}
+	return 0;
+}
+
+int parseUmtsAuthNetworkRequest(
+	const std::string &params_str,
+	std::vector<uint8_t> *out_rand,
+	std::vector<uint8_t> *out_autn)
+{
+	std::smatch matches;
+	std::regex params_umts_regex(kUmtsAuthRegex);
+	if (!std::regex_match(params_str, matches, params_umts_regex)) {
+		return 1;
+	}
+	WPA_ASSERT(matches[1].size() >= 2 * out_rand->size());
+	if (hexstr2bin(
+		matches[1].str().c_str(), out_rand->data(), out_rand->size())) {
+		wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
+		return 1;
+	}
+	WPA_ASSERT(matches[2].size() >= 2 * out_autn->size());
+	if (hexstr2bin(
+		matches[2].str().c_str(), out_autn->data(), out_autn->size())) {
+		wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
+		return 1;
+	}
+	return 0;
+}
+
+inline std::vector<uint8_t> byteArrToVec(const uint8_t* arr, int len) {
+	return std::vector<uint8_t>{arr, arr + len};
+}
+
+inline std::vector<uint8_t> macAddrToVec(const uint8_t* mac_addr) {
+	return byteArrToVec(mac_addr, ETH_ALEN);
+}
+
+// Raw pointer to the global structure maintained by the core.
+// Declared here to be accessible to onDeath()
+struct wpa_global *wpa_global_;
+
+void onDeath(void* cookie) {
+	wpa_printf(MSG_ERROR, "Client died. Terminating...");
+	wpa_supplicant_terminate_proc(wpa_global_);
+}
+
+}  // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+AidlManager *AidlManager::instance_ = NULL;
+
+AidlManager *AidlManager::getInstance()
+{
+	if (!instance_)
+		instance_ = new AidlManager();
+	return instance_;
+}
+
+void AidlManager::destroyInstance()
+{
+	if (instance_)
+		delete instance_;
+	instance_ = NULL;
+}
+
+int AidlManager::registerAidlService(struct wpa_global *global)
+{
+	// Create the main aidl service object and register it.
+	wpa_printf(MSG_INFO, "Starting AIDL supplicant");
+	supplicant_object_ = ndk::SharedRefBase::make<Supplicant>(global);
+	wpa_global_ = global;
+	std::string instance = std::string() + Supplicant::descriptor + "/default";
+	if (AServiceManager_addService(supplicant_object_->asBinder().get(),
+			instance.c_str()) != STATUS_OK)
+	{
+		return 1;
+	}
+
+	// Initialize the death notifier.
+	death_notifier_ = AIBinder_DeathRecipient_new(onDeath);
+	return 0;
+}
+
+/**
+ * Register an interface to aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::registerInterface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return 1;
+
+	if (isP2pIface(wpa_s)) {
+		if (addAidlObjectToMap<P2pIface>(
+			wpa_s->ifname,
+			ndk::SharedRefBase::make<P2pIface>(wpa_s->global, wpa_s->ifname),
+			p2p_iface_object_map_)) {
+			wpa_printf(
+				MSG_ERROR,
+				"Failed to register P2P interface with AIDL "
+				"control: %s",
+				wpa_s->ifname);
+			return 1;
+		}
+		p2p_iface_callbacks_map_[wpa_s->ifname] =
+			std::vector<std::shared_ptr<ISupplicantP2pIfaceCallback>>();
+	} else {
+		if (addAidlObjectToMap<StaIface>(
+			wpa_s->ifname,
+			ndk::SharedRefBase::make<StaIface>(wpa_s->global, wpa_s->ifname),
+			sta_iface_object_map_)) {
+			wpa_printf(
+				MSG_ERROR,
+				"Failed to register STA interface with AIDL "
+				"control: %s",
+				wpa_s->ifname);
+			return 1;
+		}
+		sta_iface_callbacks_map_[wpa_s->ifname] =
+			std::vector<std::shared_ptr<ISupplicantStaIfaceCallback>>();
+		// Turn on Android specific customizations for STA interfaces
+		// here!
+		//
+		// Turn on scan mac randomization only if driver supports.
+		if (wpa_s->mac_addr_rand_supported & MAC_ADDR_RAND_SCAN) {
+			if (wpas_mac_addr_rand_scan_set(
+				wpa_s, MAC_ADDR_RAND_SCAN, nullptr, nullptr)) {
+				wpa_printf(
+					MSG_ERROR,
+					"Failed to enable scan mac randomization");
+			}
+		}
+
+		// Enable randomized source MAC address for GAS/ANQP
+		// Set the lifetime to 0, guarantees a unique address for each GAS
+		// session
+		wpa_s->conf->gas_rand_mac_addr = 1;
+		wpa_s->conf->gas_rand_addr_lifetime = 0;
+	}
+
+	// Invoke the |onInterfaceCreated| method on all registered callbacks.
+	callWithEachSupplicantCallback(std::bind(
+		&ISupplicantCallback::onInterfaceCreated, std::placeholders::_1,
+		misc_utils::charBufToString(wpa_s->ifname)));
+	return 0;
+}
+
+/**
+ * Unregister an interface from aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::unregisterInterface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return 1;
+
+	// Check if this interface is present in P2P map first, else check in
+	// STA map.
+	// Note: We can't use isP2pIface() here because interface
+	// pointers (wpa_s->global->p2p_init_wpa_s == wpa_s) used by the helper
+	// function is cleared by the core before notifying the AIDL interface.
+	bool success =
+		!removeAidlObjectFromMap(wpa_s->ifname, p2p_iface_object_map_);
+	if (success) {  // assumed to be P2P
+		success = !removeAllIfaceCallbackAidlObjectsFromMap(
+			death_notifier_, wpa_s->ifname, p2p_iface_callbacks_map_);
+	} else {  // assumed to be STA
+		success = !removeAidlObjectFromMap(
+			wpa_s->ifname, sta_iface_object_map_);
+		if (success) {
+			success = !removeAllIfaceCallbackAidlObjectsFromMap(
+				death_notifier_, wpa_s->ifname, sta_iface_callbacks_map_);
+		}
+	}
+	if (!success) {
+		wpa_printf(
+			MSG_ERROR,
+			"Failed to unregister interface with AIDL "
+			"control: %s",
+			wpa_s->ifname);
+		return 1;
+	}
+
+	// Invoke the |onInterfaceRemoved| method on all registered callbacks.
+	callWithEachSupplicantCallback(std::bind(
+		&ISupplicantCallback::onInterfaceRemoved, std::placeholders::_1,
+		misc_utils::charBufToString(wpa_s->ifname)));
+	return 0;
+}
+
+/**
+ * Register a network to aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is added.
+ * @param ssid |wpa_ssid| struct corresponding to the network being added.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::registerNetwork(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !ssid)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+		getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+
+	if (isP2pIface(wpa_s)) {
+		if (addAidlObjectToMap<P2pNetwork>(
+			network_key,
+			ndk::SharedRefBase::make<P2pNetwork>(wpa_s->global, wpa_s->ifname, ssid->id),
+			p2p_network_object_map_)) {
+			wpa_printf(
+				MSG_ERROR,
+				"Failed to register P2P network with AIDL "
+				"control: %d",
+				ssid->id);
+			return 1;
+		}
+	} else {
+		if (addAidlObjectToMap<StaNetwork>(
+			network_key,
+			ndk::SharedRefBase::make<StaNetwork>(wpa_s->global, wpa_s->ifname, ssid->id),
+			sta_network_object_map_)) {
+			wpa_printf(
+				MSG_ERROR,
+				"Failed to register STA network with AIDL "
+				"control: %d",
+				ssid->id);
+			return 1;
+		}
+		sta_network_callbacks_map_[network_key] =
+			std::vector<std::shared_ptr<ISupplicantStaNetworkCallback>>();
+		// Invoke the |onNetworkAdded| method on all registered
+		// callbacks.
+		callWithEachStaIfaceCallback(
+			misc_utils::charBufToString(wpa_s->ifname),
+			std::bind(
+			&ISupplicantStaIfaceCallback::onNetworkAdded,
+			std::placeholders::_1, ssid->id));
+	}
+	return 0;
+}
+
+/**
+ * Unregister a network from aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is added.
+ * @param ssid |wpa_ssid| struct corresponding to the network being added.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::unregisterNetwork(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !ssid)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+		getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+
+	if (isP2pIface(wpa_s)) {
+		if (removeAidlObjectFromMap(
+			network_key, p2p_network_object_map_)) {
+			wpa_printf(
+				MSG_ERROR,
+				"Failed to unregister P2P network with AIDL "
+				"control: %d",
+				ssid->id);
+			return 1;
+		}
+	} else {
+		if (removeAidlObjectFromMap(
+			network_key, sta_network_object_map_)) {
+			wpa_printf(
+				MSG_ERROR,
+				"Failed to unregister STA network with AIDL "
+				"control: %d",
+				ssid->id);
+			return 1;
+		}
+		if (removeAllNetworkCallbackAidlObjectsFromMap(
+			death_notifier_, network_key, sta_network_callbacks_map_)) {
+			return 1;
+		}
+
+		// Invoke the |onNetworkRemoved| method on all registered
+		// callbacks.
+		callWithEachStaIfaceCallback(
+			misc_utils::charBufToString(wpa_s->ifname),
+			std::bind(
+			&ISupplicantStaIfaceCallback::onNetworkRemoved,
+			std::placeholders::_1, ssid->id));
+	}
+	return 0;
+}
+
+/**
+ * Notify all listeners about any state changes on a particular interface.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the state change event occured.
+ */
+int AidlManager::notifyStateChange(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return 1;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return 1;
+
+	// Invoke the |onStateChanged| method on all registered callbacks.
+	uint32_t aidl_network_id = UINT32_MAX;
+	std::vector<uint8_t> aidl_ssid;
+	if (wpa_s->current_ssid) {
+		aidl_network_id = wpa_s->current_ssid->id;
+		aidl_ssid.assign(
+			wpa_s->current_ssid->ssid,
+			wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+	}
+	std::vector<uint8_t> bssid;
+	// wpa_supplicant sets the |pending_bssid| field when it starts a
+	// connection. Only after association state does it update the |bssid|
+	// field. So, in the AIDL callback send the appropriate bssid.
+	if (wpa_s->wpa_state <= WPA_ASSOCIATED) {
+		bssid = macAddrToVec(wpa_s->pending_bssid);
+	} else {
+		bssid = macAddrToVec(wpa_s->bssid);
+	}
+	bool fils_hlp_sent =
+		(wpa_auth_alg_fils(wpa_s->auth_alg) &&
+		 !dl_list_empty(&wpa_s->fils_hlp_req) &&
+		 (wpa_s->wpa_state == WPA_COMPLETED)) ? true : false;
+
+	// Invoke the |onStateChanged| method on all registered callbacks.
+	std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+		func = std::bind(
+			&ISupplicantStaIfaceCallback::onStateChanged,
+			std::placeholders::_1,
+			static_cast<StaIfaceCallbackState>(
+				wpa_s->wpa_state),
+				bssid, aidl_network_id, aidl_ssid,
+				fils_hlp_sent);
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), func);
+	return 0;
+}
+
+/**
+ * Notify all listeners about a request on a particular network.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ * @param ssid |wpa_ssid| struct corresponding to the network.
+ * @param type type of request.
+ * @param param addition params associated with the request.
+ */
+int AidlManager::notifyNetworkRequest(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
+	const char *param)
+{
+	if (!wpa_s || !ssid)
+		return 1;
+
+	const std::string network_key =
+		getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+	if (sta_network_object_map_.find(network_key) ==
+		sta_network_object_map_.end())
+		return 1;
+
+	if (type == WPA_CTRL_REQ_EAP_IDENTITY) {
+		callWithEachStaNetworkCallback(
+			misc_utils::charBufToString(wpa_s->ifname),
+			ssid->id,
+			std::bind(
+			&ISupplicantStaNetworkCallback::
+				onNetworkEapIdentityRequest,
+			std::placeholders::_1));
+		return 0;
+	}
+	if (type == WPA_CTRL_REQ_SIM) {
+		std::vector<GsmRand> gsm_rands;
+		std::vector<uint8_t> umts_rand = std::vector<uint8_t>(16);
+		std::vector<uint8_t> umts_autn = std::vector<uint8_t>(16);
+		if (!parseGsmAuthNetworkRequest(param, &gsm_rands)) {
+			NetworkRequestEapSimGsmAuthParams aidl_params;
+			aidl_params.rands = gsm_rands;
+			callWithEachStaNetworkCallback(
+				misc_utils::charBufToString(wpa_s->ifname),
+				ssid->id,
+				std::bind(
+				&ISupplicantStaNetworkCallback::
+					onNetworkEapSimGsmAuthRequest,
+				std::placeholders::_1, aidl_params));
+			return 0;
+		}
+		if (!parseUmtsAuthNetworkRequest(
+			param, &umts_rand, &umts_autn)) {
+			NetworkRequestEapSimUmtsAuthParams aidl_params;
+			aidl_params.rand = umts_rand;
+			aidl_params.autn = umts_autn;
+			callWithEachStaNetworkCallback(
+				misc_utils::charBufToString(wpa_s->ifname),
+				ssid->id,
+				std::bind(
+				&ISupplicantStaNetworkCallback::
+					onNetworkEapSimUmtsAuthRequest,
+				std::placeholders::_1, aidl_params));
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/**
+ * Notify all listeners about the end of an ANQP query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param result Result of the operation ("SUCCESS" or "FAILURE").
+ * @param anqp |wpa_bss_anqp| ANQP data fetched.
+ */
+void AidlManager::notifyAnqpQueryDone(
+	struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+	const struct wpa_bss_anqp *anqp)
+{
+	if (!wpa_s || !bssid || !result || !anqp)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	AnqpData aidl_anqp_data;
+	Hs20AnqpData aidl_hs20_anqp_data;
+	if (std::string(result) == "SUCCESS") {
+		aidl_anqp_data.venueName =
+			misc_utils::convertWpaBufToVector(anqp->venue_name);
+		aidl_anqp_data.roamingConsortium =
+			misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
+		aidl_anqp_data.ipAddrTypeAvailability =
+			misc_utils::convertWpaBufToVector(
+			anqp->ip_addr_type_availability);
+		aidl_anqp_data.naiRealm =
+			misc_utils::convertWpaBufToVector(anqp->nai_realm);
+		aidl_anqp_data.anqp3gppCellularNetwork =
+			misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
+		aidl_anqp_data.domainName =
+			misc_utils::convertWpaBufToVector(anqp->domain_name);
+
+		struct wpa_bss_anqp_elem *elem;
+		dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+				 list) {
+			if (elem->infoid == ANQP_VENUE_URL && elem->protected_response) {
+				aidl_anqp_data.venueUrl =
+							misc_utils::convertWpaBufToVector(elem->payload);
+				break;
+			}
+		}
+
+		aidl_hs20_anqp_data.operatorFriendlyName =
+			misc_utils::convertWpaBufToVector(
+			anqp->hs20_operator_friendly_name);
+		aidl_hs20_anqp_data.wanMetrics =
+			misc_utils::convertWpaBufToVector(anqp->hs20_wan_metrics);
+		aidl_hs20_anqp_data.connectionCapability =
+			misc_utils::convertWpaBufToVector(
+			anqp->hs20_connection_capability);
+		aidl_hs20_anqp_data.osuProvidersList =
+			misc_utils::convertWpaBufToVector(
+			anqp->hs20_osu_providers_list);
+	}
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+				   &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+				   std::placeholders::_1, macAddrToVec(bssid), aidl_anqp_data,
+				   aidl_hs20_anqp_data));
+}
+
+/**
+ * Notify all listeners about the end of an HS20 icon query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param file_name Name of the icon file.
+ * @param image Raw bytes of the icon file.
+ * @param image_length Size of the the icon file.
+ */
+void AidlManager::notifyHs20IconQueryDone(
+	struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+	const u8 *image, u32 image_length)
+{
+	if (!wpa_s || !bssid || !file_name || !image)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onHs20IconQueryDone,
+		std::placeholders::_1, macAddrToVec(bssid), file_name,
+		std::vector<uint8_t>(image, image + image_length)));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 subscription
+ * remediation notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param url URL of the server.
+ * @param osu_method OSU method (OMA_DM or SOAP_XML_SPP).
+ */
+void AidlManager::notifyHs20RxSubscriptionRemediation(
+	struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+	if (!wpa_s || !url)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	OsuMethod aidl_osu_method;
+	if (osu_method & 0x1) {
+		aidl_osu_method = OsuMethod::OMA_DM;
+	} else if (osu_method & 0x2) {
+		aidl_osu_method = OsuMethod::SOAP_XML_SPP;
+	}
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onHs20SubscriptionRemediation,
+		std::placeholders::_1, macAddrToVec(wpa_s->bssid), aidl_osu_method, url));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 imminent death
+ * notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param code Death reason code sent from server.
+ * @param reauth_delay Reauthentication delay in seconds sent from server.
+ * @param url URL of the server containing the reason text.
+ */
+void AidlManager::notifyHs20RxDeauthImminentNotice(
+	struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onHs20DeauthImminentNotice,
+		std::placeholders::_1, macAddrToVec(wpa_s->bssid), code,
+		reauth_delay, misc_utils::charBufToString(url)));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 terms and conditions
+ * acceptance notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param url URL of the T&C server.
+ */
+void AidlManager::notifyHs20RxTermsAndConditionsAcceptance(
+	struct wpa_supplicant *wpa_s, const char *url)
+{
+	if (!wpa_s || !url)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname)
+			== sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+			&ISupplicantStaIfaceCallback
+			::onHs20TermsAndConditionsAcceptanceRequestedNotification,
+			std::placeholders::_1, macAddrToVec(wpa_s->bssid), url));
+}
+
+/**
+ * Notify all listeners about the reason code for disconnection from the
+ * currently connected network.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void AidlManager::notifyDisconnectReason(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	const u8 *bssid = wpa_s->bssid;
+	if (is_zero_ether_addr(bssid)) {
+		bssid = wpa_s->pending_bssid;
+	}
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onDisconnected,
+		std::placeholders::_1, macAddrToVec(bssid), wpa_s->disconnect_reason < 0,
+		static_cast<StaIfaceReasonCode>(
+			abs(wpa_s->disconnect_reason))));
+}
+
+/**
+ * Notify all listeners about association reject from the access point to which
+ * we are attempting to connect.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ * @param bssid bssid of AP that rejected the association.
+ * @param timed_out flag to indicate failure is due to timeout
+ * (auth, assoc, ...) rather than explicit rejection response from the AP.
+ * @param assoc_resp_ie Association response IE.
+ * @param assoc_resp_ie_len Association response IE length.
+ */
+void AidlManager::notifyAssocReject(struct wpa_supplicant *wpa_s,
+	const u8 *bssid, u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len)
+{
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+#ifdef CONFIG_MBO
+	struct wpa_bss *reject_bss;
+#endif /* CONFIG_MBO */
+	AssociationRejectionData aidl_assoc_reject_data{};
+
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+	if (wpa_s->current_ssid) {
+		aidl_assoc_reject_data.ssid = std::vector<uint8_t>(
+			wpa_s->current_ssid->ssid,
+			wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+	}
+	aidl_assoc_reject_data.bssid = macAddrToVec(bssid);
+	aidl_assoc_reject_data.statusCode = static_cast<StaIfaceStatusCode>(
+						wpa_s->assoc_status_code);
+	if (timed_out) {
+		aidl_assoc_reject_data.timedOut = true;
+	}
+#ifdef CONFIG_MBO
+	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
+		reject_bss = wpa_s->current_bss;
+	} else {
+		reject_bss = wpa_bss_get_bssid(wpa_s, bssid);
+	}
+	if (reject_bss && assoc_resp_ie && assoc_resp_ie_len > 0) {
+		if (wpa_s->assoc_status_code ==
+			WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS) {
+			const u8 *rssi_rej;
+			rssi_rej = mbo_get_attr_from_ies(
+					assoc_resp_ie,
+					assoc_resp_ie_len,
+					OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT);
+			if (rssi_rej && rssi_rej[1] == 2) {
+				wpa_printf(MSG_INFO,
+					   "OCE: RSSI-based association rejection from "
+					   MACSTR " Delta RSSI: %u, Retry Delay: %u bss rssi: %d",
+					   MAC2STR(reject_bss->bssid),
+					   rssi_rej[2], rssi_rej[3], reject_bss->level);
+				aidl_assoc_reject_data.isOceRssiBasedAssocRejectAttrPresent = true;
+				aidl_assoc_reject_data.oceRssiBasedAssocRejectData.deltaRssi
+						= rssi_rej[2];
+				aidl_assoc_reject_data.oceRssiBasedAssocRejectData.retryDelayS
+						= rssi_rej[3];
+			}
+		} else if (wpa_s->assoc_status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY
+			  || wpa_s->assoc_status_code == WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA) {
+			const u8 *assoc_disallowed;
+			assoc_disallowed = mbo_get_attr_from_ies(
+							assoc_resp_ie,
+							assoc_resp_ie_len,
+							MBO_ATTR_ID_ASSOC_DISALLOW);
+			if (assoc_disallowed && assoc_disallowed[1] == 1) {
+				wpa_printf(MSG_INFO,
+					"MBO: association disallowed indication from "
+					MACSTR " Reason: %d",
+					MAC2STR(reject_bss->bssid),
+					assoc_disallowed[2]);
+				aidl_assoc_reject_data.isMboAssocDisallowedReasonCodePresent = true;
+				aidl_assoc_reject_data.mboAssocDisallowedReason
+					= static_cast<MboAssocDisallowedReasonCode>(assoc_disallowed[2]);
+			}
+		}
+	}
+#endif /* CONFIG_MBO */
+
+	const std::function<
+			ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+			func = std::bind(
+			&ISupplicantStaIfaceCallback::onAssociationRejected,
+			std::placeholders::_1, aidl_assoc_reject_data);
+	callWithEachStaIfaceCallback(aidl_ifname, func);
+}
+
+void AidlManager::notifyAuthTimeout(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	const u8 *bssid = wpa_s->bssid;
+	if (is_zero_ether_addr(bssid)) {
+		bssid = wpa_s->pending_bssid;
+	}
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onAuthenticationTimeout,
+		std::placeholders::_1, macAddrToVec(bssid)));
+}
+
+void AidlManager::notifyBssidChanged(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	// wpa_supplicant does not explicitly give us the reason for bssid
+	// change, but we figure that out from what is set out of |wpa_s->bssid|
+	// & |wpa_s->pending_bssid|.
+	const u8 *bssid;
+	BssidChangeReason reason;
+	if (is_zero_ether_addr(wpa_s->bssid) &&
+		!is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->pending_bssid;
+		reason = BssidChangeReason::ASSOC_START;
+	} else if (
+		!is_zero_ether_addr(wpa_s->bssid) &&
+		is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->bssid;
+		reason = BssidChangeReason::ASSOC_COMPLETE;
+	} else if (
+		is_zero_ether_addr(wpa_s->bssid) &&
+		is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->pending_bssid;
+		reason = BssidChangeReason::DISASSOC;
+	} else {
+		wpa_printf(MSG_ERROR, "Unknown bssid change reason");
+		return;
+	}
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+				   &ISupplicantStaIfaceCallback::onBssidChanged,
+				   std::placeholders::_1, reason, macAddrToVec(bssid)));
+}
+
+void AidlManager::notifyWpsEventFail(
+	struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+	uint16_t error_indication)
+{
+	if (!wpa_s || !peer_macaddr)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onWpsEventFail,
+		std::placeholders::_1, macAddrToVec(peer_macaddr),
+		static_cast<WpsConfigError>(
+			config_error),
+		static_cast<WpsErrorIndication>(
+			error_indication)));
+}
+
+void AidlManager::notifyWpsEventSuccess(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+				   &ISupplicantStaIfaceCallback::onWpsEventSuccess,
+				   std::placeholders::_1));
+}
+
+void AidlManager::notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onWpsEventPbcOverlap,
+		std::placeholders::_1));
+}
+
+void AidlManager::notifyP2pDeviceFound(
+	struct wpa_supplicant *wpa_s, const u8 *addr,
+	const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+	u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+	u8 peer_wfd_r2_device_info_len)
+{
+	if (!wpa_s || !addr || !info)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	std::vector<uint8_t> aidl_peer_wfd_device_info(kWfdDeviceInfoLen);
+	if (peer_wfd_device_info) {
+		if (peer_wfd_device_info_len != kWfdDeviceInfoLen) {
+			wpa_printf(
+				MSG_ERROR, "Unexpected WFD device info len: %d",
+				peer_wfd_device_info_len);
+		} else {
+			os_memcpy(
+				aidl_peer_wfd_device_info.data(),
+				peer_wfd_device_info, kWfdDeviceInfoLen);
+		}
+	}
+
+	std::vector<uint8_t> aidl_peer_wfd_r2_device_info;
+	if (peer_wfd_r2_device_info) {
+		if (peer_wfd_r2_device_info_len != kWfdR2DeviceInfoLen) {
+			wpa_printf(
+				MSG_ERROR, "Unexpected WFD R2 device info len: %d",
+				peer_wfd_r2_device_info_len);
+			return;
+		} else {
+			std::copy(peer_wfd_r2_device_info,
+			    peer_wfd_r2_device_info + peer_wfd_r2_device_info_len,
+			    std::back_inserter(aidl_peer_wfd_r2_device_info));
+		}
+	}
+
+	std::vector<uint8_t> aidl_vendor_elems;
+	if (NULL != info->vendor_elems && wpabuf_len(info->vendor_elems) > 0) {
+		aidl_vendor_elems.reserve(wpabuf_len(info->vendor_elems));
+		std::copy(wpabuf_head_u8(info->vendor_elems),
+			wpabuf_head_u8(info->vendor_elems)
+				+ wpabuf_len(info->vendor_elems),
+			std::back_inserter(aidl_vendor_elems));
+	}
+
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
+		func = std::bind(
+		&ISupplicantP2pIfaceCallback::onDeviceFoundWithVendorElements,
+		std::placeholders::_1, macAddrToVec(addr), macAddrToVec(info->p2p_device_addr),
+		byteArrToVec(info->pri_dev_type, 8), misc_utils::charBufToString(info->device_name),
+		static_cast<WpsConfigMethods>(info->config_methods),
+		info->dev_capab, static_cast<P2pGroupCapabilityMask>(info->group_capab), aidl_peer_wfd_device_info,
+		aidl_peer_wfd_r2_device_info, aidl_vendor_elems);
+	callWithEachP2pIfaceCallback(wpa_s->ifname, func);
+}
+
+void AidlManager::notifyP2pDeviceLost(
+	struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{
+	if (!wpa_s || !p2p_device_addr)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+				   &ISupplicantP2pIfaceCallback::onDeviceLost,
+				   std::placeholders::_1, macAddrToVec(p2p_device_addr)));
+}
+
+void AidlManager::notifyP2pFindStopped(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+				   &ISupplicantP2pIfaceCallback::onFindStopped,
+				   std::placeholders::_1));
+}
+
+void AidlManager::notifyP2pGoNegReq(
+	struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+	u8 /* go_intent */)
+{
+	if (!wpa_s || !src_addr)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onGoNegotiationRequest,
+		std::placeholders::_1, macAddrToVec(src_addr),
+		static_cast<WpsDevPasswordId>(
+			dev_passwd_id)));
+}
+
+void AidlManager::notifyP2pGoNegCompleted(
+	struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{
+	if (!wpa_s || !res)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onGoNegotiationCompleted,
+		std::placeholders::_1,
+		static_cast<P2pStatusCode>(
+			res->status)));
+}
+
+void AidlManager::notifyP2pGroupFormationFailure(
+	struct wpa_supplicant *wpa_s, const char *reason)
+{
+	if (!wpa_s || !reason)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onGroupFormationFailure,
+		std::placeholders::_1, reason));
+}
+
+void AidlManager::notifyP2pGroupStarted(
+	struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+	int persistent, int client)
+{
+	if (!wpa_group_s || !wpa_group_s->parent || !ssid)
+		return;
+
+	// For group notifications, need to use the parent iface for callbacks.
+	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
+		return;
+
+	uint32_t aidl_freq = wpa_group_s->current_bss
+				 ? wpa_group_s->current_bss->freq
+				 : wpa_group_s->assoc_freq;
+	std::vector<uint8_t> aidl_psk(32);
+	if (ssid->psk_set) {
+		aidl_psk.assign(ssid->psk, ssid->psk + 32);
+	}
+	bool aidl_is_go = (client == 0 ? true : false);
+	bool aidl_is_persistent = (persistent == 1 ? true : false);
+
+	// notify the group device again to ensure the framework knowing this device.
+	struct p2p_data *p2p = wpa_s->global->p2p;
+	struct p2p_device *dev = p2p_get_device(p2p, wpa_group_s->go_dev_addr);
+	if (NULL != dev) {
+		wpa_printf(MSG_DEBUG, "P2P: Update GO device on group started.");
+		p2p->cfg->dev_found(p2p->cfg->cb_ctx, wpa_group_s->go_dev_addr,
+				&dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
+		dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
+	}
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onGroupStarted,
+		std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname),
+		aidl_is_go, byteArrToVec(ssid->ssid, ssid->ssid_len),
+		aidl_freq, aidl_psk, misc_utils::charBufToString(ssid->passphrase),
+		macAddrToVec(wpa_group_s->go_dev_addr), aidl_is_persistent));
+}
+
+void AidlManager::notifyP2pGroupRemoved(
+	struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+	const char *role)
+{
+	if (!wpa_group_s || !wpa_group_s->parent || !ssid || !role)
+		return;
+
+	// For group notifications, need to use the parent iface for callbacks.
+	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
+		return;
+
+	bool aidl_is_go = (std::string(role) == "GO");
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onGroupRemoved,
+		std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname), aidl_is_go));
+}
+
+void AidlManager::notifyP2pInvitationReceived(
+	struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+	const u8 *bssid, int id, int op_freq)
+{
+	if (!wpa_s || !sa || !go_dev_addr || !bssid)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	int aidl_network_id;
+	if (id < 0) {
+		aidl_network_id = UINT32_MAX;
+	}
+	aidl_network_id = id;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onInvitationReceived,
+		std::placeholders::_1, macAddrToVec(sa), macAddrToVec(go_dev_addr),
+		macAddrToVec(bssid), aidl_network_id, op_freq));
+}
+
+void AidlManager::notifyP2pInvitationResult(
+	struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{
+	if (!wpa_s)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onInvitationResult,
+		std::placeholders::_1, bssid ? macAddrToVec(bssid) : kZeroBssid,
+		static_cast<P2pStatusCode>(
+			status)));
+}
+
+void AidlManager::notifyP2pProvisionDiscovery(
+	struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+	enum p2p_prov_disc_status status, u16 config_methods,
+	unsigned int generated_pin)
+{
+	if (!wpa_s || !dev_addr)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	std::string aidl_generated_pin;
+	if (generated_pin > 0) {
+		aidl_generated_pin =
+			misc_utils::convertWpsPinToString(generated_pin);
+	}
+	bool aidl_is_request = (request == 1 ? true : false);
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onProvisionDiscoveryCompleted,
+		std::placeholders::_1, macAddrToVec(dev_addr), aidl_is_request,
+		static_cast<P2pProvDiscStatusCode>(status),
+		static_cast<WpsConfigMethods>(config_methods), aidl_generated_pin));
+}
+
+void AidlManager::notifyP2pSdResponse(
+	struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+	const u8 *tlvs, size_t tlvs_len)
+{
+	if (!wpa_s || !sa || !tlvs)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+		p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onServiceDiscoveryResponse,
+		std::placeholders::_1, macAddrToVec(sa), update_indic,
+		byteArrToVec(tlvs, tlvs_len)));
+}
+
+void AidlManager::notifyApStaAuthorized(
+	struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_group_s || !wpa_group_s->parent || !sta)
+		return;
+	wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
+		return;
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onStaAuthorized,
+		std::placeholders::_1, macAddrToVec(sta),
+		p2p_dev_addr ? macAddrToVec(p2p_dev_addr) : kZeroBssid));
+}
+
+void AidlManager::notifyApStaDeauthorized(
+	struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_group_s || !wpa_group_s->parent || !sta)
+		return;
+	wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
+		return;
+
+	callWithEachP2pIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantP2pIfaceCallback::onStaDeauthorized,
+		std::placeholders::_1, macAddrToVec(sta),
+		p2p_dev_addr ? macAddrToVec(p2p_dev_addr) : kZeroBssid));
+}
+
+void AidlManager::notifyExtRadioWorkStart(
+	struct wpa_supplicant *wpa_s, uint32_t id)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onExtRadioWorkStart,
+		std::placeholders::_1, id));
+}
+
+void AidlManager::notifyExtRadioWorkTimeout(
+	struct wpa_supplicant *wpa_s, uint32_t id)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+		sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onExtRadioWorkTimeout,
+		std::placeholders::_1, id));
+}
+
+void AidlManager::notifyEapError(struct wpa_supplicant *wpa_s, int error_code)
+{
+	if (!wpa_s)
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname),
+		std::bind(
+		&ISupplicantStaIfaceCallback::onEapFailure,
+		std::placeholders::_1,
+		macAddrToVec(wpa_s->bssid), error_code));
+}
+
+/**
+ * Notify listener about a new DPP configuration received success event
+ *
+ * @param ifname Interface name
+ * @param config Configuration object
+ */
+void AidlManager::notifyDppConfigReceived(struct wpa_supplicant *wpa_s,
+		struct wpa_ssid *config)
+{
+	DppAkm securityAkm;
+	DppConnectionKeys aidl_keys{};
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+	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 if (config->key_mgmt & WPA_KEY_MGMT_DPP) {
+			securityAkm = DppAkm::DPP;
+	} else {
+		/* Unsupported AKM */
+		wpa_printf(MSG_ERROR, "DPP: Error: Unsupported AKM 0x%X",
+				config->key_mgmt);
+		notifyDppFailure(wpa_s, DppFailureCode::NOT_SUPPORTED);
+		return;
+	}
+
+	std::string passphrase = misc_utils::charBufToString(config->passphrase);
+	std::vector<uint8_t> aidl_ssid(
+		config->ssid,
+		config->ssid + config->ssid_len);
+
+	if (securityAkm == DppAkm::DPP) {
+		std::string connector_str = misc_utils::charBufToString(config->dpp_connector);
+		aidl_keys.connector = std::vector<uint8_t>(connector_str.begin(),
+			connector_str.end());
+		aidl_keys.cSign = byteArrToVec(config->dpp_csign, config->dpp_csign_len);
+		aidl_keys.netAccessKey = byteArrToVec(config->dpp_netaccesskey,
+			config->dpp_netaccesskey_len);
+	}
+
+	/* At this point, the network is already registered, notify about new
+	 * received configuration
+	 */
+	callWithEachStaIfaceCallback(aidl_ifname,
+			std::bind(
+					&ISupplicantStaIfaceCallback::onDppSuccessConfigReceived,
+					std::placeholders::_1, aidl_ssid, passphrase,
+					byteArrToVec(config->psk, 32), securityAkm,
+					aidl_keys));
+}
+
+/**
+ * Notify listener about a DPP configuration sent success event
+ *
+ * @param ifname Interface name
+ */
+void AidlManager::notifyDppConfigSent(struct wpa_supplicant *wpa_s)
+{
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+	callWithEachStaIfaceCallback(aidl_ifname,
+			std::bind(&ISupplicantStaIfaceCallback::onDppSuccessConfigSent,
+					std::placeholders::_1));
+}
+
+/**
+ * Notify listener about a DPP failure event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
+		android::hardware::wifi::supplicant::DppFailureCode code) {
+	notifyDppFailure(wpa_s, code, NULL, NULL, NULL, 0);
+}
+
+/**
+ * Notify listener about a DPP failure event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
+		DppFailureCode code, const char *ssid, const char *channel_list,
+		unsigned short band_list[], int size) {
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+	std::vector<char16_t> band_list_vec(band_list, band_list + size);
+
+	callWithEachStaIfaceCallback(aidl_ifname,
+			std::bind(&ISupplicantStaIfaceCallback::onDppFailure,
+					std::placeholders::_1, code, misc_utils::charBufToString(ssid),
+					misc_utils::charBufToString(channel_list), band_list_vec));
+}
+
+/**
+ * Notify listener about a DPP progress event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppProgress(
+		struct wpa_supplicant *wpa_s, DppProgressCode code) {
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+	callWithEachStaIfaceCallback(aidl_ifname,
+			std::bind(&ISupplicantStaIfaceCallback::onDppProgress,
+					std::placeholders::_1, code));
+}
+
+/**
+ * Notify listener about a DPP success event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppSuccess(struct wpa_supplicant *wpa_s, DppEventType code)
+{
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+	callWithEachStaIfaceCallback(aidl_ifname,
+			std::bind(&ISupplicantStaIfaceCallback::onDppSuccess,
+					std::placeholders::_1, code));
+}
+
+/**
+ * Notify listener about a PMK cache added event
+ *
+ * @param ifname Interface name
+ * @param entry PMK cache entry
+ */
+void AidlManager::notifyPmkCacheAdded(
+	struct wpa_supplicant *wpa_s, struct rsn_pmksa_cache_entry *pmksa_entry)
+{
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+	// Serialize PmkCacheEntry into blob.
+	std::stringstream ss(
+		std::stringstream::in | std::stringstream::out | std::stringstream::binary);
+	misc_utils::serializePmkCacheEntry(ss, pmksa_entry);
+	std::vector<uint8_t> serializedEntry(
+		std::istreambuf_iterator<char>(ss), {});
+
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+		func = std::bind(
+		&ISupplicantStaIfaceCallback::onPmkCacheAdded,
+		std::placeholders::_1, pmksa_entry->expiration, serializedEntry);
+	callWithEachStaIfaceCallback(aidl_ifname, func);
+}
+
+#ifdef CONFIG_WNM
+BssTmStatusCode convertSupplicantBssTmStatusToAidl(
+	enum bss_trans_mgmt_status_code bss_tm_status)
+{
+	switch (bss_tm_status) {
+		case WNM_BSS_TM_ACCEPT:
+			return BssTmStatusCode::ACCEPT;
+		case WNM_BSS_TM_REJECT_UNSPECIFIED:
+			return BssTmStatusCode::REJECT_UNSPECIFIED;
+		case WNM_BSS_TM_REJECT_INSUFFICIENT_BEACON:
+			return BssTmStatusCode::REJECT_INSUFFICIENT_BEACON;
+		case WNM_BSS_TM_REJECT_INSUFFICIENT_CAPABITY:
+			return BssTmStatusCode::REJECT_INSUFFICIENT_CAPABITY;
+		case WNM_BSS_TM_REJECT_UNDESIRED:
+			return BssTmStatusCode::REJECT_BSS_TERMINATION_UNDESIRED;
+		case WNM_BSS_TM_REJECT_DELAY_REQUEST:
+			return BssTmStatusCode::REJECT_BSS_TERMINATION_DELAY_REQUEST;
+		case WNM_BSS_TM_REJECT_STA_CANDIDATE_LIST_PROVIDED:
+			return BssTmStatusCode::REJECT_STA_CANDIDATE_LIST_PROVIDED;
+		case WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES:
+			return BssTmStatusCode::REJECT_NO_SUITABLE_CANDIDATES;
+		case WNM_BSS_TM_REJECT_LEAVING_ESS:
+			return BssTmStatusCode::REJECT_LEAVING_ESS;
+		default:
+			return BssTmStatusCode::REJECT_UNSPECIFIED;
+	}
+}
+
+BssTmDataFlagsMask setBssTmDataFlagsMask(struct wpa_supplicant *wpa_s)
+{
+	uint32_t flags = 0;
+
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_BSS_TERMINATION_INCLUDED);
+	}
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_ESS_DISASSOCIATION_IMMINENT);
+	}
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_DISASSOCIATION_IMMINENT);
+	}
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ABRIDGED) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_ABRIDGED);
+	}
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED);
+	}
+#ifdef CONFIG_MBO
+	if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_ASSOC_RETRY_DELAY_INCLUDED);
+	}
+	if (wpa_s->wnm_mbo_trans_reason_present) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_TRANSITION_REASON_CODE_INCLUDED);
+	}
+	if (wpa_s->wnm_mbo_cell_pref_present) {
+		flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED);
+	}
+#endif
+	return static_cast<BssTmDataFlagsMask>(flags);
+}
+
+uint32_t getBssTmDataAssocRetryDelayMs(struct wpa_supplicant *wpa_s)
+{
+	uint32_t beacon_int;
+	uint32_t duration_ms = 0;
+
+	if (wpa_s->current_bss)
+		beacon_int = wpa_s->current_bss->beacon_int;
+	else
+		beacon_int = 100; /* best guess */
+
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+		// number of tbtts to milliseconds
+		duration_ms = wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125;
+	}
+	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
+		//wnm_bss_termination_duration contains 12 bytes of BSS
+		//termination duration subelement. Format of IE is
+		// Sub eid | Length | BSS termination TSF | Duration
+		//	1	 1		 8		2
+		// Duration indicates number of minutes for which BSS is not
+		// present.
+		duration_ms = WPA_GET_LE16(wpa_s->wnm_bss_termination_duration + 10);
+		// minutes to milliseconds
+		duration_ms = duration_ms * 60 * 1000;
+	}
+#ifdef CONFIG_MBO
+	if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
+		// number of seconds to milliseconds
+		duration_ms = wpa_s->wnm_mbo_assoc_retry_delay_sec * 1000;
+	}
+#endif
+
+	return duration_ms;
+}
+#endif
+
+/**
+ * Notify listener about the status of BSS transition management
+ * request frame handling.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void AidlManager::notifyBssTmStatus(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_WNM
+	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+	BssTmData aidl_bsstm_data{};
+
+	aidl_bsstm_data.status = convertSupplicantBssTmStatusToAidl(wpa_s->bss_tm_status);
+	aidl_bsstm_data.flags = setBssTmDataFlagsMask(wpa_s);
+	aidl_bsstm_data.assocRetryDelayMs = getBssTmDataAssocRetryDelayMs(wpa_s);
+#ifdef CONFIG_MBO
+	if (wpa_s->wnm_mbo_cell_pref_present) {
+		aidl_bsstm_data.mboCellPreference = static_cast
+			<MboCellularDataConnectionPrefValue>
+			(wpa_s->wnm_mbo_cell_preference);
+	}
+	if (wpa_s->wnm_mbo_trans_reason_present) {
+		aidl_bsstm_data.mboTransitionReason =
+			static_cast<MboTransitionReasonCode>
+			(wpa_s->wnm_mbo_transition_reason);
+	}
+#endif
+
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+		func = std::bind(
+		&ISupplicantStaIfaceCallback::onBssTmHandlingDone,
+		std::placeholders::_1, aidl_bsstm_data);
+	callWithEachStaIfaceCallback(aidl_ifname, func);
+#endif
+}
+
+TransitionDisableIndication setTransitionDisableFlagsMask(u8 bitmap)
+{
+	uint32_t flags = 0;
+
+	if (bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) {
+		flags |= static_cast<uint32_t>(TransitionDisableIndication::
+			USE_WPA3_PERSONAL);
+		bitmap &= ~TRANSITION_DISABLE_WPA3_PERSONAL;
+	}
+	if (bitmap & TRANSITION_DISABLE_SAE_PK) {
+		flags |= static_cast<uint32_t>(TransitionDisableIndication::
+			USE_SAE_PK);
+		bitmap &= ~TRANSITION_DISABLE_SAE_PK;
+	}
+	if (bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) {
+		flags |= static_cast<uint32_t>(TransitionDisableIndication::
+			USE_WPA3_ENTERPRISE);
+		bitmap &= ~TRANSITION_DISABLE_WPA3_ENTERPRISE;
+	}
+	if (bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) {
+		flags |= static_cast<uint32_t>(TransitionDisableIndication::
+			USE_ENHANCED_OPEN);
+		bitmap &= ~TRANSITION_DISABLE_ENHANCED_OPEN;
+	}
+
+	if (bitmap != 0) {
+		wpa_printf(MSG_WARNING, "Unhandled transition disable bit: 0x%x", bitmap);
+	}
+
+	return static_cast<TransitionDisableIndication>(flags);
+}
+
+void AidlManager::notifyTransitionDisable(struct wpa_supplicant *wpa_s,
+	struct wpa_ssid *ssid, u8 bitmap)
+{
+	TransitionDisableIndication flag = setTransitionDisableFlagsMask(bitmap);
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)>
+		func = std::bind(
+		&ISupplicantStaNetworkCallback::onTransitionDisable,
+		std::placeholders::_1, flag);
+
+	callWithEachStaNetworkCallback(
+		misc_utils::charBufToString(wpa_s->ifname), ssid->id, func);
+}
+
+void AidlManager::notifyNetworkNotFound(struct wpa_supplicant *wpa_s)
+{
+	std::vector<uint8_t> aidl_ssid;
+
+	if (!wpa_s->current_ssid) {
+		wpa_printf(MSG_ERROR, "Current network NULL. Drop WPA_EVENT_NETWORK_NOT_FOUND!");
+		return;
+	}
+
+	aidl_ssid.assign(
+			wpa_s->current_ssid->ssid,
+			wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+		func = std::bind(
+		&ISupplicantStaIfaceCallback::onNetworkNotFound,
+		std::placeholders::_1, aidl_ssid);
+	callWithEachStaIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
+}
+
+void AidlManager::notifyFrequencyChanged(struct wpa_supplicant *wpa_group_s, int frequency)
+{
+	if (!wpa_group_s || !wpa_group_s->parent)
+		return;
+
+	// For group notifications, need to use the parent iface for callbacks.
+	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s) {
+		wpa_printf(MSG_INFO, "Drop frequency changed event");
+		return;
+	}
+
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
+		func = std::bind(&ISupplicantP2pIfaceCallback::onGroupFrequencyChanged,
+		std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname),
+		frequency);
+	callWithEachP2pIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
+}
+
+void AidlManager::notifyCertification(struct wpa_supplicant *wpa_s,
+		int depth, const char *subject,
+		const char *altsubject[],
+		int num_altsubject,
+		const char *cert_hash,
+		const struct wpabuf *cert)
+{
+	if (!wpa_s->current_ssid) {
+		wpa_printf(MSG_ERROR, "Current network NULL. Drop Certification event!");
+		return;
+	}
+	struct wpa_ssid *current_ssid = wpa_s->current_ssid;
+	if (NULL == subject || NULL == cert_hash || NULL == cert) {
+		wpa_printf(MSG_ERROR,
+				"Incomplete certificate information. Drop Certification event!");
+		return;
+	}
+	if (!wpa_key_mgmt_wpa_ieee8021x(current_ssid->key_mgmt)) {
+		wpa_printf(MSG_ERROR, "Not 802.1x configuration, Drop Certification event!");
+		return;
+	}
+	if (current_ssid->eap.cert.ca_path || current_ssid->eap.cert.ca_cert) {
+		wpa_printf(MSG_DEBUG, "Already has CA certificate. Drop Certification event!");
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG, "notifyCertification: depth=%d subject=%s hash=%s cert-size=%zu",
+			depth, subject, cert_hash, cert->used);
+	std::vector<uint8_t> subjectBlob(subject, subject + strlen(subject));
+	std::vector<uint8_t> certHashBlob(cert_hash, cert_hash + strlen(cert_hash));
+	std::vector<uint8_t> certBlob(cert->buf, cert->buf + cert->used);
+
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)>
+		func = std::bind(
+		&ISupplicantStaNetworkCallback::onServerCertificateAvailable,
+		std::placeholders::_1,
+		depth,
+		subjectBlob,
+		certHashBlob,
+		certBlob);
+
+	callWithEachStaNetworkCallback(
+		misc_utils::charBufToString(wpa_s->ifname), current_ssid->id, func);
+}
+
+void AidlManager::notifyAuxiliaryEvent(struct wpa_supplicant *wpa_s,
+	AuxiliarySupplicantEventCode event_code, const char *reason_string)
+{
+	if (!wpa_s)
+		return;
+
+	const std::function<
+		ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+		func = std::bind(
+		&ISupplicantStaIfaceCallback::onAuxiliarySupplicantEvent,
+		std::placeholders::_1, event_code, macAddrToVec(wpa_s->bssid),
+		misc_utils::charBufToString(reason_string));
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), func);
+}
+
+/**
+ * Retrieve the |ISupplicantP2pIface| aidl object reference using the provided
+ * ifname.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param iface_object Aidl reference corresponding to the iface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getP2pIfaceAidlObjectByIfname(
+	const std::string &ifname, std::shared_ptr<ISupplicantP2pIface> *iface_object)
+{
+	if (ifname.empty() || !iface_object)
+		return 1;
+
+	auto iface_object_iter = p2p_iface_object_map_.find(ifname);
+	if (iface_object_iter == p2p_iface_object_map_.end())
+		return 1;
+
+	*iface_object = iface_object_iter->second;
+	return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantStaIface| aidl object reference using the provided
+ * ifname.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param iface_object Aidl reference corresponding to the iface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getStaIfaceAidlObjectByIfname(
+	const std::string &ifname, std::shared_ptr<ISupplicantStaIface> *iface_object)
+{
+	if (ifname.empty() || !iface_object)
+		return 1;
+
+	auto iface_object_iter = sta_iface_object_map_.find(ifname);
+	if (iface_object_iter == sta_iface_object_map_.end())
+		return 1;
+
+	*iface_object = iface_object_iter->second;
+	return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantP2pNetwork| aidl object reference using the provided
+ * ifname and network_id.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param network_object Aidl reference corresponding to the network.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getP2pNetworkAidlObjectByIfnameAndNetworkId(
+	const std::string &ifname, int network_id,
+	std::shared_ptr<ISupplicantP2pNetwork> *network_object)
+{
+	if (ifname.empty() || network_id < 0 || !network_object)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+		getNetworkObjectMapKey(ifname, network_id);
+
+	auto network_object_iter = p2p_network_object_map_.find(network_key);
+	if (network_object_iter == p2p_network_object_map_.end())
+		return 1;
+
+	*network_object = network_object_iter->second;
+	return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantStaNetwork| aidl object reference using the provided
+ * ifname and network_id.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param network_object Aidl reference corresponding to the network.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getStaNetworkAidlObjectByIfnameAndNetworkId(
+	const std::string &ifname, int network_id,
+	std::shared_ptr<ISupplicantStaNetwork> *network_object)
+{
+	if (ifname.empty() || network_id < 0 || !network_object)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+		getNetworkObjectMapKey(ifname, network_id);
+
+	auto network_object_iter = sta_network_object_map_.find(network_key);
+	if (network_object_iter == sta_network_object_map_.end())
+		return 1;
+
+	*network_object = network_object_iter->second;
+	return 0;
+}
+
+/**
+ * Add a new |ISupplicantCallback| aidl object reference to our
+ * global callback list.
+ *
+ * @param callback Aidl reference of the |ISupplicantCallback| object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addSupplicantCallbackAidlObject(
+	const std::shared_ptr<ISupplicantCallback> &callback)
+{
+	return registerForDeathAndAddCallbackAidlObjectToList<
+		ISupplicantCallback>(
+		death_notifier_, callback, supplicant_callbacks_);
+}
+
+/**
+ * Add a new iface callback aidl object reference to our
+ * interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addP2pIfaceCallbackAidlObject(
+	const std::string &ifname,
+	const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback)
+{
+	return addIfaceCallbackAidlObjectToMap(
+		death_notifier_, ifname, callback, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Add a new iface callback aidl object reference to our
+ * interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addStaIfaceCallbackAidlObject(
+	const std::string &ifname,
+	const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
+{
+	return addIfaceCallbackAidlObjectToMap(
+		death_notifier_, ifname, callback, sta_iface_callbacks_map_);
+}
+
+/**
+ * Add a new network callback aidl object reference to our network callback
+ * list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param callback Aidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addStaNetworkCallbackAidlObject(
+	const std::string &ifname, int network_id,
+	const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
+{
+	return addNetworkCallbackAidlObjectToMap(
+		death_notifier_, ifname, network_id, callback,
+		sta_network_callbacks_map_);
+}
+
+/**
+ * Finds the correct |wpa_supplicant| object for P2P notifications
+ *
+ * @param wpa_s the |wpa_supplicant| that triggered the P2P event.
+ * @return appropriate |wpa_supplicant| object or NULL if not found.
+ */
+struct wpa_supplicant *AidlManager::getTargetP2pIfaceForGroup(
+		struct wpa_supplicant *wpa_group_s)
+{
+	if (!wpa_group_s || !wpa_group_s->parent)
+		return NULL;
+
+	struct wpa_supplicant *target_wpa_s = wpa_group_s->parent;
+
+	// check wpa_supplicant object is a p2p device interface
+	if ((wpa_group_s == wpa_group_s->p2pdev) && wpa_group_s->p2p_mgmt) {
+		if (p2p_iface_object_map_.find(wpa_group_s->ifname) !=
+			p2p_iface_object_map_.end())
+			return wpa_group_s;
+	}
+
+	if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
+		p2p_iface_object_map_.end())
+		return target_wpa_s;
+
+	// try P2P device if available
+	if (!target_wpa_s->p2pdev || !target_wpa_s->p2pdev->p2p_mgmt)
+		return NULL;
+
+	target_wpa_s = target_wpa_s->p2pdev;
+	if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
+		p2p_iface_object_map_.end())
+		return target_wpa_s;
+
+	return NULL;
+}
+
+/**
+ * Removes the provided |ISupplicantCallback| aidl object reference
+ * from our global callback list.
+ *
+ * @param callback Aidl reference of the |ISupplicantCallback| object.
+ */
+void AidlManager::removeSupplicantCallbackAidlObject(
+	const std::shared_ptr<ISupplicantCallback> &callback)
+{
+	supplicant_callbacks_.erase(
+		std::remove(
+		supplicant_callbacks_.begin(), supplicant_callbacks_.end(),
+		callback),
+		supplicant_callbacks_.end());
+}
+
+/**
+ * Removes the provided iface callback aidl object reference from
+ * our interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ */
+void AidlManager::removeP2pIfaceCallbackAidlObject(
+	const std::string &ifname,
+	const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback)
+{
+	return removeIfaceCallbackAidlObjectFromMap(
+		ifname, callback, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Removes the provided iface callback aidl object reference from
+ * our interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ */
+void AidlManager::removeStaIfaceCallbackAidlObject(
+	const std::string &ifname,
+	const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
+{
+	return removeIfaceCallbackAidlObjectFromMap(
+		ifname, callback, sta_iface_callbacks_map_);
+}
+
+/**
+ * Removes the provided network callback aidl object reference from
+ * our network callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param callback Aidl reference of the callback object.
+ */
+void AidlManager::removeStaNetworkCallbackAidlObject(
+	const std::string &ifname, int network_id,
+	const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
+{
+	return removeNetworkCallbackAidlObjectFromMap(
+		ifname, network_id, callback, sta_network_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered |ISupplicantCallback| callback aidl objects.
+ *
+ * @param method Pointer to the required aidl method from
+ * |ISupplicantCallback|.
+ */
+void AidlManager::callWithEachSupplicantCallback(
+	const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantCallback>)> &method)
+{
+	for (const auto &callback : supplicant_callbacks_) {
+		if (!method(callback).isOk()) {
+			wpa_printf(MSG_ERROR, "Failed to invoke AIDL callback");
+		}
+	}
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered iface callback aidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required aidl method from
+ * |ISupplicantIfaceCallback|.
+ */
+void AidlManager::callWithEachP2pIfaceCallback(
+	const std::string &ifname,
+	const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
+	&method)
+{
+	callWithEachIfaceCallback(ifname, method, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered interface callback aidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required aidl method from
+ * |ISupplicantIfaceCallback|.
+ */
+void AidlManager::callWithEachStaIfaceCallback(
+	const std::string &ifname,
+	const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+	&method)
+{
+	callWithEachIfaceCallback(ifname, method, sta_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered network callback aidl objects for the specified
+ * |ifname| & |network_id|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param method Pointer to the required aidl method from 
+ * |ISupplicantStaNetworkCallback|.
+ */
+void AidlManager::callWithEachStaNetworkCallback(
+	const std::string &ifname, int network_id,
+	const std::function<
+	ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)> &method)
+{
+	callWithEachNetworkCallback(
+		ifname, network_id, method, sta_network_callbacks_map_);
+}
+
+void AidlManager::notifyQosPolicyReset(
+	struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onQosPolicyReset,
+			std::placeholders::_1));
+}
+
+void AidlManager::notifyQosPolicyRequest(struct wpa_supplicant *wpa_s,
+	struct dscp_policy_data *policies, int num_policies)
+{
+	if (!wpa_s || !policies)
+		return;
+
+	std::vector<QosPolicyData> qosPolicyData;
+	uint32_t mask = 0;
+
+	for (int num = 0; num < num_policies; num++) {
+		QosPolicyData policy;
+		QosPolicyClassifierParams classifier_params;
+		QosPolicyClassifierParamsMask classifier_param_mask;
+		bool ip_ver4 = false;
+
+		if (policies[num].type4_param.ip_version == 4) {
+			classifier_params.ipVersion = IpVersion::VERSION_4;
+			ip_ver4 = true;
+		} else {
+			classifier_params.ipVersion = IpVersion::VERSION_6;
+			ip_ver4 = false;
+		}
+
+		// classifier_mask parameters are defined in IEEE Std 802.11-2020, Table 9-170
+		if (policies[num].type4_param.classifier_mask & BIT(1)) {
+			mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::SRC_IP);
+			if (ip_ver4) {
+				classifier_params.srcIp =
+					byteArrToVec((const uint8_t *)
+						&policies[num].type4_param.ip_params.v4.src_ip, 4);
+			} else {
+				classifier_params.srcIp =
+					byteArrToVec((const uint8_t *)
+						&policies[num].type4_param.ip_params.v6.src_ip, 16);
+			}
+		}
+		if (policies[num].type4_param.classifier_mask & BIT(2)) {
+			mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::DST_IP);
+			if (ip_ver4){
+				classifier_params.dstIp =
+					byteArrToVec((const uint8_t *)
+						&policies[num].type4_param.ip_params.v4.dst_ip, 4);
+			} else {
+				classifier_params.dstIp =
+					byteArrToVec((const uint8_t *)
+						&policies[num].type4_param.ip_params.v6.dst_ip, 16);
+			}
+		}
+		if (policies[num].type4_param.classifier_mask & BIT(3)) {
+			mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::SRC_PORT);
+			if (ip_ver4){
+				classifier_params.srcPort =
+					policies[num].type4_param.ip_params.v4.src_port;
+			} else {
+				classifier_params.srcPort =
+					policies[num].type4_param.ip_params.v6.src_port;
+			}
+		}
+
+		if (policies[num].type4_param.classifier_mask & BIT(4)) {
+			mask |= static_cast<uint32_t>(
+				QosPolicyClassifierParamsMask::DST_PORT_RANGE);
+			if (ip_ver4) {
+				classifier_params.dstPortRange.startPort =
+					policies[num].type4_param.ip_params.v4.dst_port;
+				classifier_params.dstPortRange.endPort =
+					policies[num].type4_param.ip_params.v4.dst_port;
+			} else {
+				classifier_params.dstPortRange.startPort =
+					policies[num].type4_param.ip_params.v6.dst_port;
+				classifier_params.dstPortRange.endPort =
+					policies[num].type4_param.ip_params.v6.dst_port;
+			}
+		} else if (policies[num].port_range_info) {
+			mask |= static_cast<uint32_t>(
+				QosPolicyClassifierParamsMask::DST_PORT_RANGE);
+			classifier_params.dstPortRange.startPort = policies[num].start_port;
+			classifier_params.dstPortRange.endPort = policies[num].end_port;
+		}
+		if (policies[num].type4_param.classifier_mask & BIT(6)) {
+			mask |= static_cast<uint32_t>(
+				QosPolicyClassifierParamsMask::PROTOCOL_NEXT_HEADER);
+			if (ip_ver4) {
+				classifier_params.protocolNextHdr = static_cast<ProtocolNextHeader>(
+					policies[num].type4_param.ip_params.v4.protocol);
+			} else {
+				classifier_params.protocolNextHdr = static_cast<ProtocolNextHeader>(
+					policies[num].type4_param.ip_params.v6.next_header);
+			}
+		}
+		if (policies[num].type4_param.classifier_mask & BIT(7)) {
+			mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::FLOW_LABEL);
+			classifier_params.flowLabelIpv6 =
+				byteArrToVec(policies[num].type4_param.ip_params.v6.flow_label, 3);
+		}
+		if (policies[num].domain_name_len != 0) {
+			mask |= static_cast<uint32_t>(QosPolicyClassifierParamsMask::DOMAIN_NAME);
+			classifier_params.domainName =
+				misc_utils::charBufToString(
+					reinterpret_cast<const char *>(policies[num].domain_name));
+		}
+
+		classifier_params.classifierParamMask =
+			static_cast<QosPolicyClassifierParamsMask>(mask);
+		policy.policyId = policies[num].policy_id;
+		policy.requestType = static_cast<QosPolicyRequestType>(policies[num].req_type);
+		policy.dscp = policies[num].dscp;
+		policy.classifierParams = classifier_params;
+
+		qosPolicyData.push_back(policy);
+	}
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onQosPolicyRequest,
+			std::placeholders::_1, wpa_s->dscp_req_dialog_token, qosPolicyData));
+}
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/wpa_supplicant/aidl/aidl_manager.h b/wpa_supplicant/aidl/aidl_manager.h
new file mode 100644
index 0000000..1ed6899
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_manager.h
@@ -0,0 +1,715 @@
+/*
+ * WPA Supplicant - Manager for Aidl interface objects
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_AIDL_MANAGER_H
+#define WPA_SUPPLICANT_AIDL_AIDL_MANAGER_H
+
+#include <map>
+#include <string>
+
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.h>
+
+#include "p2p_iface.h"
+#include "p2p_network.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "sta_iface.h"
+#include "sta_network.h"
+#include "supplicant.h"
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * AidlManager is responsible for managing the lifetime of all
+ * aidl objects created by wpa_supplicant. This is a singleton
+ * class which is created by the supplicant core and can be used
+ * to get references to the aidl objects.
+ */
+class AidlManager
+{
+public:
+	static AidlManager *getInstance();
+	static void destroyInstance();
+
+	// Methods called from wpa_supplicant core.
+	int registerAidlService(struct wpa_global *global);
+	int registerInterface(struct wpa_supplicant *wpa_s);
+	int unregisterInterface(struct wpa_supplicant *wpa_s);
+	int registerNetwork(
+		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+	int unregisterNetwork(
+		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+	int notifyStateChange(struct wpa_supplicant *wpa_s);
+	int notifyNetworkRequest(
+		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
+		const char *param);
+	void notifyAnqpQueryDone(
+		struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+		const struct wpa_bss_anqp *anqp);
+	void notifyHs20IconQueryDone(
+		struct wpa_supplicant *wpa_s, const u8 *bssid,
+		const char *file_name, const u8 *image, u32 image_length);
+	void notifyHs20RxSubscriptionRemediation(
+		struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+	void notifyHs20RxDeauthImminentNotice(
+		struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
+		const char *url);
+	void notifyHs20RxTermsAndConditionsAcceptance(
+			struct wpa_supplicant *wpa_s, const char *url);
+	void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
+	void notifyAssocReject(struct wpa_supplicant *wpa_s, const u8 *bssid,
+		u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len);
+	void notifyAuthTimeout(struct wpa_supplicant *wpa_s);
+	void notifyBssidChanged(struct wpa_supplicant *wpa_s);
+	void notifyWpsEventFail(
+		struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
+		uint16_t config_error, uint16_t error_indication);
+	void notifyWpsEventSuccess(struct wpa_supplicant *wpa_s);
+	void notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s);
+	void notifyP2pDeviceFound(
+		struct wpa_supplicant *wpa_s, const u8 *addr,
+		const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+		u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+		u8 peer_wfd_r2_device_info_len);
+	void notifyP2pDeviceLost(
+		struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
+	void notifyP2pFindStopped(struct wpa_supplicant *wpa_s);
+	void notifyP2pGoNegReq(
+		struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+		u8 go_intent);
+	void notifyP2pGoNegCompleted(
+		struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
+	void notifyP2pGroupFormationFailure(
+		struct wpa_supplicant *wpa_s, const char *reason);
+	void notifyP2pGroupStarted(
+		struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+		int persistent, int client);
+	void notifyP2pGroupRemoved(
+		struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+		const char *role);
+	void notifyP2pInvitationReceived(
+		struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+		const u8 *bssid, int id, int op_freq);
+	void notifyP2pInvitationResult(
+		struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
+	void notifyP2pProvisionDiscovery(
+		struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+		enum p2p_prov_disc_status status, u16 config_methods,
+		unsigned int generated_pin);
+	void notifyP2pSdResponse(
+		struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+		const u8 *tlvs, size_t tlvs_len);
+	void notifyApStaAuthorized(
+		struct wpa_supplicant *wpa_s, const u8 *sta,
+		const u8 *p2p_dev_addr);
+	void notifyApStaDeauthorized(
+		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(struct wpa_supplicant *wpa_s,
+			struct wpa_ssid *config);
+	void notifyDppConfigSent(struct wpa_supplicant *wpa_s);
+	void notifyDppSuccess(struct wpa_supplicant *wpa_s, DppEventType code);
+	void notifyDppFailure(struct wpa_supplicant *wpa_s,
+			DppFailureCode code);
+	void notifyDppFailure(struct wpa_supplicant *wpa_s,
+			DppFailureCode code,
+			const char *ssid, const char *channel_list, unsigned short band_list[],
+			int size);
+	void notifyDppProgress(struct wpa_supplicant *wpa_s,
+			DppProgressCode code);
+	void notifyPmkCacheAdded(struct wpa_supplicant *wpa_s,
+			struct rsn_pmksa_cache_entry *pmksa_entry);
+	void notifyBssTmStatus(struct wpa_supplicant *wpa_s);
+	void notifyTransitionDisable(struct wpa_supplicant *wpa_s,
+			struct wpa_ssid *ssid,
+			u8 bitmap);
+	void notifyNetworkNotFound(struct wpa_supplicant *wpa_s);
+	void notifyFrequencyChanged(struct wpa_supplicant *wpa_s, int frequency);
+	void notifyCertification(struct wpa_supplicant *wpa_s,
+			int depth, const char *subject,
+			const char *altsubject[],
+			int num_altsubject,
+			const char *cert_hash,
+			const struct wpabuf *cert);
+	void notifyAuxiliaryEvent(struct wpa_supplicant *wpa_s,
+			AuxiliarySupplicantEventCode event_code,
+			const char *reason_string);
+	void notifyQosPolicyReset(struct wpa_supplicant *wpa_s);
+	void notifyQosPolicyRequest(struct wpa_supplicant *wpa_s,
+			struct dscp_policy_data *policies,
+			int num_policies);
+
+	// Methods called from aidl objects.
+	void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
+	void notifyExtRadioWorkTimeout(
+		struct wpa_supplicant *wpa_s, uint32_t id);
+
+	int getP2pIfaceAidlObjectByIfname(
+		const std::string &ifname,
+		std::shared_ptr<ISupplicantP2pIface> *iface_object);
+	int getStaIfaceAidlObjectByIfname(
+		const std::string &ifname,
+		std::shared_ptr<ISupplicantStaIface> *iface_object);
+	int getP2pNetworkAidlObjectByIfnameAndNetworkId(
+		const std::string &ifname, int network_id,
+		std::shared_ptr<ISupplicantP2pNetwork> *network_object);
+	int getStaNetworkAidlObjectByIfnameAndNetworkId(
+		const std::string &ifname, int network_id,
+		std::shared_ptr<ISupplicantStaNetwork> *network_object);
+	int addSupplicantCallbackAidlObject(
+		const std::shared_ptr<ISupplicantCallback> &callback);
+	int addP2pIfaceCallbackAidlObject(
+		const std::string &ifname,
+		const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback);
+	int addStaIfaceCallbackAidlObject(
+		const std::string &ifname,
+		const std::shared_ptr<ISupplicantStaIfaceCallback> &callback);
+	int addStaNetworkCallbackAidlObject(
+		const std::string &ifname, int network_id,
+		const std::shared_ptr<ISupplicantStaNetworkCallback> &callback);
+
+private:
+	AidlManager() = default;
+	~AidlManager() = default;
+	AidlManager(const AidlManager &) = default;
+	AidlManager &operator=(const AidlManager &) = default;
+
+	struct wpa_supplicant *getTargetP2pIfaceForGroup(
+		struct wpa_supplicant *wpa_s);
+	void removeSupplicantCallbackAidlObject(
+		const std::shared_ptr<ISupplicantCallback> &callback);
+	void removeP2pIfaceCallbackAidlObject(
+		const std::string &ifname,
+		const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback);
+	void removeStaIfaceCallbackAidlObject(
+		const std::string &ifname,
+		const std::shared_ptr<ISupplicantStaIfaceCallback> &callback);
+	void removeStaNetworkCallbackAidlObject(
+		const std::string &ifname, int network_id,
+		const std::shared_ptr<ISupplicantStaNetworkCallback> &callback);
+
+	void callWithEachSupplicantCallback(
+		const std::function<ndk::ScopedAStatus(
+		std::shared_ptr<ISupplicantCallback>)> &method);
+	void callWithEachP2pIfaceCallback(
+		const std::string &ifname,
+		const std::function<ndk::ScopedAStatus(
+		std::shared_ptr<ISupplicantP2pIfaceCallback>)> &method);
+	void callWithEachStaIfaceCallback(
+		const std::string &ifname,
+		const std::function<ndk::ScopedAStatus(
+		std::shared_ptr<ISupplicantStaIfaceCallback>)> &method);
+	void callWithEachStaNetworkCallback(
+		const std::string &ifname, int network_id,
+		const std::function<::ndk::ScopedAStatus(
+		std::shared_ptr<ISupplicantStaNetworkCallback>)> &method);
+
+	// Singleton instance of this class.
+	static AidlManager *instance_;
+	// Death notifier.
+	AIBinder_DeathRecipient* death_notifier_;
+	// The main aidl service object.
+	std::shared_ptr<Supplicant> supplicant_object_;
+	// Map of all the P2P interface specific aidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname|.
+	std::map<const std::string, std::shared_ptr<P2pIface>>
+		p2p_iface_object_map_;
+	// Map of all the STA interface specific aidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname|.
+	std::map<const std::string, std::shared_ptr<StaIface>>
+		sta_iface_object_map_;
+	// Map of all the P2P network specific aidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname| & |network_id|.
+	std::map<const std::string, std::shared_ptr<P2pNetwork>>
+		p2p_network_object_map_;
+	// Map of all the STA network specific aidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname| & |network_id|.
+	std::map<const std::string, std::shared_ptr<StaNetwork>>
+		sta_network_object_map_;
+
+	// Callbacks registered for the main aidl service object.
+	std::vector<std::shared_ptr<ISupplicantCallback>> supplicant_callbacks_;
+	// Map of all the callbacks registered for P2P interface specific
+	// aidl objects controlled by wpa_supplicant.  This map is keyed in by
+	// the corresponding |ifname|.
+	std::map<
+		const std::string,
+		std::vector<std::shared_ptr<ISupplicantP2pIfaceCallback>>>
+		p2p_iface_callbacks_map_;
+	// Map of all the callbacks registered for STA interface specific
+	// aidl objects controlled by wpa_supplicant.  This map is keyed in by
+	// the corresponding |ifname|.
+	std::map<
+		const std::string,
+		std::vector<std::shared_ptr<ISupplicantStaIfaceCallback>>>
+		sta_iface_callbacks_map_;
+	// Map of all the callbacks registered for STA network specific
+	// aidl objects controlled by wpa_supplicant.  This map is keyed in by
+	// the corresponding |ifname| & |network_id|.
+	std::map<
+		const std::string,
+		std::vector<std::shared_ptr<ISupplicantStaNetworkCallback>>>
+		sta_network_callbacks_map_;
+};
+
+// The aidl interface uses some values which are the same as internal ones to
+// avoid nasty runtime conversion functions. So, adding compile time asserts
+// to guard against any internal changes breaking the aidl interface.
+static_assert(
+	static_cast<uint32_t>(DebugLevel::EXCESSIVE) == MSG_EXCESSIVE,
+	"Debug level value mismatch");
+static_assert(
+	static_cast<uint32_t>(DebugLevel::ERROR) == MSG_ERROR,
+	"Debug level value mismatch");
+
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::NONE) ==
+	WPA_KEY_MGMT_NONE,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::WPA_PSK) ==
+	WPA_KEY_MGMT_PSK,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::WPA_EAP) ==
+	WPA_KEY_MGMT_IEEE8021X,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::IEEE8021X) ==
+	WPA_KEY_MGMT_IEEE8021X_NO_WPA,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::FT_EAP) ==
+	WPA_KEY_MGMT_FT_IEEE8021X,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::FT_PSK) ==
+	WPA_KEY_MGMT_FT_PSK,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::OSEN) ==
+	WPA_KEY_MGMT_OSEN,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::SAE) ==
+	WPA_KEY_MGMT_SAE,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::SUITE_B_192) ==
+	WPA_KEY_MGMT_IEEE8021X_SUITE_B_192,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::OWE) ==
+	WPA_KEY_MGMT_OWE,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::WPA_PSK_SHA256) ==
+	WPA_KEY_MGMT_PSK_SHA256,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::WPA_EAP_SHA256) ==
+	WPA_KEY_MGMT_IEEE8021X_SHA256,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::WAPI_PSK) ==
+	WPA_KEY_MGMT_WAPI_PSK,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(KeyMgmtMask::WAPI_CERT) ==
+	WPA_KEY_MGMT_WAPI_CERT,
+	"KeyMgmt value mismatch");
+static_assert(
+	static_cast<uint32_t>(ProtoMask::WPA) ==
+	WPA_PROTO_WPA,
+	"Proto value mismatch");
+static_assert(
+	static_cast<uint32_t>(ProtoMask::RSN) ==
+	WPA_PROTO_RSN,
+	"Proto value mismatch");
+static_assert(
+	static_cast<uint32_t>(ProtoMask::OSEN) ==
+	WPA_PROTO_OSEN,
+	"Proto value mismatch");
+static_assert(
+	static_cast<uint32_t>(ProtoMask::WAPI) ==
+	WPA_PROTO_WAPI,
+	"Proto value mismatch");
+static_assert(
+	static_cast<uint32_t>(AuthAlgMask::OPEN) ==
+	WPA_AUTH_ALG_OPEN,
+	"AuthAlg value mismatch");
+static_assert(
+	static_cast<uint32_t>(AuthAlgMask::SHARED) ==
+	WPA_AUTH_ALG_SHARED,
+	"AuthAlg value mismatch");
+static_assert(
+	static_cast<uint32_t>(AuthAlgMask::LEAP) ==
+	WPA_AUTH_ALG_LEAP,
+	"AuthAlg value mismatch");
+static_assert(
+	static_cast<uint32_t>(GroupCipherMask::WEP40) ==
+	WPA_CIPHER_WEP40,
+	"GroupCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(GroupCipherMask::WEP104) ==
+	WPA_CIPHER_WEP104,
+	"GroupCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(GroupCipherMask::TKIP) ==
+	WPA_CIPHER_TKIP,
+	"GroupCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(GroupCipherMask::CCMP) ==
+	WPA_CIPHER_CCMP,
+	"GroupCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(GroupCipherMask::GCMP_256) ==
+	WPA_CIPHER_GCMP_256,
+	"GroupCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(GroupCipherMask::SMS4) ==
+	WPA_CIPHER_SMS4,
+	"GroupCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	GroupCipherMask::GTK_NOT_USED) ==
+	WPA_CIPHER_GTK_NOT_USED,
+	"GroupCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(PairwiseCipherMask::NONE) ==
+	WPA_CIPHER_NONE,
+	"PairwiseCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(PairwiseCipherMask::TKIP) ==
+	WPA_CIPHER_TKIP,
+	"PairwiseCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(PairwiseCipherMask::CCMP) ==
+	WPA_CIPHER_CCMP,
+	"PairwiseCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	PairwiseCipherMask::GCMP_256) ==
+	WPA_CIPHER_GCMP_256,
+	"PairwiseCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	PairwiseCipherMask::SMS4) ==
+	WPA_CIPHER_SMS4,
+	"PairwiseCipher value mismatch");
+static_assert(
+	static_cast<uint32_t>(StaIfaceCallbackState::DISCONNECTED) ==
+	WPA_DISCONNECTED,
+	"State value mismatch");
+static_assert(
+	static_cast<uint32_t>(StaIfaceCallbackState::COMPLETED) ==
+	WPA_COMPLETED,
+	"State value mismatch");
+
+static_assert(
+	static_cast<uint32_t>(AnqpInfoId::VENUE_NAME) ==
+	ANQP_VENUE_NAME,
+	"ANQP ID value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	AnqpInfoId::ROAMING_CONSORTIUM) ==
+	ANQP_ROAMING_CONSORTIUM,
+	"ANQP ID value mismatch");
+static_assert(
+	static_cast<uint32_t>(AnqpInfoId::NAI_REALM) ==
+	ANQP_NAI_REALM,
+	"ANQP ID value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	AnqpInfoId::IP_ADDR_TYPE_AVAILABILITY) ==
+	ANQP_IP_ADDR_TYPE_AVAILABILITY,
+	"ANQP ID value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	AnqpInfoId::ANQP_3GPP_CELLULAR_NETWORK) ==
+	ANQP_3GPP_CELLULAR_NETWORK,
+	"ANQP ID value mismatch");
+static_assert(
+	static_cast<uint32_t>(AnqpInfoId::DOMAIN_NAME) ==
+	ANQP_DOMAIN_NAME,
+	"ANQP ID value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	Hs20AnqpSubtypes::OPERATOR_FRIENDLY_NAME) ==
+	HS20_STYPE_OPERATOR_FRIENDLY_NAME,
+	"HS Subtype value mismatch");
+static_assert(
+	static_cast<uint32_t>(Hs20AnqpSubtypes::WAN_METRICS) ==
+	HS20_STYPE_WAN_METRICS,
+	"HS Subtype value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	Hs20AnqpSubtypes::CONNECTION_CAPABILITY) ==
+	HS20_STYPE_CONNECTION_CAPABILITY,
+	"HS Subtype value mismatch");
+static_assert(
+	static_cast<uint32_t>(
+	Hs20AnqpSubtypes::OSU_PROVIDERS_LIST) ==
+	HS20_STYPE_OSU_PROVIDERS_LIST,
+	"HS Subtype value mismatch");
+
+static_assert(
+	static_cast<uint16_t>(
+	WpsConfigError::NO_ERROR) ==
+	WPS_CFG_NO_ERROR,
+	"Wps config error value mismatch");
+static_assert(
+	static_cast<uint16_t>(WpsConfigError::
+				  PUBLIC_KEY_HASH_MISMATCH) ==
+	WPS_CFG_PUBLIC_KEY_HASH_MISMATCH,
+	"Wps config error value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsErrorIndication::NO_ERROR) ==
+	WPS_EI_NO_ERROR,
+	"Wps error indication value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsErrorIndication::AUTH_FAILURE) ==
+	WPS_EI_AUTH_FAILURE,
+	"Wps error indication value mismatch");
+
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::USBA) == WPS_CONFIG_USBA,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::ETHERNET) == WPS_CONFIG_ETHERNET,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::LABEL) == WPS_CONFIG_LABEL,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::DISPLAY) == WPS_CONFIG_DISPLAY,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::INT_NFC_TOKEN) ==
+	WPS_CONFIG_INT_NFC_TOKEN,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::EXT_NFC_TOKEN) ==
+	WPS_CONFIG_EXT_NFC_TOKEN,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::NFC_INTERFACE) ==
+	WPS_CONFIG_NFC_INTERFACE,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::PUSHBUTTON) ==
+	WPS_CONFIG_PUSHBUTTON,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::KEYPAD) == WPS_CONFIG_KEYPAD,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::VIRT_PUSHBUTTON) ==
+	WPS_CONFIG_VIRT_PUSHBUTTON,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::PHY_PUSHBUTTON) ==
+	WPS_CONFIG_PHY_PUSHBUTTON,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::P2PS) == WPS_CONFIG_P2PS,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::VIRT_DISPLAY) ==
+	WPS_CONFIG_VIRT_DISPLAY,
+	"Wps config value mismatch");
+static_assert(
+	static_cast<uint32_t>(WpsConfigMethods::PHY_DISPLAY) ==
+	WPS_CONFIG_PHY_DISPLAY,
+	"Wps config value mismatch");
+
+static_assert(
+	static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_OWNER) ==
+	P2P_GROUP_CAPAB_GROUP_OWNER,
+	"P2P capability value mismatch");
+static_assert(
+	static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_GROUP) ==
+	P2P_GROUP_CAPAB_PERSISTENT_GROUP,
+	"P2P capability value mismatch");
+static_assert(
+	static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_LIMIT) ==
+	P2P_GROUP_CAPAB_GROUP_LIMIT,
+	"P2P capability value mismatch");
+static_assert(
+	static_cast<uint32_t>(P2pGroupCapabilityMask::INTRA_BSS_DIST) ==
+	P2P_GROUP_CAPAB_INTRA_BSS_DIST,
+	"P2P capability value mismatch");
+static_assert(
+	static_cast<uint32_t>(P2pGroupCapabilityMask::CROSS_CONN) ==
+	P2P_GROUP_CAPAB_CROSS_CONN,
+	"P2P capability value mismatch");
+static_assert(
+	static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_RECONN) ==
+	P2P_GROUP_CAPAB_PERSISTENT_RECONN,
+	"P2P capability value mismatch");
+static_assert(
+	static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_FORMATION) ==
+	P2P_GROUP_CAPAB_GROUP_FORMATION,
+	"P2P capability value mismatch");
+
+static_assert(
+	static_cast<uint16_t>(
+	WpsDevPasswordId::DEFAULT) ==
+	DEV_PW_DEFAULT,
+	"Wps dev password id value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsDevPasswordId::USER_SPECIFIED) ==
+	DEV_PW_USER_SPECIFIED,
+	"Wps dev password id value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsDevPasswordId::MACHINE_SPECIFIED) ==
+	DEV_PW_MACHINE_SPECIFIED,
+	"Wps dev password id value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsDevPasswordId::REKEY) == DEV_PW_REKEY,
+	"Wps dev password id value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsDevPasswordId::PUSHBUTTON) ==
+	DEV_PW_PUSHBUTTON,
+	"Wps dev password id value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsDevPasswordId::REGISTRAR_SPECIFIED) ==
+	DEV_PW_REGISTRAR_SPECIFIED,
+	"Wps dev password id value mismatch");
+static_assert(
+	static_cast<uint16_t>(WpsDevPasswordId::
+				  NFC_CONNECTION_HANDOVER) ==
+	DEV_PW_NFC_CONNECTION_HANDOVER,
+	"Wps dev password id value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	WpsDevPasswordId::P2PS_DEFAULT) ==
+	DEV_PW_P2PS_DEFAULT,
+	"Wps dev password id value mismatch");
+
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::SUCCESS) == P2P_SC_SUCCESS,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(P2pStatusCode::
+				  FAIL_INFO_CURRENTLY_UNAVAILABLE) ==
+	P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_INCOMPATIBLE_PARAMS) ==
+	P2P_SC_FAIL_INCOMPATIBLE_PARAMS,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_LIMIT_REACHED) ==
+	P2P_SC_FAIL_LIMIT_REACHED,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_INVALID_PARAMS) ==
+	P2P_SC_FAIL_INVALID_PARAMS,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(P2pStatusCode::
+				  FAIL_UNABLE_TO_ACCOMMODATE) ==
+	P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_PREV_PROTOCOL_ERROR) ==
+	P2P_SC_FAIL_PREV_PROTOCOL_ERROR,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_NO_COMMON_CHANNELS) ==
+	P2P_SC_FAIL_NO_COMMON_CHANNELS,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_UNKNOWN_GROUP) ==
+	P2P_SC_FAIL_UNKNOWN_GROUP,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_BOTH_GO_INTENT_15) ==
+	P2P_SC_FAIL_BOTH_GO_INTENT_15,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(P2pStatusCode::
+				  FAIL_INCOMPATIBLE_PROV_METHOD) ==
+	P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::FAIL_REJECTED_BY_USER) ==
+	P2P_SC_FAIL_REJECTED_BY_USER,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pStatusCode::SUCCESS_DEFERRED) ==
+	P2P_SC_SUCCESS_DEFERRED,
+	"P2P status code value mismatch");
+
+static_assert(
+	static_cast<uint16_t>(
+	P2pProvDiscStatusCode::SUCCESS) ==
+	P2P_PROV_DISC_SUCCESS,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pProvDiscStatusCode::TIMEOUT) ==
+	P2P_PROV_DISC_TIMEOUT,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pProvDiscStatusCode::REJECTED) ==
+	P2P_PROV_DISC_REJECTED,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pProvDiscStatusCode::TIMEOUT_JOIN) ==
+	P2P_PROV_DISC_TIMEOUT_JOIN,
+	"P2P status code value mismatch");
+static_assert(
+	static_cast<uint16_t>(
+	P2pProvDiscStatusCode::INFO_UNAVAILABLE) ==
+	P2P_PROV_DISC_INFO_UNAVAILABLE,
+	"P2P status code value mismatch");
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+#endif  // WPA_SUPPLICANT_AIDL_AIDL_MANAGER_H
diff --git a/wpa_supplicant/aidl/aidl_return_util.h b/wpa_supplicant/aidl/aidl_return_util.h
new file mode 100644
index 0000000..109723a
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_return_util.h
@@ -0,0 +1,66 @@
+/*
+ * WPA Supplicant - Validate interfaces before calling methods
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AIDL_RETURN_UTIL_H_
+#define AIDL_RETURN_UTIL_H_
+
+#include <aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace aidl_return_util {
+
+/**
+ * These utility functions are used to invoke a method on the provided
+ * AIDL interface object.
+ * These functions check if the provided AIDL interface object is valid.
+ * a) If valid, invokes the corresponding internal implementation function of
+ * the AIDL method.
+ * b) If invalid, return without calling the internal implementation function.
+ */
+
+// Use for AIDL methods which only return an AIDL status
+template <typename ObjT, typename WorkFuncT, typename... Args>
+::ndk::ScopedAStatus validateAndCall(
+	ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+	Args&&... args)
+{
+	if (obj->isValid()) {
+		return (obj->*work)(std::forward<Args>(args)...);
+	} else {
+		return ndk::ScopedAStatus::fromServiceSpecificError(
+			static_cast<int32_t>(status_code_if_invalid));
+	}
+}
+
+// Use for AIDL methods which have a return value along with the AIDL status
+template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
+::ndk::ScopedAStatus validateAndCall(
+	ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+	ReturnT* ret_val, Args&&... args)
+{
+	if (obj->isValid()) {
+		auto call_pair = (obj->*work)(std::forward<Args>(args)...);
+		*ret_val = call_pair.first;
+		return std::forward<::ndk::ScopedAStatus>(call_pair.second);
+	} else {
+		return ndk::ScopedAStatus::fromServiceSpecificError(
+			static_cast<int32_t>(status_code_if_invalid));
+	}
+}
+
+}  // namespace aidl_return_util
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+#endif  // AIDL_RETURN_UTIL_H_
diff --git a/wpa_supplicant/aidl/android.hardware.wifi.supplicant-service.rc b/wpa_supplicant/aidl/android.hardware.wifi.supplicant-service.rc
new file mode 100644
index 0000000..3275e36
--- /dev/null
+++ b/wpa_supplicant/aidl/android.hardware.wifi.supplicant-service.rc
@@ -0,0 +1,12 @@
+service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
+	-O/data/vendor/wifi/wpa/sockets -dd \
+	-g@android:wpa_wlan0
+	#   we will start as root and wpa_supplicant will switch to user wifi
+	#   after setting up the capabilities required for WEXT
+	#   user wifi
+	#   group wifi inet keystore
+	interface aidl android.hardware.wifi.supplicant.ISupplicant/default
+	class main
+	socket wpa_wlan0 dgram 660 wifi wifi
+	disabled
+	oneshot
diff --git a/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml b/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml
new file mode 100644
index 0000000..3dc9b02
--- /dev/null
+++ b/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+	<hal format="aidl">
+		<name>android.hardware.wifi.supplicant</name>
+		<fqname>ISupplicant/default</fqname>
+	</hal>
+</manifest>
diff --git a/wpa_supplicant/aidl/iface_config_utils.cpp b/wpa_supplicant/aidl/iface_config_utils.cpp
new file mode 100644
index 0000000..4d3f29c
--- /dev/null
+++ b/wpa_supplicant/aidl/iface_config_utils.cpp
@@ -0,0 +1,179 @@
+/*
+ * WPA Supplicant - Iface configuration methods
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+
+namespace {
+using aidl::android::hardware::wifi::supplicant::SupplicantStatusCode;
+using aidl::android::hardware::wifi::supplicant::WpsConfigMethods;
+
+constexpr uint32_t kMaxWpsDeviceNameSize = WPS_DEV_NAME_MAX_LEN;
+constexpr uint32_t kMaxWpsManufacturerSize = WPS_MANUFACTURER_MAX_LEN;
+constexpr uint32_t kMaxWpsModelNameSize = WPS_MODEL_NAME_MAX_LEN;
+constexpr uint32_t kMaxWpsModelNumberSize = WPS_MODEL_NUMBER_MAX_LEN;
+constexpr uint32_t kMaxWpsSerialNumberSize = WPS_SERIAL_NUMBER_MAX_LEN;
+
+void processConfigUpdate(struct wpa_supplicant* wpa_s, uint32_t changed_param)
+{
+	wpa_s->conf->changed_parameters |= changed_param;
+	wpa_supplicant_update_config(wpa_s);
+}
+
+// Free any existing pointer stored in |dst| and store the provided string value
+// there.
+int freeAndSetStringConfigParam(
+	struct wpa_supplicant* wpa_s, const std::string& value, uint32_t max_size,
+	uint32_t changed_param, char** dst)
+{
+	if (value.size() > max_size) {
+		return -1;
+	}
+	WPA_ASSERT(dst);
+	os_free(static_cast<void*>(*dst));
+	*dst = os_strdup(value.c_str());
+	processConfigUpdate(wpa_s, changed_param);
+	return 0;
+}
+
+std::string convertWpsConfigMethodsMaskToString(uint16_t config_methods)
+{
+	std::string config_methods_str;
+	for (const auto& flag_and_name :
+		 {std::make_pair(WpsConfigMethods::USBA, "usba"),
+		  {WpsConfigMethods::ETHERNET, "ethernet"},
+		  {WpsConfigMethods::LABEL, "label"},
+		  {WpsConfigMethods::DISPLAY, "display"},
+		  {WpsConfigMethods::INT_NFC_TOKEN, "int_nfc_token"},
+		  {WpsConfigMethods::EXT_NFC_TOKEN, "ext_nfc_token"},
+		  {WpsConfigMethods::NFC_INTERFACE, "nfc_interface"},
+		  {WpsConfigMethods::PUSHBUTTON, "push_button"},
+		  {WpsConfigMethods::KEYPAD, "keypad"},
+		  {WpsConfigMethods::VIRT_PUSHBUTTON, "virtual_push_button"},
+		  {WpsConfigMethods::PHY_PUSHBUTTON, "physical_push_button"},
+		  {WpsConfigMethods::P2PS, "p2ps"},
+		  {WpsConfigMethods::VIRT_DISPLAY, "virtual_display"},
+		  {WpsConfigMethods::PHY_DISPLAY, "physical_display"}}) {
+		const auto flag =
+			static_cast<std::underlying_type<WpsConfigMethods>::type>(
+			flag_and_name.first);
+		if ((config_methods & flag) == flag) {
+			config_methods_str += flag_and_name.second;
+			config_methods_str += " ";
+		}
+	}
+	return config_methods_str;
+}
+}  // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace iface_config_utils {
+using misc_utils::createStatus;
+
+ndk::ScopedAStatus setWpsDeviceName(
+	struct wpa_supplicant* wpa_s, const std::string& name)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, name, kMaxWpsDeviceNameSize, CFG_CHANGED_DEVICE_NAME,
+		&wpa_s->conf->device_name)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsDeviceType(
+	struct wpa_supplicant* wpa_s, const std::array<uint8_t, WPS_DEV_TYPE_LEN>& type)
+{
+	WPA_ASSERT(wpa_s);
+	WPA_ASSERT(type.size() == WPS_DEV_TYPE_LEN);
+	os_memcpy(wpa_s->conf->device_type, type.data(), WPS_DEV_TYPE_LEN);
+	processConfigUpdate(wpa_s, CFG_CHANGED_DEVICE_TYPE);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsManufacturer(
+	struct wpa_supplicant* wpa_s, const std::string& manufacturer)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, manufacturer, kMaxWpsManufacturerSize,
+		CFG_CHANGED_WPS_STRING, &wpa_s->conf->manufacturer)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsModelName(
+	struct wpa_supplicant* wpa_s, const std::string& model_name)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, model_name, kMaxWpsModelNameSize, CFG_CHANGED_WPS_STRING,
+		&wpa_s->conf->model_name)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsModelNumber(
+	struct wpa_supplicant* wpa_s, const std::string& model_number)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, model_number, kMaxWpsModelNumberSize,
+		CFG_CHANGED_WPS_STRING, &wpa_s->conf->model_number)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsSerialNumber(
+	struct wpa_supplicant* wpa_s, const std::string& serial_number)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, serial_number, kMaxWpsSerialNumberSize,
+		CFG_CHANGED_WPS_STRING, &wpa_s->conf->serial_number)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsConfigMethods(
+	struct wpa_supplicant* wpa_s, uint16_t config_methods)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, convertWpsConfigMethodsMaskToString(config_methods),
+		UINT32_MAX, CFG_CHANGED_CONFIG_METHODS,
+		&wpa_s->conf->config_methods)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setExternalSim(
+	struct wpa_supplicant* wpa_s, bool useExternalSim)
+{
+	WPA_ASSERT(wpa_s);
+	wpa_s->conf->external_sim = useExternalSim ? 1 : 0;
+	return ndk::ScopedAStatus::ok();
+}
+}  // namespace iface_config_utils
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/wpa_supplicant/aidl/iface_config_utils.h b/wpa_supplicant/aidl/iface_config_utils.h
new file mode 100644
index 0000000..c17dbb4
--- /dev/null
+++ b/wpa_supplicant/aidl/iface_config_utils.h
@@ -0,0 +1,55 @@
+/*
+ * WPA Supplicant - Iface configuration methods
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_IFACE_CONFIG_UTILS_H
+#define WPA_SUPPLICANT_AIDL_IFACE_CONFIG_UTILS_H
+
+#include <android-base/macros.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+}
+
+/**
+ * Utility functions to set various config parameters of an iface via AIDL
+ * methods.
+ */
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace iface_config_utils {
+ndk::ScopedAStatus setWpsDeviceName(
+	struct wpa_supplicant* wpa_s, const std::string& name);
+ndk::ScopedAStatus setWpsDeviceType(
+	struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type);
+ndk::ScopedAStatus setWpsManufacturer(
+	struct wpa_supplicant* wpa_s, const std::string& manufacturer);
+ndk::ScopedAStatus setWpsModelName(
+	struct wpa_supplicant* wpa_s, const std::string& model_name);
+ndk::ScopedAStatus setWpsModelNumber(
+	struct wpa_supplicant* wpa_s, const std::string& model_number);
+ndk::ScopedAStatus setWpsSerialNumber(
+	struct wpa_supplicant* wpa_s, const std::string& serial_number);
+ndk::ScopedAStatus setWpsConfigMethods(
+	struct wpa_supplicant* wpa_s, uint16_t config_methods);
+ndk::ScopedAStatus setExternalSim(
+	struct wpa_supplicant* wpa_s, bool useExternalSim);
+}  // namespace iface_config_utils
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // WPA_SUPPLICANT_AIDL_IFACE_CONFIG_UTILS_H
diff --git a/wpa_supplicant/hidl/1.4/misc_utils.h b/wpa_supplicant/aidl/misc_utils.h
similarity index 75%
rename from wpa_supplicant/hidl/1.4/misc_utils.h
rename to wpa_supplicant/aidl/misc_utils.h
index 6e69d4c..5c5b68c 100644
--- a/wpa_supplicant/hidl/1.4/misc_utils.h
+++ b/wpa_supplicant/aidl/misc_utils.h
@@ -1,7 +1,6 @@
 /*
- * hidl interface for wpa_supplicant daemon
- * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ * WPA Supplicant - Helper methods for Aidl
+ * Copyright (c) 2021, Google Inc. All rights reserved.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -11,6 +10,7 @@
 #define MISC_UTILS_H_
 
 #include <iostream>
+#include <aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.h>
 
 extern "C"
 {
@@ -23,12 +23,11 @@
 void freeWpaBuf(wpabuf *ptr) { wpabuf_free(ptr); }
 }  // namespace
 
+namespace aidl {
 namespace android {
 namespace hardware {
 namespace wifi {
 namespace supplicant {
-namespace V1_4 {
-namespace implementation {
 namespace misc_utils {
 using wpabuf_unique_ptr = std::unique_ptr<wpabuf, void (*)(wpabuf *)>;
 
@@ -43,7 +42,7 @@
 inline wpabuf_unique_ptr convertVectorToWpaBuf(const std::vector<uint8_t> &data)
 {
 	return createWpaBufUniquePtr(
-	    wpabuf_alloc_copy(data.data(), data.size()));
+		wpabuf_alloc_copy(data.data(), data.size()));
 }
 
 // Copies the provided wpabuf contents to a std::vector.
@@ -51,7 +50,7 @@
 {
 	if (buf) {
 		return std::vector<uint8_t>(
-		    wpabuf_head_u8(buf), wpabuf_head_u8(buf) + wpabuf_len(buf));
+			wpabuf_head_u8(buf), wpabuf_head_u8(buf) + wpabuf_len(buf));
 	} else {
 		return std::vector<uint8_t>();
 	}
@@ -65,8 +64,26 @@
 	return pin_str;
 }
 
+// Wrappers to create a ScopedAStatus using a SupplicantStatusCode
+inline ndk::ScopedAStatus createStatus(SupplicantStatusCode status_code) {
+	return ndk::ScopedAStatus::fromServiceSpecificError(
+		static_cast<int32_t>(status_code));
+}
+
+inline ndk::ScopedAStatus createStatusWithMsg(
+	SupplicantStatusCode status_code, std::string msg)
+{
+	return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+		static_cast<int32_t>(status_code), msg.c_str());
+}
+
+// Creates an std::string from a char*, which could be null
+inline std::string charBufToString(const char* buf) {
+	return buf ? std::string(buf) : "";
+}
+
 inline std::stringstream& serializePmkCacheEntry(
-    std::stringstream &ss, struct rsn_pmksa_cache_entry *pmksa_entry) {
+	std::stringstream &ss, struct rsn_pmksa_cache_entry *pmksa_entry) {
 	ss.write((char *) &pmksa_entry->pmk_len, sizeof(pmksa_entry->pmk_len));
 	ss.write((char *) pmksa_entry->pmk, pmksa_entry->pmk_len);
 	ss.write((char *) pmksa_entry->pmkid, PMKID_LEN);
@@ -84,7 +101,7 @@
 }
 
 inline std::stringstream& deserializePmkCacheEntry(
-    std::stringstream &ss, struct rsn_pmksa_cache_entry *pmksa_entry) {
+	std::stringstream &ss, struct rsn_pmksa_cache_entry *pmksa_entry) {
 	ss.seekg(0);
 	ss.read((char *) &pmksa_entry->pmk_len, sizeof(pmksa_entry->pmk_len));
 	ss.read((char *) pmksa_entry->pmk, pmksa_entry->pmk_len);
@@ -102,10 +119,9 @@
 	return ss;
 }
 }  // namespace misc_utils
-}  // namespace implementation
-}  // namespace V1_4
 }  // namespace supplicant
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
+}  // namespace aidl
 #endif  // MISC_UTILS_H_
diff --git a/wpa_supplicant/aidl/p2p_iface.cpp b/wpa_supplicant/aidl/p2p_iface.cpp
new file mode 100644
index 0000000..06c4545
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_iface.cpp
@@ -0,0 +1,2171 @@
+/*
+ * WPA Supplicant - P2P Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+#include "p2p_iface.h"
+#include "sta_network.h"
+
+extern "C"
+{
+#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 3
+// Wait time before triggering the single channel scan to discover Auto GO.
+// Use a shorter wait time when the given frequency is GO operating frequency.
+// The idea is to quickly finish scans and return the status to application.
+#define P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS 200000
+// Wait time before triggering the multiple channel scan to discover Auto GO.
+#define P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS 1000000
+
+namespace {
+const char kConfigMethodStrPbc[] = "pbc";
+const char kConfigMethodStrDisplay[] = "display";
+const char kConfigMethodStrKeypad[] = "keypad";
+constexpr char kSetMiracastMode[] = "MIRACAST ";
+constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
+constexpr uint8_t kWfdR2DeviceInfoSubelemId = 11;
+constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
+
+std::function<void()> pending_join_scan_callback = NULL;
+std::function<void()> pending_scan_res_join_callback = NULL;
+
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::MiracastMode;
+using aidl::android::hardware::wifi::supplicant::P2pFrameTypeMask;
+
+uint8_t convertAidlMiracastModeToInternal(
+	MiracastMode mode)
+{
+	switch (mode) {
+	case MiracastMode::DISABLED:
+		return 0;
+	case MiracastMode::SOURCE:
+		return 1;
+	case MiracastMode::SINK:
+		return 2;
+	};
+	WPA_ASSERT(false);
+}
+
+/**
+ * Check if the provided ssid is valid or not.
+ *
+ * Returns 1 if valid, 0 otherwise.
+ */
+int isSsidValid(const std::vector<uint8_t>& ssid)
+{
+	if (ssid.size() == 0 ||
+		ssid.size() >
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  SSID_MAX_LEN_IN_BYTES)) {
+		return 0;
+	}
+	return 1;
+}
+
+/**
+ * Check if the provided psk passhrase is valid or not.
+ *
+ * Returns 1 if valid, 0 otherwise.
+ */
+int isPskPassphraseValid(const std::string &psk)
+{
+	if (psk.size() <
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+		psk.size() >
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
+		return 0;
+	}
+	if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
+		return 0;
+	}
+	return 1;
+}
+
+static int setBandScanFreqsList(
+	struct wpa_supplicant *wpa_s,
+	enum hostapd_hw_mode hw_mode,
+	bool exclude_dfs,
+	struct wpa_driver_scan_params *params)
+{
+	struct hostapd_hw_modes *mode;
+	int count, i;
+
+	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
+	if (mode == NULL || !mode->num_channels) {
+		wpa_printf(MSG_ERROR,
+			"P2P: No channels supported in this hw_mode: %d", hw_mode);
+		return -1;
+	}
+
+	/*
+	 * Allocate memory for frequency array, allocate one extra
+	 * slot for the zero-terminator.
+	 */
+	params->freqs = (int *) os_calloc(mode->num_channels + 1, sizeof(int));
+	if (params->freqs == NULL) {
+		return -ENOMEM;
+	}
+	for (count = 0, i = 0; i < mode->num_channels; i++) {
+		if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) {
+			continue;
+		}
+		if (exclude_dfs && (mode->channels[i].flag & HOSTAPD_CHAN_RADAR)) {
+			continue;
+		}
+		params->freqs[count++] = mode->channels[i].freq;
+	}
+	if (!count && params->freqs) {
+		wpa_printf(MSG_ERROR,
+			"P2P: All channels(exclude_dfs: %d) are disabled in this hw_mode: %d",
+			exclude_dfs, hw_mode);
+		os_free(params->freqs);
+		return -1;
+	}
+	return 0;
+}
+
+static int setScanFreq(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params,
+	int freq, int operating_freq)
+{
+	int frequency = operating_freq ? operating_freq : freq;
+	if (disabled_freq(wpa_s, frequency)) {
+		wpa_printf(MSG_ERROR,
+				"P2P: freq %d is not supported for a client.", frequency);
+		return -1;
+	}
+	/*
+	 * Allocate memory for frequency array, with one extra
+	 * slot for the zero-terminator.
+	 */
+	params->freqs = new int[2] {frequency, 0};
+	return 0;
+}
+
+/**
+ * setP2pCliOptimizedScanFreqsList - Fill the frequencies to scan in Scan
+ * parameters.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @params: Pointer to Scan parameters.
+ * @freq: Frequency/Band requested to scan by the application, possible values are,
+ *		0 - All the frequencies - full scan
+ *		2 - Frequencies in 2.4GHz
+ *		5 - Frequencies in 5GHz
+ *		- Valid frequency
+ * @operating_freq: Frequency of BSS if found in scan cache
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
+	struct wpa_driver_scan_params *params, int freq, int operating_freq)
+{
+	int ret;
+	/* If BSS is found in scan cache, first scan its operating frequency */
+	if (!wpa_s->p2p_join_scan_count && operating_freq) {
+		ret = setScanFreq(wpa_s, params, freq, operating_freq);
+		if (!ret) {
+			return ret;
+		}
+	}
+
+	/* Empty freq params means scan all the frequencies */
+	if (freq == 0) {
+		return 0;
+	}
+	else if (freq == 2 || freq == 5) {
+		/* Scan the frequencies in the band */
+		enum hostapd_hw_mode mode;
+		int ret;
+		if (wpa_s->hw.modes == NULL) {
+			wpa_printf(MSG_DEBUG,
+				   "P2P: Unknown what %dG channels the driver supports.", freq);
+			return 0;
+		}
+		mode = freq == 5 ? HOSTAPD_MODE_IEEE80211A : HOSTAPD_MODE_IEEE80211G;
+		if (wpa_s->p2p_join_scan_count < 2) {
+			// scan all non DFS channels in the first two attempts
+			ret = setBandScanFreqsList(wpa_s, mode, true, params);
+			if (ret < 0 && (-ENOMEM != ret)) {
+				// try to scan all channels before returning error
+				ret = setBandScanFreqsList(wpa_s, mode, false, params);
+			}
+		} else {
+			// scan all channels
+			ret = setBandScanFreqsList(wpa_s, mode, false, params);
+		}
+		return ret;
+	} else {
+		/* Scan the frequency requested by the application */
+		ret = setScanFreq(wpa_s, params, freq, 0);
+		return ret;
+	}
+	return 0;
+}
+
+/**
+ * getP2pJoinScanInterval - Get the delay in triggering the scan to discover
+ * Auto GO.
+ */
+static int getP2pJoinScanIntervalUsecs(int freq)
+{
+	if (freq == 5 || freq == 2 || freq == 0) {
+		return P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS;
+	} else {
+		return P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS;
+	}
+}
+
+/*
+ * isAnyEtherAddr - match any ether address
+ *
+ */
+int isAnyEtherAddr(const u8 *a)
+{
+	// 02:00:00:00:00:00
+	return (a[0] == 2) && !(a[1] | a[2] | a[3] | a[4] | a[5]);
+}
+
+/**
+ * findBssBySsid - Fetch a BSS table entry based on SSID and optional BSSID.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID, 02:00:00:00:00:00 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 ((isAnyEtherAddr(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;
+}
+
+/**
+ * findBssBySsidFromAnyInterface - Fetch a BSS table entry based on SSID and optional BSSID
+ * by iterating through all the interfaces.
+ * @head: Head of Pointer to wpa_supplicant data
+ * @bssid: BSSID, 02:00:00:00:00:00 matches any bssid
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss* findBssBySsidFromAnyInterface(
+	struct wpa_supplicant *head, const u8 *bssid,
+	const u8 *ssid, size_t ssid_len)
+{
+	struct wpa_supplicant *wpa_s;
+	struct wpa_bss *bss = NULL;
+	for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) {
+		bss = findBssBySsid(wpa_s, bssid, ssid, ssid_len);
+		if (bss != NULL) {
+			return bss;
+		}
+	}
+	return bss;
+}
+
+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 = 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 (wpa_s->p2p_scan_work) {
+		struct wpa_radio_work *work = wpa_s->p2p_scan_work;
+		wpa_s->p2p_scan_work = NULL;
+		radio_work_done(work);
+	}
+
+	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 operating_freq)
+{
+	int ret;
+	struct wpa_driver_scan_params params;
+	struct wpabuf *ies;
+	size_t ielen;
+	unsigned int bands;
+
+	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+		wpa_printf(MSG_ERROR,
+			"P2P: P2P interface is gone, cancel join scan");
+		return -ENXIO;
+	}
+
+	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"
+		"BSS operating_freq from scan cache %d",
+		wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq, operating_freq);
+
+	/* Construct an optimized p2p scan channel list */
+	ret = setP2pCliOptimizedScanFreqsList(wpa_s, &params, freq, operating_freq);
+	if (ret < 0) {
+		wpa_printf(MSG_ERROR,
+				   "Failed to set frequency in p2p scan params, error = %d", ret);
+		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);
+		if (wpa_s->scan_res_handler) {
+			wpa_printf(MSG_DEBUG, "Replace current running scan result handler");
+		}
+		wpa_s->p2p_join_scan_count++;
+		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;
+}
+
+static bool is6GhzAllowed(struct wpa_supplicant *wpa_s) {
+	if (!wpa_s->global->p2p) return false;
+	return wpa_s->global->p2p->allow_6ghz;
+}
+
+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 he = wpa_s->conf->p2p_go_he;
+	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,
+		CHANWIDTH_USE_HT, he, 0, NULL, 0, 0, is6GhzAllowed(wpa_s))) {
+		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.");
+
+	if (wpa_s->p2p_scan_work) {
+		struct wpa_radio_work *work = wpa_s->p2p_scan_work;
+		wpa_s->p2p_scan_work = NULL;
+		radio_work_done(work);
+	}
+
+}
+
+static void updateP2pVendorElem(struct wpa_supplicant* wpa_s, enum wpa_vendor_elem_frame frameType,
+	const std::vector<uint8_t>& vendorElemBytes) {
+
+	wpa_printf(MSG_INFO, "Set vendor elements to frames %d", frameType);
+	struct wpa_supplicant* vendor_elem_wpa_s = wpas_vendor_elem(wpa_s, frameType);
+	if (vendor_elem_wpa_s->vendor_elem[frameType]) {
+		wpabuf_free(vendor_elem_wpa_s->vendor_elem[frameType]);
+		vendor_elem_wpa_s->vendor_elem[frameType] = NULL;
+	}
+	if (vendorElemBytes.size() > 0) {
+		vendor_elem_wpa_s->vendor_elem[frameType] =
+			wpabuf_alloc_copy(vendorElemBytes.data(), vendorElemBytes.size());
+	}
+	wpas_vendor_elem_update(vendor_elem_wpa_s);
+}
+
+uint32_t convertWpaP2pFrameTypeToHalP2pFrameTypeBit(int frameType) {
+	switch (frameType) {
+	case VENDOR_ELEM_PROBE_REQ_P2P:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_PROBE_REQ_P2P);
+	case VENDOR_ELEM_PROBE_RESP_P2P:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_PROBE_RESP_P2P);
+	case VENDOR_ELEM_PROBE_RESP_P2P_GO:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_PROBE_RESP_P2P_GO);
+	case VENDOR_ELEM_BEACON_P2P_GO:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_BEACON_P2P_GO);
+	case VENDOR_ELEM_P2P_PD_REQ:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_PD_REQ);
+	case VENDOR_ELEM_P2P_PD_RESP:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_PD_RESP);
+	case VENDOR_ELEM_P2P_GO_NEG_REQ:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_GO_NEG_REQ);
+	case VENDOR_ELEM_P2P_GO_NEG_RESP:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_GO_NEG_RESP);
+	case VENDOR_ELEM_P2P_GO_NEG_CONF:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_GO_NEG_CONF);
+	case VENDOR_ELEM_P2P_INV_REQ:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_INV_REQ);
+	case VENDOR_ELEM_P2P_INV_RESP:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_INV_RESP);
+	case VENDOR_ELEM_P2P_ASSOC_REQ:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_ASSOC_REQ);
+	case VENDOR_ELEM_P2P_ASSOC_RESP:
+		return static_cast<uint32_t>(P2pFrameTypeMask::P2P_FRAME_P2P_ASSOC_RESP);
+	}
+	return 0;
+}
+}  // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+using misc_utils::createStatusWithMsg;
+
+P2pIface::P2pIface(struct wpa_global* wpa_global, const char ifname[])
+	: wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
+{}
+
+void P2pIface::invalidate() { is_valid_ = false; }
+bool P2pIface::isValid()
+{
+	return (is_valid_ && (retrieveIfacePtr() != nullptr));
+}
+
+::ndk::ScopedAStatus P2pIface::getName(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::getNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::getType(
+	IfaceType* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::addNetwork(
+	std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::addNetworkInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::removeNetwork(
+	int32_t in_id)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::removeNetworkInternal, in_id);
+}
+
+::ndk::ScopedAStatus P2pIface::getNetwork(
+	int32_t in_id, std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::getNetworkInternal, _aidl_return, in_id);
+}
+
+::ndk::ScopedAStatus P2pIface::listNetworks(
+	std::vector<int32_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::listNetworksInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::registerCallback(
+	const std::shared_ptr<ISupplicantP2pIfaceCallback>& in_callback)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus P2pIface::getDeviceAddress(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::getDeviceAddressInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::setSsidPostfix(
+	const std::vector<uint8_t>& in_postfix)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setSsidPostfixInternal, in_postfix);
+}
+
+::ndk::ScopedAStatus P2pIface::setGroupIdle(
+	const std::string& in_groupIfName, int32_t in_timeoutInSec)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setGroupIdleInternal, in_groupIfName,
+		in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus P2pIface::setPowerSave(
+	const std::string& in_groupIfName, bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setPowerSaveInternal, in_groupIfName, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::find(
+	int32_t in_timeoutInSec)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::findInternal, in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus P2pIface::stopFind()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::stopFindInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::flush()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::flushInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::connect(
+	const std::vector<uint8_t>& in_peerAddress,
+	WpsProvisionMethod in_provisionMethod,
+	const std::string& in_preSelectedPin, bool in_joinExistingGroup,
+	bool in_persistent, int32_t in_goIntent, std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::connectInternal, _aidl_return, in_peerAddress,
+		in_provisionMethod, in_preSelectedPin, in_joinExistingGroup,
+		in_persistent, in_goIntent);
+}
+
+::ndk::ScopedAStatus P2pIface::cancelConnect()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::cancelConnectInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::provisionDiscovery(
+	const std::vector<uint8_t>& in_peerAddress,
+	WpsProvisionMethod in_provisionMethod)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::provisionDiscoveryInternal, in_peerAddress,
+		in_provisionMethod);
+}
+
+ndk::ScopedAStatus P2pIface::addGroup(
+	bool in_persistent, int32_t in_persistentNetworkId)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::addGroupInternal, in_persistent,
+		in_persistentNetworkId);
+}
+
+::ndk::ScopedAStatus P2pIface::addGroupWithConfig(
+	const std::vector<uint8_t>& in_ssid,
+	const std::string& in_pskPassphrase, bool in_persistent,
+	int32_t in_freq, const std::vector<uint8_t>& in_peerAddress,
+	bool in_joinExistingGroup)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::addGroupWithConfigInternal, in_ssid,
+		in_pskPassphrase, in_persistent, in_freq,
+		in_peerAddress, in_joinExistingGroup);
+}
+
+::ndk::ScopedAStatus P2pIface::removeGroup(
+	const std::string& in_groupIfName)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::removeGroupInternal, in_groupIfName);
+}
+
+::ndk::ScopedAStatus P2pIface::reject(
+	const std::vector<uint8_t>& in_peerAddress)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::rejectInternal, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::invite(
+	const std::string& in_groupIfName,
+	const std::vector<uint8_t>& in_goDeviceAddress,
+	const std::vector<uint8_t>& in_peerAddress)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::inviteInternal, in_groupIfName,
+		in_goDeviceAddress, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::reinvoke(
+	int32_t in_persistentNetworkId,
+	const std::vector<uint8_t>& in_peerAddress)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::reinvokeInternal, in_persistentNetworkId,
+		in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::configureExtListen(
+	int32_t in_periodInMillis, int32_t in_intervalInMillis)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::configureExtListenInternal, in_periodInMillis,
+		in_intervalInMillis);
+}
+
+::ndk::ScopedAStatus P2pIface::setListenChannel(
+	int32_t in_channel, int32_t in_operatingClass)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setListenChannelInternal, in_channel,
+		in_operatingClass);
+}
+
+::ndk::ScopedAStatus P2pIface::setDisallowedFrequencies(
+	const std::vector<FreqRange>& in_ranges)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setDisallowedFrequenciesInternal, in_ranges);
+}
+
+::ndk::ScopedAStatus P2pIface::getSsid(
+	const std::vector<uint8_t>& in_peerAddress,
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::getSsidInternal, _aidl_return, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::getGroupCapability(
+	const std::vector<uint8_t>& in_peerAddress,
+	P2pGroupCapabilityMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::getGroupCapabilityInternal, _aidl_return, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::addBonjourService(
+	const std::vector<uint8_t>& in_query,
+	const std::vector<uint8_t>& in_response)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::addBonjourServiceInternal, in_query, in_response);
+}
+
+::ndk::ScopedAStatus P2pIface::removeBonjourService(
+	const std::vector<uint8_t>& in_query)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::removeBonjourServiceInternal, in_query);
+}
+
+::ndk::ScopedAStatus P2pIface::addUpnpService(
+	int32_t in_version, const std::string& in_serviceName)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::addUpnpServiceInternal, in_version, in_serviceName);
+}
+
+::ndk::ScopedAStatus P2pIface::removeUpnpService(
+	int32_t in_version, const std::string& in_serviceName)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::removeUpnpServiceInternal, in_version,
+		in_serviceName);
+}
+
+::ndk::ScopedAStatus P2pIface::flushServices()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::flushServicesInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::requestServiceDiscovery(
+	const std::vector<uint8_t>& in_peerAddress,
+	const std::vector<uint8_t>& in_query,
+	int64_t* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::requestServiceDiscoveryInternal, _aidl_return,
+		in_peerAddress, in_query);
+}
+
+::ndk::ScopedAStatus P2pIface::cancelServiceDiscovery(
+	int64_t in_identifier)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::cancelServiceDiscoveryInternal, in_identifier);
+}
+
+::ndk::ScopedAStatus P2pIface::setMiracastMode(
+	MiracastMode in_mode)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setMiracastModeInternal, in_mode);
+}
+
+::ndk::ScopedAStatus P2pIface::startWpsPbc(
+	const std::string& in_groupIfName,
+	const std::vector<uint8_t>& in_bssid)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::startWpsPbcInternal, in_groupIfName, in_bssid);
+}
+
+::ndk::ScopedAStatus P2pIface::startWpsPinKeypad(
+	const std::string& in_groupIfName,
+	const std::string& in_pin)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::startWpsPinKeypadInternal, in_groupIfName, in_pin);
+}
+
+::ndk::ScopedAStatus P2pIface::startWpsPinDisplay(
+	const std::string& in_groupIfName,
+	const std::vector<uint8_t>& in_bssid,
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::startWpsPinDisplayInternal, _aidl_return,
+		in_groupIfName, in_bssid);
+}
+
+::ndk::ScopedAStatus P2pIface::cancelWps(
+	const std::string& in_groupIfName)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::cancelWpsInternal, in_groupIfName);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsDeviceName(
+	const std::string& in_name)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWpsDeviceNameInternal, in_name);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsDeviceType(
+	const std::vector<uint8_t>& in_type)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWpsDeviceTypeInternal, in_type);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsManufacturer(
+	const std::string& in_manufacturer)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWpsManufacturerInternal, in_manufacturer);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsModelName(
+	const std::string& in_modelName)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWpsModelNameInternal, in_modelName);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsModelNumber(
+	const std::string& in_modelNumber)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWpsModelNumberInternal, in_modelNumber);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsSerialNumber(
+	const std::string& in_serialNumber)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWpsSerialNumberInternal, in_serialNumber);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsConfigMethods(
+	WpsConfigMethods in_configMethods)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWpsConfigMethodsInternal, in_configMethods);
+}
+
+::ndk::ScopedAStatus P2pIface::enableWfd(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::enableWfdInternal, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::setWfdDeviceInfo(
+	const std::vector<uint8_t>& in_info)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWfdDeviceInfoInternal, in_info);
+}
+
+::ndk::ScopedAStatus P2pIface::createNfcHandoverRequestMessage(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::createNfcHandoverRequestMessageInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::createNfcHandoverSelectMessage(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::createNfcHandoverSelectMessageInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::reportNfcHandoverResponse(
+	const std::vector<uint8_t>& in_request)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::reportNfcHandoverResponseInternal, in_request);
+}
+
+::ndk::ScopedAStatus P2pIface::reportNfcHandoverInitiation(
+	const std::vector<uint8_t>& in_select)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::reportNfcHandoverInitiationInternal, in_select);
+}
+
+::ndk::ScopedAStatus P2pIface::saveConfig()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::saveConfigInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::setMacRandomization(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setMacRandomizationInternal, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::setEdmg(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pIface::setEdmgInternal, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::getEdmg(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pIface::getEdmgInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::setWfdR2DeviceInfo(
+	const std::vector<uint8_t>& in_info)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setWfdR2DeviceInfoInternal, in_info);
+}
+
+::ndk::ScopedAStatus P2pIface::removeClient(
+        const std::vector<uint8_t>& peer_address, bool isLegacyClient)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::removeClientInternal, peer_address, isLegacyClient);
+}
+
+::ndk::ScopedAStatus P2pIface::findOnSocialChannels(
+	int32_t in_timeoutInSec)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::findOnSocialChannelsInternal, in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus P2pIface::findOnSpecificFrequency(
+	int32_t in_freq,
+	int32_t in_timeoutInSec)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::findOnSpecificFrequencyInternal,
+		in_freq, in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus P2pIface::setVendorElements(
+	P2pFrameTypeMask in_frameTypeMask,
+	const std::vector<uint8_t>& in_vendorElemBytes)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::setVendorElementsInternal, in_frameTypeMask, in_vendorElemBytes);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> P2pIface::getNameInternal()
+{
+	return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> P2pIface::getTypeInternal()
+{
+	return {IfaceType::P2P, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+P2pIface::addNetworkInternal()
+{
+	std::shared_ptr<ISupplicantP2pNetwork> network;
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpa_ssid* ssid = wpa_supplicant_add_network(wpa_s);
+	if (!ssid) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	AidlManager* aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager ||
+		aidl_manager->getP2pNetworkAidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {network, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::removeNetworkInternal(int32_t id)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int result = wpa_supplicant_remove_network(wpa_s, id);
+	if (result == -1) {
+		return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+	} else if (result != 0) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+P2pIface::getNetworkInternal(int32_t id)
+{
+	std::shared_ptr<ISupplicantP2pNetwork> network;
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpa_ssid* ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (!ssid) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN)};
+	}
+	AidlManager* aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager ||
+		aidl_manager->getP2pNetworkAidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {network, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+P2pIface::listNetworksInternal()
+{
+	std::vector<int32_t> network_ids;
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	for (struct wpa_ssid* wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
+		 wpa_ssid = wpa_ssid->next) {
+		network_ids.emplace_back(wpa_ssid->id);
+	}
+	return {std::move(network_ids), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::registerCallbackInternal(
+	const std::shared_ptr<ISupplicantP2pIfaceCallback>& callback)
+{
+	AidlManager* aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager ||
+		aidl_manager->addP2pIfaceCallbackAidlObject(ifname_, callback)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+P2pIface::getDeviceAddressInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	std::vector<uint8_t> addr(
+		wpa_s->global->p2p_dev_addr,
+		wpa_s->global->p2p_dev_addr + ETH_ALEN);
+	return {addr, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::setSsidPostfixInternal(
+	const std::vector<uint8_t>& postfix)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (p2p_set_ssid_postfix(
+		wpa_s->global->p2p, postfix.data(), postfix.size())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setGroupIdleInternal(
+	const std::string& group_ifname, uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_group_s =
+		retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	wpa_group_s->conf->p2p_group_idle = timeout_in_sec;
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setPowerSaveInternal(
+	const std::string& group_ifname, bool enable)
+{
+	struct wpa_supplicant* wpa_group_s =
+		retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	if (wpa_drv_set_p2p_powersave(wpa_group_s, enable, -1, -1)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::findInternal(uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
+	if (wpas_p2p_find(
+		wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
+		nullptr, search_delay, 0, nullptr, 0, is6GhzAllowed(wpa_s))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::stopFindInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(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 ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::flushInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
+	wpa_s->force_long_sd = 0;
+	wpas_p2p_stop_find(wpa_s);
+	wpa_s->parent->p2ps_method_config_any = 0;
+	wpa_bss_flush(wpa_s);
+	if (wpa_s->global->p2p)
+		p2p_flush(wpa_s->global->p2p);
+	return ndk::ScopedAStatus::ok();
+}
+
+// This method only implements support for subset (needed by Android framework)
+// of parameters that can be specified for connect.
+std::pair<std::string, ndk::ScopedAStatus> P2pIface::connectInternal(
+	const std::vector<uint8_t>& peer_address,
+	WpsProvisionMethod provision_method,
+	const std::string& pre_selected_pin, bool join_existing_group,
+	bool persistent, uint32_t go_intent)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (go_intent > 15) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+	}
+	int go_intent_signed = join_existing_group ? -1 : go_intent;
+	p2p_wps_method wps_method = {};
+	switch (provision_method) {
+	case WpsProvisionMethod::PBC:
+		wps_method = WPS_PBC;
+		break;
+	case WpsProvisionMethod::DISPLAY:
+		wps_method = WPS_PIN_DISPLAY;
+		break;
+	case WpsProvisionMethod::KEYPAD:
+		wps_method = WPS_PIN_KEYPAD;
+		break;
+	}
+	int he = wpa_s->conf->p2p_go_he;
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+	const char* pin =
+		pre_selected_pin.length() > 0 ? pre_selected_pin.data() : nullptr;
+	bool auto_join = !join_existing_group;
+	int new_pin = wpas_p2p_connect(
+		wpa_s, peer_address.data(), pin, wps_method, persistent, auto_join,
+		join_existing_group, false, go_intent_signed, 0, 0, -1, false, ht40,
+		vht, CHANWIDTH_USE_HT, he, 0, nullptr, 0, is6GhzAllowed(wpa_s));
+	if (new_pin < 0) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	std::string pin_ret;
+	if (provision_method == WpsProvisionMethod::DISPLAY &&
+		pre_selected_pin.empty()) {
+		pin_ret = misc_utils::convertWpsPinToString(new_pin);
+	}
+	return {pin_ret, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus 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 createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::provisionDiscoveryInternal(
+	const std::vector<uint8_t>& peer_address,
+	WpsProvisionMethod provision_method)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	p2ps_provision* prov_param;
+	const char* config_method_str = nullptr;
+	switch (provision_method) {
+	case WpsProvisionMethod::PBC:
+		config_method_str = kConfigMethodStrPbc;
+		break;
+	case WpsProvisionMethod::DISPLAY:
+		config_method_str = kConfigMethodStrDisplay;
+		break;
+	case WpsProvisionMethod::KEYPAD:
+		config_method_str = kConfigMethodStrKeypad;
+		break;
+	}
+	if (wpas_p2p_prov_disc(
+		wpa_s, peer_address.data(), config_method_str,
+		WPAS_P2P_PD_FOR_GO_NEG, nullptr)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
+{
+	struct wpa_supplicant* wpa_group_s =
+		retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	wpa_group_s->global->p2p_go_found_external_scan = 0;
+	if (wpas_p2p_group_remove(wpa_group_s, group_ifname.c_str())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::rejectInternal(
+	const std::vector<uint8_t>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	if (wpas_p2p_reject(wpa_s, peer_address.data())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::inviteInternal(
+	const std::string& group_ifname,
+	const std::vector<uint8_t>& go_device_address,
+	const std::vector<uint8_t>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_invite_group(
+		wpa_s, group_ifname.c_str(), peer_address.data(),
+		go_device_address.data(), is6GhzAllowed(wpa_s))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::reinvokeInternal(
+	int32_t persistent_network_id,
+	const std::vector<uint8_t>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int he = wpa_s->conf->p2p_go_he;
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+	struct wpa_ssid* ssid =
+		wpa_config_get_network(wpa_s->conf, persistent_network_id);
+	if (ssid == NULL || ssid->disabled != 2) {
+		return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+	}
+	if (wpas_p2p_invite(
+		wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
+		CHANWIDTH_USE_HT, 0, he, 0, is6GhzAllowed(wpa_s))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::configureExtListenInternal(
+	uint32_t period_in_millis, uint32_t interval_in_millis)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_ext_listen(wpa_s, period_in_millis, interval_in_millis)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setListenChannelInternal(
+	uint32_t channel, uint32_t operating_class)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (p2p_set_listen_channel(
+		wpa_s->global->p2p, operating_class, channel, 1)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setDisallowedFrequenciesInternal(
+	const std::vector<FreqRange>& ranges)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	using DestT = struct wpa_freq_range_list::wpa_freq_range;
+	DestT* freq_ranges = nullptr;
+	// Empty ranges is used to enable all frequencies.
+	if (ranges.size() != 0) {
+		freq_ranges = static_cast<DestT*>(
+			os_malloc(sizeof(DestT) * ranges.size()));
+		if (!freq_ranges) {
+			return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+		}
+		uint32_t i = 0;
+		for (const auto& range : ranges) {
+			freq_ranges[i].min = range.min;
+			freq_ranges[i].max = range.max;
+			i++;
+		}
+	}
+
+	os_free(wpa_s->global->p2p_disallow_freq.range);
+	wpa_s->global->p2p_disallow_freq.range = freq_ranges;
+	wpa_s->global->p2p_disallow_freq.num = ranges.size();
+	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> P2pIface::getSsidInternal(
+	const std::vector<uint8_t>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	const struct p2p_peer_info* info =
+		p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
+	if (!info) {
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	const struct p2p_device* dev =
+		reinterpret_cast<const struct p2p_device*>(
+		(reinterpret_cast<const uint8_t*>(info)) -
+		offsetof(struct p2p_device, info));
+	std::vector<uint8_t> ssid;
+	if (dev && dev->oper_ssid_len) {
+		ssid.assign(
+			dev->oper_ssid, dev->oper_ssid + dev->oper_ssid_len);
+	}
+	return {ssid, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<P2pGroupCapabilityMask, ndk::ScopedAStatus> P2pIface::getGroupCapabilityInternal(
+	const std::vector<uint8_t>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	const struct p2p_peer_info* info =
+		p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
+	if (!info) {
+		return {static_cast<P2pGroupCapabilityMask>(0),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {static_cast<P2pGroupCapabilityMask>(info->group_capab),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::addBonjourServiceInternal(
+	const std::vector<uint8_t>& query, const std::vector<uint8_t>& response)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+	auto response_buf = misc_utils::convertVectorToWpaBuf(response);
+	if (!query_buf || !response_buf) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	if (wpas_p2p_service_add_bonjour(
+		wpa_s, query_buf.get(), response_buf.get())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	// If successful, the wpabuf is referenced internally and hence should
+	// not be freed.
+	query_buf.release();
+	response_buf.release();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::removeBonjourServiceInternal(
+	const std::vector<uint8_t>& query)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+	if (!query_buf) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	if (wpas_p2p_service_del_bonjour(wpa_s, query_buf.get())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::addUpnpServiceInternal(
+	uint32_t version, const std::string& service_name)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_service_add_upnp(wpa_s, version, service_name.c_str())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::removeUpnpServiceInternal(
+	uint32_t version, const std::string& service_name)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_service_del_upnp(wpa_s, version, service_name.c_str())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::flushServicesInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wpas_p2p_service_flush(wpa_s);
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<uint64_t, ndk::ScopedAStatus> P2pIface::requestServiceDiscoveryInternal(
+	const std::vector<uint8_t>& peer_address,
+	const std::vector<uint8_t>& query)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+	if (!query_buf) {
+		return {0, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	const uint8_t* dst_addr = is_zero_ether_addr(peer_address.data())
+					  ? nullptr
+					  : peer_address.data();
+	uint64_t identifier =
+		wpas_p2p_sd_request(wpa_s, dst_addr, query_buf.get());
+	if (identifier == 0) {
+		return {0, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {identifier, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setMiracastModeInternal(
+	MiracastMode mode)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	uint8_t mode_internal = convertAidlMiracastModeToInternal(mode);
+	const std::string cmd_str =
+		kSetMiracastMode + std::to_string(mode_internal);
+	std::vector<char> cmd(
+		cmd_str.c_str(), cmd_str.c_str() + cmd_str.size() + 1);
+	char driver_cmd_reply_buf[4096] = {};
+	if (wpa_drv_driver_cmd(
+		wpa_s, cmd.data(), driver_cmd_reply_buf,
+		sizeof(driver_cmd_reply_buf))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::startWpsPbcInternal(
+	const std::string& group_ifname, const std::vector<uint8_t>& bssid)
+{
+	struct wpa_supplicant* wpa_group_s =
+		retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	const uint8_t* bssid_addr =
+		is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+#ifdef CONFIG_AP
+	if (wpa_group_s->ap_iface) {
+		if (wpa_supplicant_ap_wps_pbc(wpa_group_s, bssid_addr, NULL)) {
+			return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+		}
+		return ndk::ScopedAStatus::ok();
+	}
+#endif /* CONFIG_AP */
+	if (wpas_wps_start_pbc(wpa_group_s, bssid_addr, 0, 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::startWpsPinKeypadInternal(
+	const std::string& group_ifname, const std::string& pin)
+{
+	struct wpa_supplicant* wpa_group_s =
+		retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+#ifdef CONFIG_AP
+	if (wpa_group_s->ap_iface) {
+		if (wpa_supplicant_ap_wps_pin(
+			wpa_group_s, nullptr, pin.c_str(), nullptr, 0, 0) < 0) {
+			return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+		}
+		return ndk::ScopedAStatus::ok();
+	}
+#endif /* CONFIG_AP */
+	if (wpas_wps_start_pin(
+		wpa_group_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::string, ndk::ScopedAStatus> P2pIface::startWpsPinDisplayInternal(
+	const std::string& group_ifname, const std::vector<uint8_t>& bssid)
+{
+	struct wpa_supplicant* wpa_group_s =
+		retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
+	}
+	const uint8_t* bssid_addr =
+		is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	int pin = wpas_wps_start_pin(
+		wpa_group_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
+	if (pin < 0) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::convertWpsPinToString(pin), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::cancelWpsInternal(const std::string& group_ifname)
+{
+	struct wpa_supplicant* wpa_group_s =
+		retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	if (wpas_wps_cancel(wpa_group_s)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setWpsDeviceNameInternal(const std::string& name)
+{
+	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsDeviceTypeInternal(
+	const std::vector<uint8_t>& type)
+{
+	std::array<uint8_t, 8> type_arr;
+	std::copy_n(type.begin(), 8, type_arr.begin());
+	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type_arr);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsManufacturerInternal(
+	const std::string& manufacturer)
+{
+	return iface_config_utils::setWpsManufacturer(
+		retrieveIfacePtr(), manufacturer);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsModelNameInternal(
+	const std::string& model_name)
+{
+	return iface_config_utils::setWpsModelName(
+		retrieveIfacePtr(), model_name);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsModelNumberInternal(
+	const std::string& model_number)
+{
+	return iface_config_utils::setWpsModelNumber(
+		retrieveIfacePtr(), model_number);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsSerialNumberInternal(
+	const std::string& serial_number)
+{
+	return iface_config_utils::setWpsSerialNumber(
+		retrieveIfacePtr(), serial_number);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsConfigMethodsInternal(WpsConfigMethods config_methods)
+{
+
+	return iface_config_utils::setWpsConfigMethods(
+		retrieveIfacePtr(), static_cast<uint16_t>(config_methods));
+}
+
+ndk::ScopedAStatus P2pIface::enableWfdInternal(bool enable)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wifi_display_enable(wpa_s->global, enable);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setWfdDeviceInfoInternal(
+	const std::vector<uint8_t>& info)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	std::vector<char> wfd_device_info_hex(info.size() * 2 + 1);
+	wpa_snprintf_hex(
+		wfd_device_info_hex.data(), wfd_device_info_hex.size(), info.data(),
+		info.size());
+	// |wifi_display_subelem_set| expects the first 2 bytes
+	// to hold the lenght of the subelement. In this case it's
+	// fixed to 6, so prepend that.
+	std::string wfd_device_info_set_cmd_str =
+		std::to_string(kWfdDeviceInfoSubelemId) + " " +
+		kWfdDeviceInfoSubelemLenHexStr + wfd_device_info_hex.data();
+	std::vector<char> wfd_device_info_set_cmd(
+		wfd_device_info_set_cmd_str.c_str(),
+		wfd_device_info_set_cmd_str.c_str() +
+		wfd_device_info_set_cmd_str.size() + 1);
+	if (wifi_display_subelem_set(
+		wpa_s->global, wfd_device_info_set_cmd.data())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+P2pIface::createNfcHandoverRequestMessageInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto buf = misc_utils::createWpaBufUniquePtr(
+		wpas_p2p_nfc_handover_req(wpa_s, 1));
+	if (!buf) {
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::convertWpaBufToVector(buf.get()),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+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 {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::convertWpaBufToVector(buf.get()),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus 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 createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	if (wpas_p2p_nfc_report_handover(wpa_s, 0, req.get(), sel.get(), 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus 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 createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	if (wpas_p2p_nfc_report_handover(wpa_s, 1, req.get(), sel.get(), 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::saveConfigInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (!wpa_s->conf->update_config) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::addGroupInternal(
+	bool persistent, int32_t persistent_network_id)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int he = wpa_s->conf->p2p_go_he;
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+	struct wpa_ssid* ssid =
+		wpa_config_get_network(wpa_s->conf, persistent_network_id);
+	if (ssid == NULL) {
+		if (wpas_p2p_group_add(
+			wpa_s, persistent, 0, 0, ht40, vht,
+			CHANWIDTH_USE_HT, he, 0, is6GhzAllowed(wpa_s))) {
+			return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+		} else {
+			return ndk::ScopedAStatus::ok();
+		}
+	} else if (ssid->disabled == 2) {
+		if (wpas_p2p_group_add_persistent(
+			wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
+			CHANWIDTH_USE_HT, he, 0, NULL, 0, 0, is6GhzAllowed(wpa_s))) {
+			return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+		} else {
+			return ndk::ScopedAStatus::ok();
+		}
+	}
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+
+ndk::ScopedAStatus P2pIface::addGroupWithConfigInternal(
+	const std::vector<uint8_t>& ssid, const std::string& passphrase,
+	bool persistent, uint32_t freq, const std::vector<uint8_t>& peer_address,
+	bool joinExistingGroup)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int he = wpa_s->conf->p2p_go_he;
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+
+	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+
+	if (!isSsidValid(ssid)) {
+		return createStatusWithMsg(SupplicantStatusCode::FAILURE_ARGS_INVALID,
+			"SSID is invalid.");
+	}
+
+	if (!isPskPassphraseValid(passphrase)) {
+		return createStatusWithMsg(SupplicantStatusCode::FAILURE_ARGS_INVALID,
+			"Passphrase is invalid.");
+	}
+
+	if (!joinExistingGroup) {
+		struct p2p_data *p2p = wpa_s->global->p2p;
+		os_memcpy(p2p->ssid, ssid.data(), ssid.size());
+		p2p->ssid_len = ssid.size();
+		p2p->ssid_set = 1;
+
+		os_memset(p2p->passphrase, 0, sizeof(p2p->passphrase));
+		os_memcpy(p2p->passphrase, passphrase.c_str(), passphrase.length());
+		p2p->passphrase_set = 1;
+
+		if (wpas_p2p_group_add(
+			wpa_s, persistent, freq, 0, ht40, vht,
+			CHANWIDTH_USE_HT, he, 0, is6GhzAllowed(wpa_s))) {
+			return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+		}
+		return ndk::ScopedAStatus::ok();
+	}
+
+	// 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);
+
+	if (pending_scan_res_join_callback != NULL) {
+		wpa_printf(MSG_WARNING, "P2P: Renew scan result callback with new request.");
+	}
+
+	pending_join_scan_callback =
+		[wpa_s, ssid, peer_address, freq]() {
+		if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+			return;
+		}
+		int operating_freq = 0;
+		struct wpa_bss *bss = findBssBySsidFromAnyInterface(
+			wpa_s->global->ifaces, peer_address.data(), ssid.data(), ssid.size());
+		if (bss != NULL) {
+			wpa_printf(MSG_DEBUG, "P2P: Found Group owner " MACSTR "in scan cache",
+				MAC2STR(bss->bssid));
+			operating_freq = bss->freq;
+		}
+
+		int ret = joinScanReq(wpa_s, ssid, freq, operating_freq);
+		// for BUSY case, the scan might be occupied by WiFi.
+		// Do not give up immediately, but try again later.
+		if (-EBUSY == ret) {
+			// re-schedule this join scan
+			eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
+			eloop_register_timeout(0, P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS,
+					joinScanWrapper, wpa_s, NULL);
+		} else if (0 != ret) {
+			notifyGroupJoinFailure(wpa_s);
+			pending_scan_res_join_callback = NULL;
+		}
+	};
+
+	pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, freq, this]() {
+		if (wpa_s->global->p2p == NULL || 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) {
+			wpa_s->global->p2p_go_found_external_scan = 1;
+			if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
+				wpa_printf(MSG_ERROR, "P2P: Failed to join a group.");
+				wpa_s->global->p2p_go_found_external_scan = 0;
+			}
+			// 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_printf(MSG_DEBUG, "P2P: Join scan count %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(0, getP2pJoinScanIntervalUsecs(freq),
+				joinScanWrapper, wpa_s, this);
+			return;
+		}
+
+		wpa_printf(MSG_ERROR, "P2P: Failed to find the group with "
+			"network name %s - stop join attempt",
+			wpa_ssid_txt(ssid.data(), ssid.size()));
+		notifyGroupJoinFailure(wpa_s);
+		pending_scan_res_join_callback = NULL;
+	};
+
+	wpa_s->p2p_join_scan_count = 0;
+	pending_join_scan_callback();
+	if (pending_scan_res_join_callback == NULL) {
+		return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+			"Failed to start scan.");
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setMacRandomizationInternal(bool enable)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	bool currentEnabledState = !!wpa_s->conf->p2p_device_random_mac_addr;
+	u8 *addr = NULL;
+
+	// The same state, no change is needed.
+	if (currentEnabledState == enable) {
+		wpa_printf(MSG_DEBUG, "The random MAC is %s already.",
+			(enable) ? "enabled" : "disabled");
+		return ndk::ScopedAStatus::ok();
+	}
+
+	if (enable) {
+		wpa_s->conf->p2p_device_random_mac_addr = 1;
+		wpa_s->conf->p2p_interface_random_mac_addr = 1;
+
+		// restore config if it failed to set up MAC address.
+		if (wpas_p2p_mac_setup(wpa_s) < 0) {
+			wpa_s->conf->p2p_device_random_mac_addr = 0;
+			wpa_s->conf->p2p_interface_random_mac_addr = 0;
+			return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+				"Failed to set up MAC address.");
+		}
+	} else {
+		// disable random MAC will use original MAC address
+		// regardless of any saved persistent groups.
+		if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
+			wpa_printf(MSG_ERROR, "Failed to restore MAC address");
+			return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+				"Failed to restore MAC address.");
+		}
+
+		if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+			wpa_printf(MSG_INFO, "Could not update MAC address information");
+			return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+				"Failed to update MAC address.");
+		}
+		wpa_s->conf->p2p_device_random_mac_addr = 0;
+		wpa_s->conf->p2p_interface_random_mac_addr = 0;
+	}
+
+	// update internal data to send out correct device address in action frame.
+	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
+	os_memcpy(wpa_s->global->p2p->cfg->dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
+
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setEdmgInternal(bool enable)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wpa_printf(MSG_DEBUG, "set p2p_go_edmg to %d", enable);
+	wpa_s->conf->p2p_go_edmg = enable ? 1 : 0;
+	wpa_s->p2p_go_edmg = enable ? 1 : 0;
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pIface::getEdmgInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	return {(wpa_s->p2p_go_edmg == 1), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::setWfdR2DeviceInfoInternal(
+	const std::vector<uint8_t>& info)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	uint32_t wfd_r2_device_info_hex_len = info.size() * 2 + 1;
+	std::vector<char> wfd_r2_device_info_hex(wfd_r2_device_info_hex_len);
+	wpa_snprintf_hex(
+		wfd_r2_device_info_hex.data(), wfd_r2_device_info_hex.size(),
+		info.data(),info.size());
+	std::string wfd_r2_device_info_set_cmd_str =
+		 std::to_string(kWfdR2DeviceInfoSubelemId) + " " +
+		 wfd_r2_device_info_hex.data();
+	std::vector<char> wfd_r2_device_info_set_cmd(
+		 wfd_r2_device_info_set_cmd_str.c_str(),
+		 wfd_r2_device_info_set_cmd_str.c_str() +
+		 wfd_r2_device_info_set_cmd_str.size() + 1);
+	if (wifi_display_subelem_set(
+		wpa_s->global, wfd_r2_device_info_set_cmd.data())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::removeClientInternal(
+    const std::vector<uint8_t>& peer_address, bool isLegacyClient)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wpas_p2p_remove_client(wpa_s, peer_address.data(), isLegacyClient? 1 : 0);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::findOnSocialChannelsInternal(uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
+	if (wpas_p2p_find(
+		wpa_s, timeout_in_sec, P2P_FIND_ONLY_SOCIAL, 0, nullptr,
+		nullptr, search_delay, 0, nullptr, 0, is6GhzAllowed(wpa_s))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::findOnSpecificFrequencyInternal(
+	uint32_t freq, uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
+	if (wpas_p2p_find(
+		wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
+		nullptr, search_delay, 0, nullptr, freq, is6GhzAllowed(wpa_s))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setVendorElementsInternal(
+	P2pFrameTypeMask frameTypeMask,
+	const std::vector<uint8_t>& vendorElemBytes)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	for (int i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
+		uint32_t bit = convertWpaP2pFrameTypeToHalP2pFrameTypeBit(i);
+		if (0 == bit) continue;
+
+		if (static_cast<uint32_t>(frameTypeMask) & bit) {
+			updateP2pVendorElem(wpa_s, (enum wpa_vendor_elem_frame) i, vendorElemBytes);
+		}
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this iface.
+ * If the underlying iface is removed, then all RPC method calls on this object
+ * will return failure.
+ */
+wpa_supplicant* P2pIface::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this group iface.
+ */
+wpa_supplicant* P2pIface::retrieveGroupIfacePtr(const std::string& group_ifname)
+{
+	return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
+}
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/wpa_supplicant/aidl/p2p_iface.h b/wpa_supplicant/aidl/p2p_iface.h
new file mode 100644
index 0000000..5f9903c
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_iface.h
@@ -0,0 +1,316 @@
+/*
+ * WPA Supplicant - P2P Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_P2P_IFACE_H
+#define WPA_SUPPLICANT_AIDL_P2P_IFACE_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantP2pIface.h>
+#include <aidl/android/hardware/wifi/supplicant/FreqRange.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.h>
+#include <aidl/android/hardware/wifi/supplicant/MiracastMode.h>
+#include <aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "p2p/p2p.h"
+#include "p2p/p2p_i.h"
+#include "p2p_supplicant.h"
+#include "p2p_supplicant.h"
+#include "config.h"
+}
+
+#define P2P_MGMT_DEVICE_PREFIX	   "p2p-dev-"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of P2pIface aidl object. Each unique aidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class P2pIface : public BnSupplicantP2pIface
+{
+public:
+	P2pIface(struct wpa_global* wpa_global, const char ifname[]);
+	~P2pIface() override = default;
+	// Refer to |StaIface::invalidate()|.
+	void invalidate();
+	bool isValid();
+
+	// Aidl methods exposed.
+	::ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+	::ndk::ScopedAStatus addNetwork(
+		std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return) override;
+	::ndk::ScopedAStatus removeNetwork(int32_t in_id) override;
+	::ndk::ScopedAStatus getNetwork(
+		int32_t in_id, std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return) override;
+	::ndk::ScopedAStatus listNetworks(std::vector<int32_t>* _aidl_return) override;
+	::ndk::ScopedAStatus registerCallback(
+		const std::shared_ptr<ISupplicantP2pIfaceCallback>& in_callback) override;
+	::ndk::ScopedAStatus getDeviceAddress(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus setSsidPostfix(const std::vector<uint8_t>& in_postfix) override;
+	::ndk::ScopedAStatus setGroupIdle(
+		const std::string& in_groupIfName, int32_t in_timeoutInSec) override;
+	::ndk::ScopedAStatus setPowerSave(
+		const std::string& in_groupIfName, bool in_enable) override;
+	::ndk::ScopedAStatus find(int32_t in_timeoutInSec) override;
+	::ndk::ScopedAStatus stopFind() override;
+	::ndk::ScopedAStatus flush() override;
+	::ndk::ScopedAStatus connect(
+		const std::vector<uint8_t>& in_peerAddress, WpsProvisionMethod in_provisionMethod,
+		const std::string& in_preSelectedPin, bool in_joinExistingGroup,
+		bool in_persistent, int32_t in_goIntent, std::string* _aidl_return) override;
+	::ndk::ScopedAStatus cancelConnect() override;
+	::ndk::ScopedAStatus provisionDiscovery(
+		const std::vector<uint8_t>& in_peerAddress,
+		WpsProvisionMethod in_provisionMethod) override;
+	::ndk::ScopedAStatus addGroup(bool in_persistent, int32_t in_persistentNetworkId) override;
+	::ndk::ScopedAStatus addGroupWithConfig(
+		const std::vector<uint8_t>& in_ssid, const std::string& in_pskPassphrase,
+		bool in_persistent, int32_t in_freq, const std::vector<uint8_t>& in_peerAddress,
+		bool in_joinExistingGroup) override;
+	::ndk::ScopedAStatus removeGroup(const std::string& in_groupIfName) override;
+	::ndk::ScopedAStatus reject(const std::vector<uint8_t>& in_peerAddress) override;
+	::ndk::ScopedAStatus invite(
+		const std::string& in_groupIfName,
+		const std::vector<uint8_t>& in_goDeviceAddress,
+		const std::vector<uint8_t>& in_peerAddress) override;
+	::ndk::ScopedAStatus reinvoke(
+		int32_t in_persistentNetworkId,
+		const std::vector<uint8_t>& in_peerAddress) override;
+	::ndk::ScopedAStatus configureExtListen(
+		int32_t in_periodInMillis, int32_t in_intervalInMillis) override;
+	::ndk::ScopedAStatus setListenChannel(
+		int32_t in_channel, int32_t in_operatingClass) override;
+	::ndk::ScopedAStatus setDisallowedFrequencies(
+		const std::vector<FreqRange>& in_ranges) override;
+	::ndk::ScopedAStatus getSsid(
+		const std::vector<uint8_t>& in_peerAddress,
+		std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getGroupCapability(
+		const std::vector<uint8_t>& in_peerAddress,
+		P2pGroupCapabilityMask* _aidl_return) override;
+	::ndk::ScopedAStatus addBonjourService(
+		const std::vector<uint8_t>& in_query,
+		const std::vector<uint8_t>& in_response) override;
+	::ndk::ScopedAStatus removeBonjourService(
+		const std::vector<uint8_t>& in_query) override;
+	::ndk::ScopedAStatus addUpnpService(
+		int32_t in_version, const std::string& in_serviceName) override;
+	::ndk::ScopedAStatus removeUpnpService(
+		int32_t in_version, const std::string& in_serviceName) override;
+	::ndk::ScopedAStatus flushServices() override;
+	::ndk::ScopedAStatus requestServiceDiscovery(
+		const std::vector<uint8_t>& in_peerAddress,
+		const std::vector<uint8_t>& in_query, int64_t* _aidl_return) override;
+	::ndk::ScopedAStatus cancelServiceDiscovery(int64_t in_identifier) override;
+	::ndk::ScopedAStatus setMiracastMode(MiracastMode in_mode) override;
+	::ndk::ScopedAStatus startWpsPbc(
+		const std::string& in_groupIfName,
+		const std::vector<uint8_t>& in_bssid) override;
+	::ndk::ScopedAStatus startWpsPinKeypad(
+		const std::string& in_groupIfName, const std::string& in_pin) override;
+	::ndk::ScopedAStatus startWpsPinDisplay(
+		const std::string& in_groupIfName,
+		const std::vector<uint8_t>& in_bssid,
+		std::string* _aidl_return) override;
+	::ndk::ScopedAStatus cancelWps(const std::string& in_groupIfName) override;
+	::ndk::ScopedAStatus setWpsDeviceName(
+		const std::string& in_name) override;
+	::ndk::ScopedAStatus setWpsDeviceType(
+		const std::vector<uint8_t>& in_type) override;
+	::ndk::ScopedAStatus setWpsManufacturer(
+		const std::string& in_manufacturer) override;
+	::ndk::ScopedAStatus setWpsModelName(
+		const std::string& in_modelName) override;
+	::ndk::ScopedAStatus setWpsModelNumber(
+		const std::string& in_modelNumber) override;
+	::ndk::ScopedAStatus setWpsSerialNumber(
+		const std::string& in_serialNumber) override;
+	::ndk::ScopedAStatus setWpsConfigMethods(
+		WpsConfigMethods in_configMethods) override;
+	::ndk::ScopedAStatus enableWfd(bool in_enable) override;
+	::ndk::ScopedAStatus setWfdDeviceInfo(
+		const std::vector<uint8_t>& in_info) override;
+	::ndk::ScopedAStatus createNfcHandoverRequestMessage(
+		std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus createNfcHandoverSelectMessage(
+		std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus reportNfcHandoverInitiation(
+		const std::vector<uint8_t>& in_select) override;
+	::ndk::ScopedAStatus reportNfcHandoverResponse(
+		const std::vector<uint8_t>& in_request) override;
+	::ndk::ScopedAStatus saveConfig() override;
+	::ndk::ScopedAStatus setMacRandomization(bool in_enable) override;
+	::ndk::ScopedAStatus setEdmg(bool in_enable) override;
+	::ndk::ScopedAStatus getEdmg(bool* _aidl_return) override;
+	::ndk::ScopedAStatus setWfdR2DeviceInfo(
+		const std::vector<uint8_t>& in_info) override;
+	::ndk::ScopedAStatus removeClient(
+		const std::vector<uint8_t>& peer_address, bool isLegacyClient) override;
+	::ndk::ScopedAStatus findOnSocialChannels(int32_t in_timeoutInSec) override;
+	::ndk::ScopedAStatus findOnSpecificFrequency(
+		int32_t in_freq, int32_t in_timeoutInSec) override;
+	::ndk::ScopedAStatus setVendorElements(
+		P2pFrameTypeMask in_frameTypeMask,
+		const std::vector<uint8_t>& in_vendorElemBytes) override;
+
+private:
+	// Corresponding worker functions for the AIDL methods.
+	std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+	std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+	std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+		addNetworkInternal();
+	ndk::ScopedAStatus removeNetworkInternal(int32_t id);
+	std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+		getNetworkInternal(int32_t id);
+	std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+		listNetworksInternal();
+	ndk::ScopedAStatus registerCallbackInternal(
+		const std::shared_ptr<ISupplicantP2pIfaceCallback>& callback);
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		getDeviceAddressInternal();
+	ndk::ScopedAStatus setSsidPostfixInternal(
+		const std::vector<uint8_t>& postfix);
+	ndk::ScopedAStatus setGroupIdleInternal(
+		const std::string& group_ifname, uint32_t timeout_in_sec);
+	ndk::ScopedAStatus setPowerSaveInternal(
+		const std::string& group_ifname, bool enable);
+	ndk::ScopedAStatus findInternal(uint32_t timeout_in_sec);
+	ndk::ScopedAStatus stopFindInternal();
+	ndk::ScopedAStatus flushInternal();
+	std::pair<std::string, ndk::ScopedAStatus> connectInternal(
+		const std::vector<uint8_t>& peer_address,
+		WpsProvisionMethod provision_method,
+		const std::string& pre_selected_pin, bool join_existing_group,
+		bool persistent, uint32_t go_intent);
+	ndk::ScopedAStatus cancelConnectInternal();
+	ndk::ScopedAStatus provisionDiscoveryInternal(
+		const std::vector<uint8_t>& peer_address,
+		WpsProvisionMethod provision_method);
+	ndk::ScopedAStatus addGroupInternal(bool in_persistent, int32_t in_persistentNetworkId);
+	ndk::ScopedAStatus addGroupWithConfigInternal(
+		const std::vector<uint8_t>& ssid, const std::string& passphrase,
+		bool persistent, uint32_t freq, const std::vector<uint8_t>& peer_address,
+		bool joinExistingGroup);
+	ndk::ScopedAStatus removeGroupInternal(const std::string& group_ifname);
+	ndk::ScopedAStatus rejectInternal(
+		const std::vector<uint8_t>& peer_address);
+	ndk::ScopedAStatus inviteInternal(
+		const std::string& group_ifname,
+		const std::vector<uint8_t>& go_device_address,
+		const std::vector<uint8_t>& peer_address);
+	ndk::ScopedAStatus reinvokeInternal(
+		int32_t persistent_network_id,
+		const std::vector<uint8_t>& peer_address);
+	ndk::ScopedAStatus configureExtListenInternal(
+		uint32_t period_in_millis, uint32_t interval_in_millis);
+	ndk::ScopedAStatus setListenChannelInternal(
+		uint32_t channel, uint32_t operating_class);
+	ndk::ScopedAStatus setDisallowedFrequenciesInternal(
+		const std::vector<FreqRange>& ranges);
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getSsidInternal(
+		const std::vector<uint8_t>& peer_address);
+	std::pair<P2pGroupCapabilityMask, ndk::ScopedAStatus> getGroupCapabilityInternal(
+		const std::vector<uint8_t>& peer_address);
+	ndk::ScopedAStatus addBonjourServiceInternal(
+		const std::vector<uint8_t>& query,
+		const std::vector<uint8_t>& response);
+	ndk::ScopedAStatus removeBonjourServiceInternal(
+		const std::vector<uint8_t>& query);
+	ndk::ScopedAStatus addUpnpServiceInternal(
+		uint32_t version, const std::string& service_name);
+	ndk::ScopedAStatus removeUpnpServiceInternal(
+		uint32_t version, const std::string& service_name);
+	ndk::ScopedAStatus flushServicesInternal();
+	std::pair<uint64_t, ndk::ScopedAStatus> requestServiceDiscoveryInternal(
+		const std::vector<uint8_t>& peer_address,
+		const std::vector<uint8_t>& query);
+	ndk::ScopedAStatus cancelServiceDiscoveryInternal(uint64_t identifier);
+	ndk::ScopedAStatus setMiracastModeInternal(
+		MiracastMode mode);
+	ndk::ScopedAStatus startWpsPbcInternal(
+		const std::string& group_ifname,
+		const std::vector<uint8_t>& bssid);
+	ndk::ScopedAStatus startWpsPinKeypadInternal(
+		const std::string& group_ifname, const std::string& pin);
+	std::pair<std::string, ndk::ScopedAStatus> startWpsPinDisplayInternal(
+		const std::string& group_ifname,
+		const std::vector<uint8_t>& bssid);
+	ndk::ScopedAStatus cancelWpsInternal(const std::string& group_ifname);
+	ndk::ScopedAStatus setWpsDeviceNameInternal(const std::string& name);
+	ndk::ScopedAStatus setWpsDeviceTypeInternal(
+		const std::vector<uint8_t>& type);
+	ndk::ScopedAStatus setWpsManufacturerInternal(
+		const std::string& manufacturer);
+	ndk::ScopedAStatus setWpsModelNameInternal(const std::string& model_name);
+	ndk::ScopedAStatus setWpsModelNumberInternal(
+		const std::string& model_number);
+	ndk::ScopedAStatus setWpsSerialNumberInternal(
+		const std::string& serial_number);
+	ndk::ScopedAStatus setWpsConfigMethodsInternal(WpsConfigMethods config_methods);
+	ndk::ScopedAStatus enableWfdInternal(bool enable);
+	ndk::ScopedAStatus setWfdDeviceInfoInternal(
+		const std::vector<uint8_t>& info);
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		createNfcHandoverRequestMessageInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		createNfcHandoverSelectMessageInternal();
+	ndk::ScopedAStatus reportNfcHandoverResponseInternal(
+		const std::vector<uint8_t>& request);
+	ndk::ScopedAStatus reportNfcHandoverInitiationInternal(
+		const std::vector<uint8_t>& select);
+	ndk::ScopedAStatus saveConfigInternal();
+	ndk::ScopedAStatus setMacRandomizationInternal(bool enable);
+	ndk::ScopedAStatus setEdmgInternal(bool enable);
+	std::pair<bool, ndk::ScopedAStatus> getEdmgInternal();
+	ndk::ScopedAStatus setWfdR2DeviceInfoInternal(
+		const std::vector<uint8_t>& info);
+	ndk::ScopedAStatus removeClientInternal(
+		const std::vector<uint8_t>& peer_address, bool isLegacyClient);
+	ndk::ScopedAStatus findOnSocialChannelsInternal(uint32_t timeout_in_sec);
+	ndk::ScopedAStatus findOnSpecificFrequencyInternal(
+		uint32_t freq, uint32_t timeout_in_sec);
+	ndk::ScopedAStatus setVendorElementsInternal(
+		P2pFrameTypeMask frameTypeMask,
+		const std::vector<uint8_t>& vendorElemBytes);
+
+	struct wpa_supplicant* retrieveIfacePtr();
+	struct wpa_supplicant* retrieveGroupIfacePtr(
+		const std::string& group_ifname);
+
+	// Reference to the global wpa_struct. This is assumed to be valid for
+	// the lifetime of the process.
+	struct wpa_global* wpa_global_;
+	// Name of the iface this aidl object controls
+	const std::string ifname_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(P2pIface);
+};
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // WPA_SUPPLICANT_AIDL_P2P_IFACE_H
diff --git a/wpa_supplicant/aidl/p2p_network.cpp b/wpa_supplicant/aidl/p2p_network.cpp
new file mode 100644
index 0000000..9288382
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_network.cpp
@@ -0,0 +1,252 @@
+/*
+ * WPA Supplicant - P2P network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "misc_utils.h"
+#include "p2p_network.h"
+
+extern "C"
+{
+#include "config_ssid.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+
+P2pNetwork::P2pNetwork(
+	struct wpa_global *wpa_global, const char ifname[], int network_id)
+	: wpa_global_(wpa_global),
+	  ifname_(ifname),
+	  network_id_(network_id),
+	  is_valid_(true)
+{}
+
+void P2pNetwork::invalidate() { is_valid_ = false; }
+bool P2pNetwork::isValid()
+{
+	return (is_valid_ && (retrieveNetworkPtr() != nullptr));
+}
+
+::ndk::ScopedAStatus P2pNetwork::getId(
+	int32_t* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::getIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getInterfaceName(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::getInterfaceNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getType(
+	IfaceType* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getSsid(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::getSsidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getBssid(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::getBssidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::isCurrent(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::isCurrentInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::isPersistent(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::isPersistentInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::isGroupOwner(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::isGroupOwnerInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::setClientList(
+	const std::vector<MacAddress>& in_clients)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::setClientListInternal, in_clients);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getClientList(
+	std::vector<MacAddress>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&P2pNetwork::getClientListInternal, _aidl_return);
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> P2pNetwork::getIdInternal()
+{
+	return {network_id_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> P2pNetwork::getInterfaceNameInternal()
+{
+	return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> P2pNetwork::getTypeInternal()
+{
+	return {IfaceType::P2P, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> P2pNetwork::getSsidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::vector<uint8_t> ssid(
+		wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len);
+	return {ssid, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+P2pNetwork::getBssidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::vector<uint8_t> bssid;
+	if (wpa_ssid->bssid_set) {
+		bssid.assign(wpa_ssid->bssid, wpa_ssid->bssid + ETH_ALEN);
+	}
+	return {bssid, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pNetwork::isCurrentInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {(wpa_s->current_ssid == wpa_ssid),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pNetwork::isPersistentInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {(wpa_ssid->disabled == 2), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pNetwork::isGroupOwnerInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {(wpa_ssid->mode == wpas_mode::WPAS_MODE_P2P_GO),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pNetwork::setClientListInternal(
+	const std::vector<MacAddress> &clients)
+{
+	for (const auto &client : clients) {
+		if (client.data.size() != ETH_ALEN) {
+			return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+		}
+	}
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	os_free(wpa_ssid->p2p_client_list);
+	// Internal representation uses a generic MAC addr/mask storage format
+	// (even though the mask is always 0xFF'ed for p2p_client_list). So, the
+	// first 6 bytes holds the client MAC address and the next 6 bytes are
+	// OxFF'ed.
+	wpa_ssid->p2p_client_list =
+		(u8 *)os_malloc(ETH_ALEN * 2 * clients.size());
+	if (!wpa_ssid->p2p_client_list) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	u8 *list = wpa_ssid->p2p_client_list;
+	for (const auto &client : clients) {
+		os_memcpy(list, client.data.data(), ETH_ALEN);
+		list += ETH_ALEN;
+		os_memset(list, 0xFF, ETH_ALEN);
+		list += ETH_ALEN;
+	}
+	wpa_ssid->num_p2p_clients = clients.size();
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<MacAddress>, ndk::ScopedAStatus>
+P2pNetwork::getClientListInternal()
+{
+	std::vector<MacAddress> clients;
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->p2p_client_list) {
+		return {clients, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	u8 *list = wpa_ssid->p2p_client_list;
+	for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) {
+		MacAddress client = MacAddress{};
+		client.data = std::vector<uint8_t>(list, list + ETH_ALEN);
+		clients.emplace_back(client);
+		list += 2 * ETH_ALEN;
+	}
+	return {clients, ndk::ScopedAStatus::ok()};
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface
+ * this network belong to is removed, all RPC method calls
+ * on this object will return failure.
+ */
+struct wpa_ssid *P2pNetwork::retrieveNetworkPtr()
+{
+	wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (!wpa_s)
+		return nullptr;
+	return wpa_config_get_network(wpa_s->conf, network_id_);
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this network.
+ */
+struct wpa_supplicant *P2pNetwork::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(
+		(struct wpa_global *)wpa_global_, ifname_.c_str());
+}
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/wpa_supplicant/aidl/p2p_network.h b/wpa_supplicant/aidl/p2p_network.h
new file mode 100644
index 0000000..3b7ec5a
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_network.h
@@ -0,0 +1,94 @@
+/*
+ * WPA Supplicant - P2P network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_P2P_NETWORK_H
+#define WPA_SUPPLICANT_AIDL_P2P_NETWORK_H
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantP2pNetwork.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of P2pNetwork aidl object. Each unique aidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class P2pNetwork : public BnSupplicantP2pNetwork
+{
+public:
+	P2pNetwork(
+		struct wpa_global* wpa_global, const char ifname[], int network_id);
+	~P2pNetwork() override = default;
+	// Refer to |StaIface::invalidate()|.
+	void invalidate();
+	bool isValid();
+
+	// Aidl methods exposed.
+  	::ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
+	::ndk::ScopedAStatus getInterfaceName(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+	::ndk::ScopedAStatus getSsid(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getBssid(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus isCurrent(bool* _aidl_return) override;
+	::ndk::ScopedAStatus isPersistent(bool* _aidl_return) override;
+	::ndk::ScopedAStatus isGroupOwner(bool* _aidl_return) override;
+	::ndk::ScopedAStatus setClientList(
+		const std::vector<MacAddress>& in_clients) override;
+	::ndk::ScopedAStatus getClientList(
+		std::vector<MacAddress>* _aidl_return) override;
+
+private:
+	// Corresponding worker functions for the AIDL methods.
+	std::pair<uint32_t, ndk::ScopedAStatus> getIdInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getInterfaceNameInternal();
+	std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getSsidInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getBssidInternal();
+	std::pair<bool, ndk::ScopedAStatus> isCurrentInternal();
+	std::pair<bool, ndk::ScopedAStatus> isPersistentInternal();
+	std::pair<bool, ndk::ScopedAStatus> isGroupOwnerInternal();
+	ndk::ScopedAStatus setClientListInternal(
+		const std::vector<MacAddress>& clients);
+	std::pair<std::vector<MacAddress>, ndk::ScopedAStatus>
+		getClientListInternal();
+
+	struct wpa_ssid* retrieveNetworkPtr();
+	struct wpa_supplicant* retrieveIfacePtr();
+
+	// Reference to the global wpa_struct. This is assumed to be valid
+	// for the lifetime of the process.
+	const struct wpa_global* wpa_global_;
+	// Name of the iface this network belongs to.
+	const std::string ifname_;
+	// Id of the network this aidl object controls.
+	const int network_id_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(P2pNetwork);
+};
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // WPA_SUPPLICANT_AIDL_P2P_NETWORK_H
diff --git a/wpa_supplicant/aidl/sta_iface.cpp b/wpa_supplicant/aidl/sta_iface.cpp
new file mode 100644
index 0000000..7a07cc1
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_iface.cpp
@@ -0,0 +1,1951 @@
+/*
+ * WPA Supplicant - Sta Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+#include "sta_iface.h"
+
+extern "C"
+{
+#include "utils/eloop.h"
+#include "gas_query.h"
+#include "interworking.h"
+#include "hs20_supplicant.h"
+#include "wps_supplicant.h"
+#include "dpp.h"
+#include "dpp_supplicant.h"
+#include "rsn_supp/wpa.h"
+#include "rsn_supp/pmksa_cache.h"
+}
+
+namespace {
+using aidl::android::hardware::wifi::supplicant::AidlManager;
+using aidl::android::hardware::wifi::supplicant::BtCoexistenceMode;
+using aidl::android::hardware::wifi::supplicant::ConnectionCapabilities;
+using aidl::android::hardware::wifi::supplicant::DppCurve;
+using aidl::android::hardware::wifi::supplicant::DppResponderBootstrapInfo;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::LegacyMode;
+using aidl::android::hardware::wifi::supplicant::RxFilterType;
+using aidl::android::hardware::wifi::supplicant::SupplicantStatusCode;
+using aidl::android::hardware::wifi::supplicant::WifiTechnology;
+using aidl::android::hardware::wifi::supplicant::misc_utils::createStatus;
+
+// TODO (b/204810426): Import from wifi vendor AIDL interface when it exists
+enum WifiChannelWidthInMhz {
+  WIDTH_20	= 0,
+  WIDTH_40	= 1,
+  WIDTH_80	= 2,
+  WIDTH_160   = 3,
+  WIDTH_80P80 = 4,
+  WIDTH_5	 = 5,
+  WIDTH_10	= 6,
+  WIDTH_INVALID = -1
+};
+
+constexpr uint32_t kMaxAnqpElems = 100;
+constexpr char kGetMacAddress[] = "MACADDR";
+constexpr char kStartRxFilter[] = "RXFILTER-START";
+constexpr char kStopRxFilter[] = "RXFILTER-STOP";
+constexpr char kAddRxFilter[] = "RXFILTER-ADD";
+constexpr char kRemoveRxFilter[] = "RXFILTER-REMOVE";
+constexpr char kSetBtCoexistenceMode[] = "BTCOEXMODE";
+constexpr char kSetBtCoexistenceScanStart[] = "BTCOEXSCAN-START";
+constexpr char kSetBtCoexistenceScanStop[] = "BTCOEXSCAN-STOP";
+constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
+constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
+constexpr char kSetCountryCode[] = "COUNTRY";
+constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec =
+	static_cast<uint32_t>(ISupplicant::EXT_RADIO_WORK_TIMEOUT_IN_SECS);
+constexpr char kExtRadioWorkNamePrefix[] = "ext:";
+
+uint8_t convertAidlRxFilterTypeToInternal(
+	RxFilterType type)
+{
+	switch (type) {
+	case RxFilterType::V4_MULTICAST:
+		return 2;
+	case RxFilterType::V6_MULTICAST:
+		return 3;
+	};
+	WPA_ASSERT(false);
+}
+
+uint8_t convertAidlBtCoexModeToInternal(
+	BtCoexistenceMode mode)
+{
+	switch (mode) {
+	case BtCoexistenceMode::ENABLED:
+		return 0;
+	case BtCoexistenceMode::DISABLED:
+		return 1;
+	case BtCoexistenceMode::SENSE:
+		return 2;
+	};
+	WPA_ASSERT(false);
+}
+
+ndk::ScopedAStatus doZeroArgDriverCommand(
+	struct wpa_supplicant *wpa_s, const char *cmd)
+{
+	std::vector<char> cmd_vec(cmd, cmd + strlen(cmd) + 1);
+	char driver_cmd_reply_buf[4096] = {};
+	if (wpa_drv_driver_cmd(
+		wpa_s, cmd_vec.data(), driver_cmd_reply_buf,
+		sizeof(driver_cmd_reply_buf))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus doOneArgDriverCommand(
+	struct wpa_supplicant *wpa_s, const char *cmd, uint8_t arg)
+{
+	std::string cmd_str = std::string(cmd) + " " + std::to_string(arg);
+	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
+}
+
+ndk::ScopedAStatus doOneArgDriverCommand(
+	struct wpa_supplicant *wpa_s, const char *cmd, const std::string &arg)
+{
+	std::string cmd_str = std::string(cmd) + " " + arg;
+	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
+}
+
+void endExtRadioWork(struct wpa_radio_work *work)
+{
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	work->wpa_s->ext_work_in_progress = 0;
+	radio_work_done(work);
+	os_free(ework);
+}
+
+void extRadioWorkTimeoutCb(void *eloop_ctx, void *timeout_ctx)
+{
+	auto *work = static_cast<struct wpa_radio_work *>(eloop_ctx);
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	wpa_dbg(
+		work->wpa_s, MSG_DEBUG, "Timing out external radio work %u (%s)",
+		ework->id, work->type);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	WPA_ASSERT(aidl_manager);
+	aidl_manager->notifyExtRadioWorkTimeout(work->wpa_s, ework->id);
+
+	endExtRadioWork(work);
+}
+
+void startExtRadioWork(struct wpa_radio_work *work)
+{
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	work->wpa_s->ext_work_in_progress = 1;
+	if (!ework->timeout) {
+		ework->timeout = kExtRadioWorkDefaultTimeoutInSec;
+	}
+	eloop_register_timeout(
+		ework->timeout, 0, extRadioWorkTimeoutCb, work, nullptr);
+}
+
+void extRadioWorkStartCb(struct wpa_radio_work *work, int deinit)
+{
+	// deinit==1 is invoked during interface removal. Since the AIDL
+	// interface does not support interface addition/removal, we don't
+	// need to handle this scenario.
+	WPA_ASSERT(!deinit);
+
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	wpa_dbg(
+		work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
+		ework->id, ework->type);
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	WPA_ASSERT(aidl_manager);
+	aidl_manager->notifyExtRadioWorkStart(work->wpa_s, ework->id);
+
+	startExtRadioWork(work);
+}
+
+KeyMgmtMask convertWpaKeyMgmtCapabilitiesToAidl (
+	struct wpa_supplicant *wpa_s, struct wpa_driver_capa *capa) {
+
+	uint32_t mask = 0;
+	/* Logic from ctrl_iface.c, NONE and IEEE8021X have no capability
+	 * flags and always enabled.
+	 */
+	mask |=
+		(static_cast<uint32_t>(KeyMgmtMask::NONE) |
+		 static_cast<uint32_t>(KeyMgmtMask::IEEE8021X));
+
+	if (capa->key_mgmt &
+		(WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::WPA_EAP);
+	}
+
+	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+				 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::WPA_PSK);
+	}
+#ifdef CONFIG_SUITEB192
+	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::SUITE_B_192);
+	}
+#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_OWE
+	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::OWE);
+	}
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_SAE
+	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::SAE);
+	}
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_DPP
+	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::DPP);
+	}
+#endif
+#ifdef CONFIG_WAPI_INTERFACE
+	mask |= static_cast<uint32_t>(KeyMgmtMask::WAPI_PSK);
+	mask |= static_cast<uint32_t>(KeyMgmtMask::WAPI_CERT);
+#endif /* CONFIG_WAPI_INTERFACE */
+#ifdef CONFIG_FILS
+	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::FILS_SHA256);
+	}
+	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
+		mask |= static_cast<uint32_t>(KeyMgmtMask::FILS_SHA384);
+	}
+#endif /* CONFIG_FILS */
+	return static_cast<KeyMgmtMask>(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 aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+
+StaIface::StaIface(struct wpa_global *wpa_global, const char ifname[])
+	: wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
+{}
+
+void StaIface::invalidate() { is_valid_ = false; }
+bool StaIface::isValid()
+{
+	return (is_valid_ && (retrieveIfacePtr() != nullptr));
+}
+
+::ndk::ScopedAStatus StaIface::getName(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::getNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::getType(
+	IfaceType* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::addNetwork(
+	std::shared_ptr<ISupplicantStaNetwork>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::addNetworkInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::removeNetwork(
+	int32_t in_id)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::removeNetworkInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::filsHlpFlushRequest()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::filsHlpFlushRequestInternal);
+}
+
+::ndk::ScopedAStatus StaIface::filsHlpAddRequest(
+	const std::vector<uint8_t>& in_dst_mac,
+	const std::vector<uint8_t>& in_pkt)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::filsHlpAddRequestInternal, in_dst_mac, in_pkt);
+}
+
+::ndk::ScopedAStatus StaIface::getNetwork(
+	int32_t in_id, std::shared_ptr<ISupplicantStaNetwork>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::getNetworkInternal, _aidl_return, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::listNetworks(
+	std::vector<int32_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::listNetworksInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::registerCallback(
+	const std::shared_ptr<ISupplicantStaIfaceCallback>& in_callback)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus StaIface::reassociate()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::reassociateInternal);
+}
+
+::ndk::ScopedAStatus StaIface::reconnect()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::reconnectInternal);
+}
+
+::ndk::ScopedAStatus StaIface::disconnect()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::disconnectInternal);
+}
+
+::ndk::ScopedAStatus StaIface::setPowerSave(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setPowerSaveInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::initiateTdlsDiscover(
+	const std::vector<uint8_t>& in_macAddress)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::initiateTdlsDiscoverInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateTdlsSetup(
+	const std::vector<uint8_t>& in_macAddress)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::initiateTdlsSetupInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateTdlsTeardown(
+	const std::vector<uint8_t>& in_macAddress)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::initiateTdlsTeardownInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateAnqpQuery(
+	const std::vector<uint8_t>& in_macAddress,
+	const std::vector<AnqpInfoId>& in_infoElements,
+	const std::vector<Hs20AnqpSubtypes>& in_subTypes)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::initiateAnqpQueryInternal, in_macAddress,
+		in_infoElements, in_subTypes);
+}
+
+::ndk::ScopedAStatus StaIface::initiateVenueUrlAnqpQuery(
+	const std::vector<uint8_t>& in_macAddress)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::initiateVenueUrlAnqpQueryInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateHs20IconQuery(
+	const std::vector<uint8_t>& in_macAddress,
+	const std::string& in_fileName)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::initiateHs20IconQueryInternal, in_macAddress,
+		in_fileName);
+}
+
+::ndk::ScopedAStatus StaIface::getMacAddress(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::getMacAddressInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::startRxFilter()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::startRxFilterInternal);
+}
+
+::ndk::ScopedAStatus StaIface::stopRxFilter()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::stopRxFilterInternal);
+}
+
+::ndk::ScopedAStatus StaIface::addRxFilter(
+	RxFilterType in_type)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::addRxFilterInternal, in_type);
+}
+
+::ndk::ScopedAStatus StaIface::removeRxFilter(
+	RxFilterType in_type)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::removeRxFilterInternal, in_type);
+}
+
+::ndk::ScopedAStatus StaIface::setBtCoexistenceMode(
+	BtCoexistenceMode in_mode)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setBtCoexistenceModeInternal, in_mode);
+}
+
+::ndk::ScopedAStatus StaIface::setBtCoexistenceScanModeEnabled(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setBtCoexistenceScanModeEnabledInternal,
+		in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::setSuspendModeEnabled(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setSuspendModeEnabledInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::setCountryCode(
+	const std::vector<uint8_t>& in_code)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setCountryCodeInternal, in_code);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsRegistrar(
+	const std::vector<uint8_t>& in_bssid,
+	const std::string& in_pin)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::startWpsRegistrarInternal, in_bssid, in_pin);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsPbc(
+	const std::vector<uint8_t>& in_bssid)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::startWpsPbcInternal, in_bssid);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsPinKeypad(
+	const std::string& in_pin)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::startWpsPinKeypadInternal, in_pin);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsPinDisplay(
+	const std::vector<uint8_t>& in_bssid,
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::startWpsPinDisplayInternal, _aidl_return, in_bssid);
+}
+
+::ndk::ScopedAStatus StaIface::cancelWps()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::cancelWpsInternal);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsDeviceName(
+	const std::string& in_name)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setWpsDeviceNameInternal, in_name);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsDeviceType(
+	const std::vector<uint8_t>& in_type)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setWpsDeviceTypeInternal, in_type);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsManufacturer(
+	const std::string& in_manufacturer)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setWpsManufacturerInternal, in_manufacturer);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsModelName(
+	const std::string& in_modelName)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setWpsModelNameInternal, in_modelName);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsModelNumber(
+	const std::string& in_modelNumber)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setWpsModelNumberInternal, in_modelNumber);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsSerialNumber(
+	const std::string& in_serialNumber)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setWpsSerialNumberInternal, in_serialNumber);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsConfigMethods(
+	WpsConfigMethods in_configMethods)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setWpsConfigMethodsInternal, in_configMethods);
+}
+
+::ndk::ScopedAStatus StaIface::setExternalSim(
+	bool in_useExternalSim)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::setExternalSimInternal, in_useExternalSim);
+}
+
+::ndk::ScopedAStatus StaIface::addExtRadioWork(
+	const std::string& in_name, int32_t in_freqInMhz,
+	int32_t in_timeoutInSec,
+	int32_t* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::addExtRadioWorkInternal, _aidl_return, in_name, in_freqInMhz,
+		in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus StaIface::removeExtRadioWork(
+	int32_t in_id)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::removeExtRadioWorkInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::enableAutoReconnect(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::enableAutoReconnectInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::getKeyMgmtCapabilities(
+	KeyMgmtMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaIface::getKeyMgmtCapabilitiesInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::addDppPeerUri(
+	const std::string& in_uri, int32_t* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaIface::addDppPeerUriInternal, _aidl_return, in_uri);
+}
+
+::ndk::ScopedAStatus StaIface::removeDppUri(
+	int32_t in_id)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaIface::removeDppUriInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::startDppConfiguratorInitiator(
+	int32_t in_peerBootstrapId, int32_t in_ownBootstrapId,
+	const std::string& in_ssid, const std::string& in_password,
+	const std::string& in_psk, DppNetRole in_netRole,
+	DppAkm in_securityAkm, const std::vector<uint8_t>& in_privEcKey,
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaIface::startDppConfiguratorInitiatorInternal, _aidl_return,
+		in_peerBootstrapId,in_ownBootstrapId, in_ssid, in_password,
+		in_psk, in_netRole, in_securityAkm, in_privEcKey);
+}
+
+::ndk::ScopedAStatus StaIface::startDppEnrolleeInitiator(
+	int32_t in_peerBootstrapId, int32_t in_ownBootstrapId)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaIface::startDppEnrolleeInitiatorInternal, in_peerBootstrapId,
+		in_ownBootstrapId);
+}
+
+::ndk::ScopedAStatus StaIface::stopDppInitiator()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaIface::stopDppInitiatorInternal);
+}
+
+::ndk::ScopedAStatus StaIface::getConnectionCapabilities(
+	ConnectionCapabilities* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::getConnectionCapabilitiesInternal,
+		_aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::generateDppBootstrapInfoForResponder(
+	const std::vector<uint8_t>& in_macAddress, const std::string& in_deviceInfo,
+	DppCurve in_curve, DppResponderBootstrapInfo* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::generateDppBootstrapInfoForResponderInternal, _aidl_return, 
+		in_macAddress, in_deviceInfo, in_curve);
+}
+
+::ndk::ScopedAStatus StaIface::startDppEnrolleeResponder(
+	int32_t in_listenChannel)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::startDppEnrolleeResponderInternal, in_listenChannel);
+}
+
+::ndk::ScopedAStatus StaIface::stopDppResponder(
+	int32_t in_ownBootstrapId)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::stopDppResponderInternal, in_ownBootstrapId);
+}
+
+::ndk::ScopedAStatus StaIface::generateSelfDppConfiguration(
+	const std::string& in_ssid, const std::vector<uint8_t>& in_privEcKey)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&StaIface::generateSelfDppConfigurationInternal, in_ssid, in_privEcKey);
+}
+
+::ndk::ScopedAStatus StaIface::getWpaDriverCapabilities(
+	WpaDriverCapabilitiesMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::getWpaDriverCapabilitiesInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::setMboCellularDataStatus(
+	bool in_available)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::setMboCellularDataStatusInternal, in_available);
+}
+
+::ndk::ScopedAStatus StaIface::setQosPolicyFeatureEnabled(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::setQosPolicyFeatureEnabledInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::sendQosPolicyResponse(
+	int32_t in_qosPolicyRequestId, bool in_morePolicies,
+	const std::vector<QosPolicyStatus>& in_qosPolicyStatusList)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::sendQosPolicyResponseInternal, in_qosPolicyRequestId,
+		in_morePolicies, in_qosPolicyStatusList);
+}
+
+::ndk::ScopedAStatus StaIface::removeAllQosPolicies()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::removeAllQosPoliciesInternal);
+}
+
+::ndk::ScopedAStatus StaIface::getConnectionMloLinksInfo(MloLinksInfo* _aidl_return) {
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::getConnectionMloLinksInfoInternal, _aidl_return);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaIface::getNameInternal()
+{
+	return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> StaIface::getTypeInternal()
+{
+	return {IfaceType::STA, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::filsHlpFlushRequestInternal()
+{
+#ifdef CONFIG_FILS
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+
+	wpas_flush_fils_hlp_req(wpa_s);
+	return ndk::ScopedAStatus::ok();
+#else /* CONFIG_FILS */
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN, "");
+#endif /* CONFIG_FILS */
+}
+
+ndk::ScopedAStatus StaIface::filsHlpAddRequestInternal(
+	const std::vector<uint8_t> &dst_mac, const std::vector<uint8_t> &pkt)
+{
+#ifdef CONFIG_FILS
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct fils_hlp_req *req;
+
+	if (!pkt.size())
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	if (dst_mac.size() != ETH_ALEN)
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+
+
+	req = (struct fils_hlp_req *)os_zalloc(sizeof(*req));
+	if (!req)
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+
+	os_memcpy(req->dst, dst_mac.data(), ETH_ALEN);
+
+	req->pkt = wpabuf_alloc_copy(pkt.data(), pkt.size());
+	if (!req->pkt) {
+		os_free(req);
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
+	return ndk::ScopedAStatus::ok();
+#else /* CONFIG_FILS */
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif /* CONFIG_FILS */
+}
+
+std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+StaIface::addNetworkInternal()
+{
+	std::shared_ptr<ISupplicantStaNetwork> network;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
+	if (!ssid) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager ||
+		aidl_manager->getStaNetworkAidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {network, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::removeNetworkInternal(int32_t id)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	int result = wpa_supplicant_remove_network(wpa_s, id);
+	if (result == -1) {
+		return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+	}
+	if (result != 0) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+StaIface::getNetworkInternal(int32_t id)
+{
+	std::shared_ptr<ISupplicantStaNetwork> network;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (!ssid) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN)};
+	}
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager ||
+		aidl_manager->getStaNetworkAidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {network, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+StaIface::listNetworksInternal()
+{
+	std::vector<int32_t> network_ids;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	for (struct wpa_ssid *wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
+		 wpa_ssid = wpa_ssid->next) {
+		network_ids.emplace_back(wpa_ssid->id);
+	}
+	return {std::move(network_ids), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::registerCallbackInternal(
+	const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
+{
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager ||
+		aidl_manager->addStaIfaceCallbackAidlObject(ifname_, callback)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::reassociateInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	wpas_request_connection(wpa_s);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::reconnectInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	if (!wpa_s->disconnected) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_NOT_DISCONNECTED);
+	}
+	wpas_request_connection(wpa_s);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::disconnectInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	wpas_request_disconnection(wpa_s);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::setPowerSaveInternal(bool enable)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateTdlsDiscoverInternal(
+	const std::vector<uint8_t> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	int ret;
+	const u8 *peer = mac_address.data();
+	if (wpa_tdls_is_external_setup(wpa_s->wpa)) {
+		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
+	} else {
+		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
+	}
+	if (ret) {
+		wpa_printf(MSG_INFO, "StaIface: TDLS discover failed: %d", ret);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateTdlsSetupInternal(
+	const std::vector<uint8_t> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	int ret;
+	const u8 *peer = mac_address.data();
+	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
+		!(wpa_s->conf->tdls_external_control)) {
+		wpa_tdls_remove(wpa_s->wpa, peer);
+		ret = wpa_tdls_start(wpa_s->wpa, peer);
+	} else {
+		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
+	}
+	if (ret) {
+		wpa_printf(MSG_INFO, "StaIface: TDLS setup failed: %d", ret);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateTdlsTeardownInternal(
+	const std::vector<uint8_t> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	int ret;
+	const u8 *peer = mac_address.data();
+	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
+		!(wpa_s->conf->tdls_external_control)) {
+		ret = wpa_tdls_teardown_link(
+			wpa_s->wpa, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
+	} else {
+		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
+	}
+	if (ret) {
+		wpa_printf(MSG_INFO, "StaIface: TDLS teardown failed: %d", ret);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateAnqpQueryInternal(
+	const std::vector<uint8_t> &mac_address,
+	const std::vector<AnqpInfoId> &info_elements,
+	const std::vector<Hs20AnqpSubtypes> &sub_types)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (info_elements.size() > kMaxAnqpElems) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	uint16_t info_elems_buf[kMaxAnqpElems];
+	uint32_t num_info_elems = 0;
+	for (const auto &info_element : info_elements) {
+		info_elems_buf[num_info_elems++] =
+			static_cast<std::underlying_type<
+			AnqpInfoId>::type>(info_element);
+	}
+	uint32_t sub_types_bitmask = 0;
+	for (const auto &type : sub_types) {
+		sub_types_bitmask |= BIT(
+			static_cast<std::underlying_type<
+			Hs20AnqpSubtypes>::type>(type));
+	}
+
+	if (anqp_send_req(
+		wpa_s, mac_address.data(), 0, info_elems_buf, num_info_elems,
+		sub_types_bitmask, 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateVenueUrlAnqpQueryInternal(
+	const std::vector<uint8_t> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	uint16_t info_elems_buf[1] = {ANQP_VENUE_URL};
+
+	if (anqp_send_req(
+		wpa_s, mac_address.data(), 0, info_elems_buf, 1, 0, 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateHs20IconQueryInternal(
+	const std::vector<uint8_t> &mac_address, const std::string &file_name)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->fetch_osu_icon_in_progress = 0;
+	if (hs20_anqp_send_req(
+		wpa_s, mac_address.data(), BIT(HS20_STYPE_ICON_REQUEST),
+		reinterpret_cast<const uint8_t *>(file_name.c_str()),
+		file_name.size(), true)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaIface::getMacAddressInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::vector<char> cmd(
+		kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
+	char driver_cmd_reply_buf[4096] = {};
+	int ret = wpa_drv_driver_cmd(
+		wpa_s, cmd.data(), driver_cmd_reply_buf,
+		sizeof(driver_cmd_reply_buf));
+	// Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
+	std::string reply_str = driver_cmd_reply_buf;
+	if (ret < 0 || reply_str.empty() ||
+		reply_str.find("=") == std::string::npos) {
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	// Remove all whitespace first and then split using the delimiter "=".
+	reply_str.erase(
+		remove_if(reply_str.begin(), reply_str.end(), isspace),
+		reply_str.end());
+	std::string mac_addr_str =
+		reply_str.substr(reply_str.find("=") + 1, reply_str.size());
+	std::vector<uint8_t> mac_addr(6);
+	if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {mac_addr, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::startRxFilterInternal()
+{
+	return doZeroArgDriverCommand(retrieveIfacePtr(), kStartRxFilter);
+}
+
+ndk::ScopedAStatus StaIface::stopRxFilterInternal()
+{
+	return doZeroArgDriverCommand(retrieveIfacePtr(), kStopRxFilter);
+}
+
+ndk::ScopedAStatus StaIface::addRxFilterInternal(
+	RxFilterType type)
+{
+	return doOneArgDriverCommand(
+		retrieveIfacePtr(), kAddRxFilter,
+		convertAidlRxFilterTypeToInternal(type));
+}
+
+ndk::ScopedAStatus StaIface::removeRxFilterInternal(
+	RxFilterType type)
+{
+	return doOneArgDriverCommand(
+		retrieveIfacePtr(), kRemoveRxFilter,
+		convertAidlRxFilterTypeToInternal(type));
+}
+
+ndk::ScopedAStatus StaIface::setBtCoexistenceModeInternal(
+	BtCoexistenceMode mode)
+{
+	return doOneArgDriverCommand(
+		retrieveIfacePtr(), kSetBtCoexistenceMode,
+		convertAidlBtCoexModeToInternal(mode));
+}
+
+ndk::ScopedAStatus StaIface::setBtCoexistenceScanModeEnabledInternal(bool enable)
+{
+	const char *cmd;
+	if (enable) {
+		cmd = kSetBtCoexistenceScanStart;
+	} else {
+		cmd = kSetBtCoexistenceScanStop;
+	}
+	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
+}
+
+ndk::ScopedAStatus StaIface::setSuspendModeEnabledInternal(bool enable)
+{
+	const char *cmd;
+	if (enable) {
+		cmd = kSetSupendModeEnabled;
+	} else {
+		cmd = kSetSupendModeDisabled;
+	}
+	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
+}
+
+ndk::ScopedAStatus StaIface::setCountryCodeInternal(
+	const std::vector<uint8_t> &code)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	ndk::ScopedAStatus status = doOneArgDriverCommand(
+		wpa_s, kSetCountryCode,
+		std::string(std::begin(code), std::end(code)));
+	if (!status.isOk()) {
+		return status;
+	}
+	struct p2p_data *p2p = wpa_s->global->p2p;
+	if (p2p) {
+		char country[3];
+		country[0] = code[0];
+		country[1] = code[1];
+		country[2] = 0x04;
+		p2p_set_country(p2p, country);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::startWpsRegistrarInternal(
+	const std::vector<uint8_t> &bssid, const std::string &pin)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_start_reg(wpa_s, bssid.data(), pin.c_str(), nullptr)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::startWpsPbcInternal(
+	const std::vector<uint8_t> &bssid)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	const uint8_t *bssid_addr =
+		is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	if (wpas_wps_start_pbc(wpa_s, bssid_addr, 0, 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::startWpsPinKeypadInternal(const std::string &pin)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_start_pin(
+		wpa_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaIface::startWpsPinDisplayInternal(
+	const std::vector<uint8_t> &bssid)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	const uint8_t *bssid_addr =
+		is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	int pin =
+		wpas_wps_start_pin(wpa_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
+	if (pin < 0) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::convertWpsPinToString(pin),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::cancelWpsInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_cancel(wpa_s)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::setWpsDeviceNameInternal(const std::string &name)
+{
+	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
+}
+
+ndk::ScopedAStatus StaIface::setWpsDeviceTypeInternal(
+	const std::vector<uint8_t> &type)
+{
+	std::array<uint8_t, 8> type_arr;
+	std::copy_n(type.begin(), 8, type_arr.begin());
+	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type_arr);
+}
+
+ndk::ScopedAStatus StaIface::setWpsManufacturerInternal(
+	const std::string &manufacturer)
+{
+	return iface_config_utils::setWpsManufacturer(
+		retrieveIfacePtr(), manufacturer);
+}
+
+ndk::ScopedAStatus StaIface::setWpsModelNameInternal(
+	const std::string &model_name)
+{
+	return iface_config_utils::setWpsModelName(
+		retrieveIfacePtr(), model_name);
+}
+
+ndk::ScopedAStatus StaIface::setWpsModelNumberInternal(
+	const std::string &model_number)
+{
+	return iface_config_utils::setWpsModelNumber(
+		retrieveIfacePtr(), model_number);
+}
+
+ndk::ScopedAStatus StaIface::setWpsSerialNumberInternal(
+	const std::string &serial_number)
+{
+	return iface_config_utils::setWpsSerialNumber(
+		retrieveIfacePtr(), serial_number);
+}
+
+ndk::ScopedAStatus StaIface::setWpsConfigMethodsInternal(WpsConfigMethods config_methods)
+{
+	return iface_config_utils::setWpsConfigMethods(
+		retrieveIfacePtr(), static_cast<uint16_t>(config_methods));
+}
+
+ndk::ScopedAStatus StaIface::setExternalSimInternal(bool useExternalSim)
+{
+	return iface_config_utils::setExternalSim(
+		retrieveIfacePtr(), useExternalSim);
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> StaIface::addExtRadioWorkInternal(
+	const std::string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	auto *ework = static_cast<struct wpa_external_work *>(
+		os_zalloc(sizeof(struct wpa_external_work)));
+	if (!ework) {
+		return {UINT32_MAX, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+
+	std::string radio_work_name = kExtRadioWorkNamePrefix + name;
+	os_strlcpy(ework->type, radio_work_name.c_str(), sizeof(ework->type));
+	ework->timeout = timeout_in_sec;
+	wpa_s->ext_work_id++;
+	if (wpa_s->ext_work_id == 0) {
+		wpa_s->ext_work_id++;
+	}
+	ework->id = wpa_s->ext_work_id;
+
+	if (radio_add_work(
+		wpa_s, freq_in_mhz, ework->type, 0, extRadioWorkStartCb,
+		ework)) {
+		os_free(ework);
+		return {UINT32_MAX, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {ework->id, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::removeExtRadioWorkInternal(uint32_t id)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_radio_work *work;
+	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
+	{
+		if (os_strncmp(
+			work->type, kExtRadioWorkNamePrefix,
+			sizeof(kExtRadioWorkNamePrefix)) != 0)
+			continue;
+
+		auto *ework =
+			static_cast<struct wpa_external_work *>(work->ctx);
+		if (ework->id != id)
+			continue;
+
+		wpa_dbg(
+			wpa_s, MSG_DEBUG, "Completed external radio work %u (%s)",
+			ework->id, ework->type);
+		eloop_cancel_timeout(extRadioWorkTimeoutCb, work, NULL);
+		endExtRadioWork(work);
+
+		return ndk::ScopedAStatus::ok();
+	}
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+
+ndk::ScopedAStatus StaIface::enableAutoReconnectInternal(bool enable)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->auto_reconnect_disabled = enable ? 0 : 1;
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus>
+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 {id, ndk::ScopedAStatus::ok()};
+	}
+#endif
+	return {-1, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+}
+
+ndk::ScopedAStatus 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 (dpp_bootstrap_remove(wpa_s->dpp, bootstrap_id_str.c_str()) >= 0) {
+		return ndk::ScopedAStatus::ok();
+	}
+#endif
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+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,
+		const std::vector<uint8_t> &privEcKey)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string cmd = "";
+	std::string cmd2 = "";
+	int32_t id;
+	char key[1024];
+
+	if (net_role != DppNetRole::AP &&
+			net_role != DppNetRole::STA) {
+		wpa_printf(MSG_ERROR,
+			   "DPP: Error: Invalid network role specified: %d", net_role);
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+
+	cmd += " peer=" + std::to_string(peer_bootstrap_id);
+	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 && security_akm != DppAkm::DPP) {
+		wpa_printf(MSG_ERROR, "DPP: Error: invalid AKM specified: %d",
+				security_akm);
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+
+	/* 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 {std::vector<uint8_t>(),
+			createStatus(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 {std::vector<uint8_t>(),
+				createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+		}
+		if (password.empty() && psk.empty()) {
+			wpa_printf(MSG_ERROR, "DPP: Error: Password or PSK not specified");
+			return {std::vector<uint8_t>(),
+				createStatus(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;
+
+	case DppAkm::DPP:
+		role += "dpp";
+		break;
+
+	default:
+		wpa_printf(MSG_ERROR,
+			   "DPP: Invalid or unsupported security AKM specified: %d", security_akm);
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+
+	cmd += " conf=";
+	cmd += role;
+
+	if (net_role == DppNetRole::STA) {
+		/* DPP R2 connection status request */
+		cmd += " conn_status=1";
+	}
+
+	if (security_akm == DppAkm::DPP) {
+		if (!privEcKey.empty()) {
+			cmd2 += " key=" + std::string(privEcKey.begin(), privEcKey.end());
+		}
+		id = dpp_configurator_add(wpa_s->dpp, cmd2.c_str());
+		if (id < 0 || (privEcKey.empty() &&
+			       (dpp_configurator_get_key_id(wpa_s->dpp, id, key, sizeof(key)) < 0)))
+		{
+			wpa_printf(MSG_ERROR, "DPP configurator add failed. "
+			           "Input key might be incorrect");
+			return {std::vector<uint8_t>(),
+				createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+		}
+
+		cmd += " configurator=" + std::to_string(id);
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP initiator command: %s", cmd.c_str());
+
+	if (wpas_dpp_auth_init(wpa_s, cmd.c_str()) == 0) {
+		// Return key if input privEcKey was null/empty.
+		if (security_akm == DppAkm::DPP && privEcKey.empty()) {
+			std::string k(key);
+			std::vector<uint8_t> vKey(k.begin(), k.end());
+			return {vKey, ndk::ScopedAStatus::ok()};
+		}
+		return {std::vector<uint8_t>(), ndk::ScopedAStatus::ok()};
+	}
+#endif
+	return {std::vector<uint8_t>(), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+}
+
+ndk::ScopedAStatus 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 AIDL 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 ndk::ScopedAStatus::ok();
+	}
+#endif
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+ndk::ScopedAStatus StaIface::stopDppInitiatorInternal()
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+
+	wpas_dpp_stop(wpa_s);
+	return ndk::ScopedAStatus::ok();
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif
+}
+
+std::pair<DppResponderBootstrapInfo, ndk::ScopedAStatus>
+StaIface::generateDppBootstrapInfoForResponderInternal(
+	const std::vector<uint8_t> &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;
+	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 {bootstrap_info, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	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 {bootstrap_info, ndk::ScopedAStatus::ok()};
+		}
+	}
+	return {bootstrap_info, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+#else
+	return {bootstrap_info, createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED)};
+#endif
+}
+
+ndk::ScopedAStatus 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 AIDL 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 ndk::ScopedAStatus::ok();
+	}
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+ndk::ScopedAStatus 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 ndk::ScopedAStatus::ok();
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+ndk::ScopedAStatus StaIface::generateSelfDppConfigurationInternal(const std::string& ssid,
+		const std::vector<uint8_t> &privEcKey)
+{
+#ifdef CONFIG_DPP
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::string cmd = "";
+	char *ssid_hex_str;
+	int len;
+	int32_t id;
+
+	if (ssid.empty() || privEcKey.empty()) {
+		wpa_printf(MSG_ERROR, "DPP generate self configuration failed. ssid/key empty");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	cmd += " key=" + std::string(privEcKey.begin(), privEcKey.end());
+
+	id = dpp_configurator_add(wpa_s->dpp, cmd.c_str());
+	if (id < 0) {
+		wpa_printf(MSG_ERROR, "DPP configurator add failed. Input key might be incorrect");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	cmd = " conf=sta-dpp";
+	cmd += " configurator=" + std::to_string(id);
+
+	ssid_hex_str = (char *) os_zalloc(ssid.size() * 2 + 1);
+	if (!ssid_hex_str) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	wpa_snprintf_hex(ssid_hex_str, ssid.size() * 2 + 1, (u8*)ssid.data(), ssid.size());
+	cmd += " ssid=" + std::string(ssid_hex_str);
+
+	/* Report received configuration to AIDL and create an internal profile */
+	wpa_s->conf->dpp_config_processing = 1;
+
+	if (wpas_dpp_configurator_sign(wpa_s, cmd.c_str()) == 0) {
+		os_free(ssid_hex_str);
+		return ndk::ScopedAStatus::ok();
+	}
+
+	os_free(ssid_hex_str);
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+std::pair<ConnectionCapabilities, ndk::ScopedAStatus>
+StaIface::getConnectionCapabilitiesInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	ConnectionCapabilities capa;
+
+	if (wpa_s->connection_set) {
+		capa.legacyMode = LegacyMode::UNKNOWN;
+		if (wpa_s->connection_he) {
+			capa.technology = WifiTechnology::HE;
+		} else if (wpa_s->connection_vht) {
+			capa.technology = WifiTechnology::VHT;
+		} else if (wpa_s->connection_ht) {
+			capa.technology = WifiTechnology::HT;
+		} else {
+			capa.technology = WifiTechnology::LEGACY;
+			if (wpas_freq_to_band(wpa_s->assoc_freq) == BAND_2_4_GHZ) {
+				capa.legacyMode = (wpa_s->connection_11b_only) ? LegacyMode::B_MODE
+						: LegacyMode::G_MODE; 
+			} else {
+				capa.legacyMode = LegacyMode::A_MODE;
+			}
+		}
+		switch (wpa_s->connection_channel_bandwidth) {
+		case CHAN_WIDTH_20:
+			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+			break;
+		case CHAN_WIDTH_40:
+			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_40;
+			break;
+		case CHAN_WIDTH_80:
+			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80;
+			break;
+		case CHAN_WIDTH_160:
+			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_160;
+			break;
+		case CHAN_WIDTH_80P80:
+			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80P80;
+			break;
+		default:
+			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+			break;
+		}
+		capa.maxNumberRxSpatialStreams = wpa_s->connection_max_nss_rx;
+		capa.maxNumberTxSpatialStreams = wpa_s->connection_max_nss_tx;
+	} else {
+		capa.technology = WifiTechnology::UNKNOWN;
+		capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+		capa.maxNumberTxSpatialStreams = 1;
+		capa.maxNumberRxSpatialStreams = 1;
+		capa.legacyMode = LegacyMode::UNKNOWN;
+	}
+	return {capa, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<WpaDriverCapabilitiesMask, ndk::ScopedAStatus>
+StaIface::getWpaDriverCapabilitiesInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	uint32_t mask = 0;
+
+#ifdef CONFIG_MBO
+	/* MBO has no capability flags. It's mainly legacy 802.11v BSS
+	 * transition + Cellular steering. 11v is a default feature in
+	 * supplicant. And cellular steering is handled in framework.
+	 */
+	mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::MBO);
+	if (wpa_s->enable_oce & OCE_STA) {
+		mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::OCE);
+	}
+#endif
+#ifdef CONFIG_SAE_PK
+	mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::SAE_PK);
+#endif
+	mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::WFD_R2);
+
+	mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::TRUST_ON_FIRST_USE);
+
+	wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);
+
+	return {static_cast<WpaDriverCapabilitiesMask>(mask),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::setMboCellularDataStatusInternal(bool available)
+{
+#ifdef CONFIG_MBO
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	enum mbo_cellular_capa mbo_cell_capa;
+
+	if (available) {
+		mbo_cell_capa = MBO_CELL_CAPA_AVAILABLE;
+	} else {
+		mbo_cell_capa = MBO_CELL_CAPA_NOT_AVAILABLE;
+	}
+
+#ifdef ENABLE_PRIV_CMD_UPDATE_MBO_CELL_STATUS
+	char mbo_cmd[32];
+	char buf[32];
+
+	os_snprintf(mbo_cmd, sizeof(mbo_cmd), "%s %d", "MBO CELL_DATA_CAP", mbo_cell_capa);
+	if (wpa_drv_driver_cmd(wpa_s, mbo_cmd, buf, sizeof(buf)) < 0) {
+		wpa_printf(MSG_ERROR, "MBO CELL_DATA_CAP cmd failed CAP:%d", mbo_cell_capa);
+	}
+#else
+	wpas_mbo_update_cell_capa(wpa_s, mbo_cell_capa);
+#endif
+
+	return ndk::ScopedAStatus::ok();
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif
+}
+
+std::pair<KeyMgmtMask, ndk::ScopedAStatus>
+StaIface::getKeyMgmtCapabilitiesInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_driver_capa capa;
+
+	/* Get capabilities from driver and populate the key management mask */
+	if (wpa_drv_get_capa(wpa_s, &capa) < 0) {
+		return {static_cast<KeyMgmtMask>(0),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+
+	return {convertWpaKeyMgmtCapabilitiesToAidl(wpa_s, &capa),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::setQosPolicyFeatureEnabledInternal(bool enable)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->enable_dscp_policy_capa = enable ? 1 : 0;
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::sendQosPolicyResponseInternal(
+	int32_t qos_policy_request_id, bool more_policies,
+	const std::vector<QosPolicyStatus>& qos_policy_status_list)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct dscp_resp_data resp_data;
+	int num_policies = qos_policy_status_list.size();
+
+	memset(&resp_data, 0, sizeof(resp_data));
+
+	resp_data.more = more_policies ? 1 : 0;
+	resp_data.policy = (struct dscp_policy_status *) malloc(
+		sizeof(struct dscp_policy_status) * num_policies);
+	if (num_policies && !resp_data.policy){
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	resp_data.solicited = true;
+	wpa_s->dscp_req_dialog_token = qos_policy_request_id;
+
+	for (int i = 0; i < num_policies; i++) {
+		resp_data.policy[i].id = qos_policy_status_list.at(i).policyId;
+		resp_data.policy[i].status =
+			static_cast<uint8_t>(qos_policy_status_list.at(i).status);
+	}
+	resp_data.num_policies = num_policies;
+
+	if (wpas_send_dscp_response(wpa_s, &resp_data)) {
+		free(resp_data.policy);
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	free(resp_data.policy);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::removeAllQosPoliciesInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct dscp_resp_data resp_data;
+
+	memset(&resp_data, 0, sizeof(resp_data));
+	resp_data.reset = true;
+	resp_data.solicited = false;
+	wpa_s->dscp_req_dialog_token = 0;
+
+	if (wpas_send_dscp_response(wpa_s, &resp_data)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<MloLinksInfo, ndk::ScopedAStatus> StaIface::getConnectionMloLinksInfoInternal()
+{
+	MloLinksInfo linksInfo;
+	return {linksInfo, ndk::ScopedAStatus::ok()};
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this iface.
+ * If the underlying iface is removed, then all RPC method calls on this object
+ * will return failure.
+ */
+wpa_supplicant *StaIface::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/wpa_supplicant/aidl/sta_iface.h b/wpa_supplicant/aidl/sta_iface.h
new file mode 100644
index 0000000..0ed29d8
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_iface.h
@@ -0,0 +1,282 @@
+/*
+ * WPA Supplicant - Sta Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_STA_IFACE_H
+#define WPA_SUPPLICANT_AIDL_STA_IFACE_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/AnqpInfoId.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaIface.h>
+#include <aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.h>
+#include <aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.h>
+#include <aidl/android/hardware/wifi/supplicant/MloLinksInfo.h>
+#include <aidl/android/hardware/wifi/supplicant/QosPolicyStatus.h>
+#include <aidl/android/hardware/wifi/supplicant/RxFilterType.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+#include "driver_i.h"
+#include "wpa.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of StaIface aidl object. Each unique aidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class StaIface : public BnSupplicantStaIface
+{
+public:
+	StaIface(struct wpa_global* wpa_global, const char ifname[]);
+	~StaIface() override = default;
+	// AIDL does not provide a built-in mechanism to let the server
+	// invalidate a AIDL interface object after creation. If any client
+	// process holds onto a reference to the object in their context,
+	// any method calls on that reference will continue to be directed to
+	// the server.
+	// However Supplicant HAL needs to control the lifetime of these
+	// objects. So, add a public |invalidate| method to all |Iface| and
+	// |Network| objects.
+	// This will be used to mark an object invalid when the corresponding
+	// iface or network is removed.
+	// All AIDL method implementations should check if the object is still
+	// marked valid before processing them.
+	void invalidate();
+	bool isValid();
+
+	// Aidl methods exposed.
+  	::ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+	::ndk::ScopedAStatus addNetwork(
+		std::shared_ptr<ISupplicantStaNetwork>* _aidl_return) override;
+	::ndk::ScopedAStatus removeNetwork(int32_t in_id) override;
+	::ndk::ScopedAStatus filsHlpFlushRequest() override;
+	::ndk::ScopedAStatus filsHlpAddRequest(
+		const std::vector<uint8_t>& in_dst_mac,
+		const std::vector<uint8_t>& in_pkt) override;
+	::ndk::ScopedAStatus getNetwork(
+		int32_t in_id, std::shared_ptr<ISupplicantStaNetwork>* _aidl_return) override;
+	::ndk::ScopedAStatus listNetworks(std::vector<int32_t>* _aidl_return) override;
+	::ndk::ScopedAStatus registerCallback(
+		const std::shared_ptr<ISupplicantStaIfaceCallback>& in_callback) override;
+	::ndk::ScopedAStatus reassociate() override;
+	::ndk::ScopedAStatus reconnect() override;
+	::ndk::ScopedAStatus disconnect() override;
+	::ndk::ScopedAStatus setPowerSave(bool in_enable) override;
+	::ndk::ScopedAStatus initiateTdlsDiscover(
+		const std::vector<uint8_t>& in_macAddress) override;
+	::ndk::ScopedAStatus initiateTdlsSetup(
+		const std::vector<uint8_t>& in_macAddress) override;
+	::ndk::ScopedAStatus initiateTdlsTeardown(
+		const std::vector<uint8_t>& in_macAddress) override;
+	::ndk::ScopedAStatus initiateAnqpQuery(
+		const std::vector<uint8_t>& in_macAddress,
+		const std::vector<AnqpInfoId>& in_infoElements,
+		const std::vector<Hs20AnqpSubtypes>& in_subTypes) override;
+	::ndk::ScopedAStatus initiateVenueUrlAnqpQuery(
+		const std::vector<uint8_t>& in_macAddress) override;
+	::ndk::ScopedAStatus initiateHs20IconQuery(
+		const std::vector<uint8_t>& in_macAddress, const std::string& in_fileName) override;
+	::ndk::ScopedAStatus getMacAddress(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus startRxFilter() override;
+	::ndk::ScopedAStatus stopRxFilter() override;
+	::ndk::ScopedAStatus addRxFilter(RxFilterType in_type) override;
+	::ndk::ScopedAStatus removeRxFilter(RxFilterType in_type) override;
+	::ndk::ScopedAStatus setBtCoexistenceMode(BtCoexistenceMode in_mode) override;
+	::ndk::ScopedAStatus setBtCoexistenceScanModeEnabled(bool in_enable) override;
+	::ndk::ScopedAStatus setSuspendModeEnabled(bool in_enable) override;
+	::ndk::ScopedAStatus setCountryCode(const std::vector<uint8_t>& in_code) override;
+	::ndk::ScopedAStatus startWpsRegistrar(
+		const std::vector<uint8_t>& in_bssid, const std::string& in_pin) override;
+	::ndk::ScopedAStatus startWpsPbc(const std::vector<uint8_t>& in_bssid) override;
+	::ndk::ScopedAStatus startWpsPinDisplay(
+		const std::vector<uint8_t>& in_bssid, std::string* _aidl_return) override;
+	::ndk::ScopedAStatus startWpsPinKeypad(const std::string& in_pin) override;
+	::ndk::ScopedAStatus cancelWps() override;
+	::ndk::ScopedAStatus setWpsDeviceName(const std::string& in_name) override;
+	::ndk::ScopedAStatus setWpsDeviceType(const std::vector<uint8_t>& in_type) override;
+	::ndk::ScopedAStatus setWpsManufacturer(const std::string& in_manufacturer) override;
+	::ndk::ScopedAStatus setWpsModelName(const std::string& in_modelName) override;
+	::ndk::ScopedAStatus setWpsModelNumber(const std::string& in_modelNumber) override;
+	::ndk::ScopedAStatus setWpsSerialNumber(const std::string& in_serialNumber) override;
+	::ndk::ScopedAStatus setWpsConfigMethods(WpsConfigMethods in_configMethods) override;
+	::ndk::ScopedAStatus setExternalSim(bool in_useExternalSim) override;
+	::ndk::ScopedAStatus addExtRadioWork(
+		const std::string& in_name, int32_t in_freqInMhz,
+		int32_t in_timeoutInSec, int32_t* _aidl_return) override;
+	::ndk::ScopedAStatus removeExtRadioWork(int32_t in_id) override;
+	::ndk::ScopedAStatus enableAutoReconnect(bool in_enable) override;
+	::ndk::ScopedAStatus getKeyMgmtCapabilities(KeyMgmtMask* _aidl_return) override;
+	::ndk::ScopedAStatus addDppPeerUri(
+		const std::string& in_uri, int32_t* _aidl_return) override;
+	::ndk::ScopedAStatus removeDppUri(int32_t in_id) override;
+	::ndk::ScopedAStatus startDppConfiguratorInitiator(
+		int32_t in_peerBootstrapId, int32_t in_ownBootstrapId,
+		const std::string& in_ssid, const std::string& in_password,
+		const std::string& in_psk, DppNetRole in_netRole, DppAkm in_securityAkm,
+		const std::vector<uint8_t>& in_privEcKey,
+		std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus startDppEnrolleeInitiator(
+		int32_t in_peerBootstrapId, int32_t in_ownBootstrapId) override;
+	::ndk::ScopedAStatus stopDppInitiator() override;
+	::ndk::ScopedAStatus getConnectionCapabilities(ConnectionCapabilities* _aidl_return) override;
+	::ndk::ScopedAStatus getWpaDriverCapabilities(WpaDriverCapabilitiesMask* _aidl_return) override;
+	::ndk::ScopedAStatus setMboCellularDataStatus(bool in_available) override;
+	::ndk::ScopedAStatus generateDppBootstrapInfoForResponder(
+		const std::vector<uint8_t>& in_macAddress,
+		const std::string& in_deviceInfo, DppCurve in_curve,
+		DppResponderBootstrapInfo* _aidl_return) override;
+	::ndk::ScopedAStatus startDppEnrolleeResponder(int32_t in_listenChannel) override;
+	::ndk::ScopedAStatus stopDppResponder(int32_t in_ownBootstrapId) override;
+	::ndk::ScopedAStatus generateSelfDppConfiguration(
+		const std::string& in_ssid, const std::vector<uint8_t>& in_privEcKey) override;
+	::ndk::ScopedAStatus setQosPolicyFeatureEnabled(bool in_enable) override;
+	::ndk::ScopedAStatus sendQosPolicyResponse(
+		int32_t in_qosPolicyRequestId, bool in_morePolicies,
+		const std::vector<QosPolicyStatus>& in_qosPolicyStatusList) override;
+	::ndk::ScopedAStatus removeAllQosPolicies() override;
+	::ndk::ScopedAStatus getConnectionMloLinksInfo(MloLinksInfo* _aidl_return) override;
+
+private:
+	// Corresponding worker functions for the AIDL methods.
+	std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+	std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+	std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+		addNetworkInternal();
+	ndk::ScopedAStatus filsHlpFlushRequestInternal();
+	ndk::ScopedAStatus filsHlpAddRequestInternal(
+		const std::vector<uint8_t>& dst_mac,
+		const std::vector<uint8_t>& pkt);
+	ndk::ScopedAStatus removeNetworkInternal(int32_t id);
+	std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+		getNetworkInternal(int32_t id);
+	std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+		listNetworksInternal();
+	ndk::ScopedAStatus registerCallbackInternal(
+		const std::shared_ptr<ISupplicantStaIfaceCallback>& callback);
+	ndk::ScopedAStatus reassociateInternal();
+	ndk::ScopedAStatus reconnectInternal();
+	ndk::ScopedAStatus disconnectInternal();
+	ndk::ScopedAStatus setPowerSaveInternal(bool enable);
+	ndk::ScopedAStatus initiateTdlsDiscoverInternal(
+		const std::vector<uint8_t>& mac_address);
+	ndk::ScopedAStatus initiateTdlsSetupInternal(
+		const std::vector<uint8_t>& mac_address);
+	ndk::ScopedAStatus initiateTdlsTeardownInternal(
+		const std::vector<uint8_t>& mac_address);
+	ndk::ScopedAStatus initiateAnqpQueryInternal(
+		const std::vector<uint8_t>& mac_address,
+		const std::vector<AnqpInfoId>& info_elements,
+		const std::vector<Hs20AnqpSubtypes>&
+		sub_types);
+	ndk::ScopedAStatus initiateVenueUrlAnqpQueryInternal(
+		const std::vector<uint8_t>& mac_address);
+	ndk::ScopedAStatus initiateHs20IconQueryInternal(
+		const std::vector<uint8_t>& mac_address,
+		const std::string& file_name);
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		getMacAddressInternal();
+	ndk::ScopedAStatus startRxFilterInternal();
+	ndk::ScopedAStatus stopRxFilterInternal();
+	ndk::ScopedAStatus addRxFilterInternal(
+		RxFilterType type);
+	ndk::ScopedAStatus removeRxFilterInternal(
+		RxFilterType type);
+	ndk::ScopedAStatus setBtCoexistenceModeInternal(
+		BtCoexistenceMode mode);
+	ndk::ScopedAStatus setBtCoexistenceScanModeEnabledInternal(bool enable);
+	ndk::ScopedAStatus setSuspendModeEnabledInternal(bool enable);
+	ndk::ScopedAStatus setCountryCodeInternal(
+		const std::vector<uint8_t>& code);
+	ndk::ScopedAStatus startWpsRegistrarInternal(
+		const std::vector<uint8_t>& bssid, const std::string& pin);
+	ndk::ScopedAStatus startWpsPbcInternal(
+		const std::vector<uint8_t>& bssid);
+	ndk::ScopedAStatus startWpsPinKeypadInternal(const std::string& pin);
+	std::pair<std::string, ndk::ScopedAStatus> startWpsPinDisplayInternal(
+		const std::vector<uint8_t>& bssid);
+	ndk::ScopedAStatus cancelWpsInternal();
+	ndk::ScopedAStatus setWpsDeviceNameInternal(const std::string& name);
+	ndk::ScopedAStatus setWpsDeviceTypeInternal(
+		const std::vector<uint8_t>& type);
+	ndk::ScopedAStatus setWpsManufacturerInternal(
+		const std::string& manufacturer);
+	ndk::ScopedAStatus setWpsModelNameInternal(const std::string& model_name);
+	ndk::ScopedAStatus setWpsModelNumberInternal(
+		const std::string& model_number);
+	ndk::ScopedAStatus setWpsSerialNumberInternal(
+		const std::string& serial_number);
+	ndk::ScopedAStatus setWpsConfigMethodsInternal(WpsConfigMethods config_methods);
+	ndk::ScopedAStatus setExternalSimInternal(bool useExternalSim);
+	std::pair<uint32_t, ndk::ScopedAStatus> addExtRadioWorkInternal(
+		const std::string& name, uint32_t freq_in_mhz,
+		uint32_t timeout_in_sec);
+	ndk::ScopedAStatus removeExtRadioWorkInternal(uint32_t id);
+	ndk::ScopedAStatus enableAutoReconnectInternal(bool enable);
+	std::pair<KeyMgmtMask, ndk::ScopedAStatus> getKeyMgmtCapabilitiesInternal();
+	std::pair<uint32_t, ndk::ScopedAStatus> addDppPeerUriInternal(const std::string& uri);
+	ndk::ScopedAStatus removeDppUriInternal(uint32_t bootstrap_id);
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> 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, const std::vector<uint8_t> &privEcKey);
+	ndk::ScopedAStatus startDppEnrolleeInitiatorInternal(uint32_t peer_bootstrap_id,
+			uint32_t own_bootstrap_id);
+	ndk::ScopedAStatus stopDppInitiatorInternal();
+	std::pair<ConnectionCapabilities, ndk::ScopedAStatus> getConnectionCapabilitiesInternal();
+	std::pair<WpaDriverCapabilitiesMask, ndk::ScopedAStatus> getWpaDriverCapabilitiesInternal();
+	ndk::ScopedAStatus setMboCellularDataStatusInternal(bool available);
+	std::pair<DppResponderBootstrapInfo, ndk::ScopedAStatus>
+			generateDppBootstrapInfoForResponderInternal(
+			const std::vector<uint8_t>& mac_address, const std::string& device_info,
+			DppCurve curve);
+	ndk::ScopedAStatus startDppEnrolleeResponderInternal(uint32_t listen_channel);
+	ndk::ScopedAStatus stopDppResponderInternal(uint32_t own_bootstrap_id);
+	ndk::ScopedAStatus generateSelfDppConfigurationInternal(
+		const std::string& ssid, const std::vector<uint8_t> &privEcKey);
+	ndk::ScopedAStatus setQosPolicyFeatureEnabledInternal(bool enable);
+	ndk::ScopedAStatus sendQosPolicyResponseInternal(
+		int32_t qos_policy_request_id, bool more_policies,
+		const std::vector<QosPolicyStatus>& qos_policy_status_list);
+	ndk::ScopedAStatus removeAllQosPoliciesInternal();
+	std::pair<MloLinksInfo, ndk::ScopedAStatus> getConnectionMloLinksInfoInternal();
+	struct wpa_supplicant* retrieveIfacePtr();
+
+	// Reference to the global wpa_struct. This is assumed to be valid for
+	// the lifetime of the process.
+	struct wpa_global* wpa_global_;
+	// Name of the iface this aidl object controls
+	const std::string ifname_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(StaIface);
+};
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // WPA_SUPPLICANT_AIDL_STA_IFACE_H
diff --git a/wpa_supplicant/aidl/sta_network.cpp b/wpa_supplicant/aidl/sta_network.cpp
new file mode 100644
index 0000000..fe4a760
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_network.cpp
@@ -0,0 +1,2568 @@
+/*
+ * WPA Supplicant - Sta network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "misc_utils.h"
+#include "sta_network.h"
+
+extern "C"
+{
+#include "wps_supplicant.h"
+}
+
+namespace {
+using aidl::android::hardware::wifi::supplicant::AuthAlgMask;
+using aidl::android::hardware::wifi::supplicant::EapMethod;
+using aidl::android::hardware::wifi::supplicant::EapPhase2Method;
+using aidl::android::hardware::wifi::supplicant::GroupCipherMask;
+using aidl::android::hardware::wifi::supplicant::GroupMgmtCipherMask;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::PairwiseCipherMask;
+using aidl::android::hardware::wifi::supplicant::ProtoMask;
+
+constexpr uint8_t kZeroBssid[6] = {0, 0, 0, 0, 0, 0};
+
+constexpr uint32_t kAllowedKeyMgmtMask =
+	(static_cast<uint32_t>(KeyMgmtMask::NONE) |
+	 static_cast<uint32_t>(KeyMgmtMask::WPA_PSK) |
+	 static_cast<uint32_t>(KeyMgmtMask::WPA_EAP) |
+	 static_cast<uint32_t>(KeyMgmtMask::IEEE8021X) |
+	 static_cast<uint32_t>(KeyMgmtMask::FT_EAP) |
+	 static_cast<uint32_t>(KeyMgmtMask::FT_PSK) |
+	 static_cast<uint32_t>(KeyMgmtMask::OSEN) |
+	 static_cast<uint32_t>(KeyMgmtMask::SAE) |
+	 static_cast<uint32_t>(KeyMgmtMask::SUITE_B_192) |
+	 static_cast<uint32_t>(KeyMgmtMask::OWE) |
+	 static_cast<uint32_t>(KeyMgmtMask::WPA_PSK_SHA256) |
+	 static_cast<uint32_t>(KeyMgmtMask::WPA_EAP_SHA256) |
+	 static_cast<uint32_t>(KeyMgmtMask::WAPI_PSK) |
+	 static_cast<uint32_t>(KeyMgmtMask::WAPI_CERT) |
+	 static_cast<uint32_t>(KeyMgmtMask::FILS_SHA256) |
+	 static_cast<uint32_t>(KeyMgmtMask::FILS_SHA384) |
+	 static_cast<uint32_t>(KeyMgmtMask::DPP));
+constexpr uint32_t kAllowedProtoMask =
+	(static_cast<uint32_t>(ProtoMask::WPA) |
+	 static_cast<uint32_t>(ProtoMask::RSN) |
+	 static_cast<uint32_t>(ProtoMask::OSEN) |
+	 static_cast<uint32_t>(ProtoMask::WAPI));
+constexpr uint32_t kAllowedAuthAlgMask =
+	(static_cast<uint32_t>(AuthAlgMask::OPEN) |
+	 static_cast<uint32_t>(AuthAlgMask::SHARED) |
+	 static_cast<uint32_t>(AuthAlgMask::LEAP) |
+	 static_cast<uint32_t>(AuthAlgMask::SAE));
+constexpr uint32_t kAllowedGroupCipherMask =
+	(static_cast<uint32_t>(GroupCipherMask::WEP40) |
+	 static_cast<uint32_t>(GroupCipherMask::WEP104) |
+	 static_cast<uint32_t>(GroupCipherMask::TKIP) |
+	 static_cast<uint32_t>(GroupCipherMask::CCMP) |
+	 static_cast<uint32_t>(
+	 GroupCipherMask::GTK_NOT_USED) |
+	 static_cast<uint32_t>(GroupCipherMask::GCMP_256) |
+	 static_cast<uint32_t>(GroupCipherMask::SMS4) |
+	 static_cast<uint32_t>(GroupCipherMask::GCMP_128));
+constexpr uint32_t kAllowedPairwisewCipherMask =
+	(static_cast<uint32_t>(PairwiseCipherMask::NONE) |
+	 static_cast<uint32_t>(PairwiseCipherMask::TKIP) |
+	 static_cast<uint32_t>(PairwiseCipherMask::CCMP) |
+	 static_cast<uint32_t>(
+	 PairwiseCipherMask::GCMP_256) |
+	 static_cast<uint32_t>(
+	 PairwiseCipherMask::SMS4) |
+	 static_cast<uint32_t>(PairwiseCipherMask::GCMP_128));
+constexpr uint32_t kAllowedGroupMgmtCipherMask =
+	(static_cast<uint32_t>(
+			GroupMgmtCipherMask::BIP_GMAC_128) |
+	 static_cast<uint32_t>(
+			 GroupMgmtCipherMask::BIP_GMAC_256) |
+	 static_cast<uint32_t>(
+			 GroupMgmtCipherMask::BIP_CMAC_256));
+
+constexpr uint32_t kEapMethodMax =
+	static_cast<uint32_t>(EapMethod::WFA_UNAUTH_TLS) + 1;
+constexpr char const *kEapMethodStrings[kEapMethodMax] = {
+	"PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS"};
+constexpr uint32_t kEapPhase2MethodMax =
+	static_cast<uint32_t>(EapPhase2Method::AKA_PRIME) + 1;
+constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
+	"", "PAP", "MSCHAP", "MSCHAPV2", "GTC", "SIM", "AKA", "AKA'"};
+constexpr char kEapPhase2AuthPrefix[] = "auth=";
+constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
+constexpr char kNetworkEapSimGsmAuthResponse[] = "GSM-AUTH";
+constexpr char kNetworkEapSimUmtsAuthResponse[] = "UMTS-AUTH";
+constexpr char kNetworkEapSimUmtsAutsResponse[] = "UMTS-AUTS";
+constexpr char kNetworkEapSimGsmAuthFailure[] = "GSM-FAIL";
+constexpr char kNetworkEapSimUmtsAuthFailure[] = "UMTS-FAIL";
+
+#ifdef CONFIG_WAPI_INTERFACE
+std::string dummyWapiCertSuite;
+std::vector<uint8_t> dummyWapiPsk;
+#endif /* CONFIG_WAPI_INTERFACE */
+}  // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+using misc_utils::createStatusWithMsg;
+
+StaNetwork::StaNetwork(
+	struct wpa_global *wpa_global, const char ifname[], int network_id)
+	: wpa_global_(wpa_global),
+	  ifname_(ifname),
+	  network_id_(network_id),
+	  is_valid_(true)
+{}
+
+void StaNetwork::invalidate() { is_valid_ = false; }
+bool StaNetwork::isValid()
+{
+	return (is_valid_ && (retrieveNetworkPtr() != nullptr));
+}
+
+::ndk::ScopedAStatus StaNetwork::getId(
+	int32_t* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getInterfaceName(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getInterfaceNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getType(
+	IfaceType* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::registerCallback(
+	const std::shared_ptr<ISupplicantStaNetworkCallback>& in_callback)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSsid(
+	const std::vector<uint8_t>& in_ssid)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setSsidInternal, in_ssid);
+}
+
+::ndk::ScopedAStatus StaNetwork::setBssid(
+	const std::vector<uint8_t>& in_bssid)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setBssidInternal, in_bssid);
+}
+
+::ndk::ScopedAStatus StaNetwork::setDppKeys(const DppConnectionKeys& in_keys)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setDppKeysInternal, in_keys);
+}
+
+::ndk::ScopedAStatus StaNetwork::setScanSsid(bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setScanSsidInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setKeyMgmt(
+	KeyMgmtMask in_keyMgmtMask)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setKeyMgmtInternal, in_keyMgmtMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setProto(
+	ProtoMask in_protoMask)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setProtoInternal, in_protoMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setAuthAlg(
+	AuthAlgMask in_authAlgMask)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setAuthAlgInternal, in_authAlgMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setGroupCipher(
+	GroupCipherMask in_groupCipherMask)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setGroupCipherInternal, in_groupCipherMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPairwiseCipher(
+	PairwiseCipherMask in_pairwiseCipherMask)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setPairwiseCipherInternal,
+		in_pairwiseCipherMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPskPassphrase(
+	const std::string& in_psk)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setPskPassphraseInternal, in_psk);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPsk(
+	const std::vector<uint8_t>& in_psk)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setPskInternal, in_psk);
+}
+
+::ndk::ScopedAStatus StaNetwork::setWepKey(
+	int32_t in_keyIdx, const std::vector<uint8_t>& in_wepKey)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setWepKeyInternal, in_keyIdx, in_wepKey);
+}
+
+::ndk::ScopedAStatus StaNetwork::setWepTxKeyIdx(
+	int32_t in_keyIdx)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setWepTxKeyIdxInternal, in_keyIdx);
+}
+
+::ndk::ScopedAStatus StaNetwork::setRequirePmf(bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setRequirePmfInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapMethod(
+	EapMethod in_method)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapMethodInternal, in_method);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapPhase2Method(
+	EapPhase2Method in_method)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapPhase2MethodInternal, in_method);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapIdentity(
+	const std::vector<uint8_t>& in_identity)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapIdentityInternal, in_identity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapEncryptedImsiIdentity(
+	const std::vector<uint8_t>& in_identity)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapEncryptedImsiIdentityInternal,
+		in_identity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapAnonymousIdentity(
+	const std::vector<uint8_t>& in_identity)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapAnonymousIdentityInternal, in_identity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapPassword(
+	const std::vector<uint8_t>& in_password)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapPasswordInternal, in_password);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapCACert(
+	const std::string& in_path)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapCACertInternal, in_path);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapCAPath(
+	const std::string& in_path)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapCAPathInternal, in_path);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapClientCert(
+	const std::string& in_path)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapClientCertInternal, in_path);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapPrivateKeyId(
+	const std::string& in_id)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapPrivateKeyIdInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapSubjectMatch(
+	const std::string& in_match)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapSubjectMatchInternal, in_match);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapAltSubjectMatch(
+	const std::string& in_match)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapAltSubjectMatchInternal, in_match);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapEngine(bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapEngineInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapEngineID(
+	const std::string& in_id)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapEngineIDInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapDomainSuffixMatch(
+	const std::string& in_match)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapDomainSuffixMatchInternal, in_match);
+}
+
+::ndk::ScopedAStatus StaNetwork::setProactiveKeyCaching(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setProactiveKeyCachingInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setIdStr(
+	const std::string& in_idStr)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setIdStrInternal, in_idStr);
+}
+
+::ndk::ScopedAStatus StaNetwork::setUpdateIdentifier(
+	int32_t in_id)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setUpdateIdentifierInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaNetwork::setWapiCertSuite(
+	const std::string& in_suite)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setWapiCertSuiteInternal, in_suite);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEdmg(bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEdmgInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::getSsid(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getSsidInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus StaNetwork::getBssid(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getBssidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getScanSsid(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getScanSsidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getKeyMgmt(
+	KeyMgmtMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getKeyMgmtInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getProto(
+	ProtoMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getProtoInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getAuthAlg(
+	AuthAlgMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getAuthAlgInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getGroupCipher(
+	GroupCipherMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getGroupCipherInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getPairwiseCipher(
+	PairwiseCipherMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getPairwiseCipherInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getPskPassphrase(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getPskPassphraseInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getPsk(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getPskInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getSaePassword(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getSaePasswordInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getSaePasswordId(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getSaePasswordIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWepKey(
+	int32_t in_keyIdx,
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getWepKeyInternal, _aidl_return, in_keyIdx);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWepTxKeyIdx(
+	int32_t* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getWepTxKeyIdxInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getRequirePmf(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getRequirePmfInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapMethod(
+	EapMethod* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapMethodInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapPhase2Method(
+	EapPhase2Method* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapPhase2MethodInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapIdentity(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapIdentityInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapAnonymousIdentity(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapAnonymousIdentityInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapPassword(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapPasswordInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapCACert(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapCACertInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapCAPath(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapCAPathInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapClientCert(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapClientCertInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapPrivateKeyId(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapPrivateKeyIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapSubjectMatch(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapSubjectMatchInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapAltSubjectMatch(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapAltSubjectMatchInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapEngine(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapEngineInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapEngineId(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapEngineIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapDomainSuffixMatch(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEapDomainSuffixMatchInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getIdStr(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getIdStrInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWpsNfcConfigurationToken(
+	std::vector<uint8_t>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getWpsNfcConfigurationTokenInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWapiCertSuite(
+	std::string* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getWapiCertSuiteInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEdmg(
+	bool* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getEdmgInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::enable(bool in_noConnect)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::enableInternal, in_noConnect);
+}
+
+::ndk::ScopedAStatus StaNetwork::disable()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::disableInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::select()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::selectInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthResponse(
+	const std::vector<NetworkResponseEapSimGsmAuthParams>& in_params)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::sendNetworkEapSimGsmAuthResponseInternal,
+		in_params);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthFailure()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::sendNetworkEapSimGsmAuthFailureInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthResponse(
+	const NetworkResponseEapSimUmtsAuthParams& in_params)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal,
+		in_params);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAutsResponse(
+	const std::vector<uint8_t>& in_auts)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal,
+		in_auts);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthFailure()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapIdentityResponse(
+	const std::vector<uint8_t>& in_identity,
+	const std::vector<uint8_t>& in_encryptedIdentity)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::sendNetworkEapIdentityResponseInternal,
+		in_identity, in_encryptedIdentity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setGroupMgmtCipher(
+	GroupMgmtCipherMask in_groupMgmtCipherMask)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setGroupMgmtCipherInternal,
+		in_groupMgmtCipherMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::getGroupMgmtCipher(
+	GroupMgmtCipherMask* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getGroupMgmtCipherInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::enableTlsSuiteBEapPhase1Param(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::enableTlsSuiteBEapPhase1ParamInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::enableSuiteBEapOpenSslCiphers()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::enableSuiteBEapOpenSslCiphersInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSaePassword(
+	const std::string& in_saePassword)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setSaePasswordInternal, in_saePassword);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSaePasswordId(
+	const std::string& in_saePasswordId)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setSaePasswordIdInternal, in_saePasswordId);
+}
+
+::ndk::ScopedAStatus StaNetwork::setOcsp(
+	OcspType in_ocspType)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setOcspInternal, in_ocspType);
+}
+
+::ndk::ScopedAStatus StaNetwork::getOcsp(
+	OcspType* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::getOcspInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPmkCache(
+	const std::vector<uint8_t>& in_serializedEntry)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setPmkCacheInternal, in_serializedEntry);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapErp(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setEapErpInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSaeH2eMode(
+	SaeH2eMode in_mode)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setSaeH2eModeInternal, in_mode);
+}
+
+::ndk::ScopedAStatus StaNetwork::enableSaePkOnlyMode(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::enableSaePkOnlyModeInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setRoamingConsortiumSelection(
+	const std::vector<uint8_t>& in_selectedRcoi)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+		&StaNetwork::setRoamingConsortiumSelectionInternal, in_selectedRcoi);
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> StaNetwork::getIdInternal()
+{
+	return {network_id_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getInterfaceNameInternal()
+{
+	return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> StaNetwork::getTypeInternal()
+{
+	return {IfaceType::STA, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::registerCallbackInternal(
+	const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
+{
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager || aidl_manager->addStaNetworkCallbackAidlObject(
+				 ifname_, network_id_, callback)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setSsidInternal(const std::vector<uint8_t> &ssid)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (ssid.size() == 0 ||
+		ssid.size() >
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  SSID_MAX_LEN_IN_BYTES)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	if (setByteArrayFieldAndResetState(
+		ssid.data(), ssid.size(), &(wpa_ssid->ssid),
+		&(wpa_ssid->ssid_len), "ssid")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	if (wpa_ssid->passphrase) {
+		wpa_config_update_psk(wpa_ssid);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setBssidInternal(
+	const std::vector<uint8_t> &bssid)
+{
+	if (bssid.size() != ETH_ALEN) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	int prev_bssid_set = wpa_ssid->bssid_set;
+	u8 prev_bssid[ETH_ALEN];
+	os_memcpy(prev_bssid, wpa_ssid->bssid, ETH_ALEN);
+	// Zero'ed array is used to clear out the BSSID value.
+	if (os_memcmp(bssid.data(), kZeroBssid, ETH_ALEN) == 0) {
+		wpa_ssid->bssid_set = 0;
+		wpa_printf(MSG_MSGDUMP, "BSSID any");
+	} else {
+		os_memcpy(wpa_ssid->bssid, bssid.data(), ETH_ALEN);
+		wpa_ssid->bssid_set = 1;
+		wpa_hexdump(MSG_MSGDUMP, "BSSID", wpa_ssid->bssid, ETH_ALEN);
+	}
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if ((wpa_ssid->bssid_set != prev_bssid_set ||
+		 os_memcmp(wpa_ssid->bssid, prev_bssid, ETH_ALEN) != 0)) {
+		wpas_notify_network_bssid_set_changed(wpa_s, wpa_ssid);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setDppKeysInternal(const DppConnectionKeys& keys)
+{
+#ifdef CONFIG_DPP
+	if (keys.connector.empty() || keys.cSign.empty() || keys.netAccessKey.empty()) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::string connector_str(keys.connector.begin(), keys.connector.end());
+
+	if (setStringFieldAndResetState(
+		connector_str.c_str(), &(wpa_ssid->dpp_connector), "dpp_connector")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	if (setByteArrayFieldAndResetState(
+		keys.cSign.data(), keys.cSign.size(), &(wpa_ssid->dpp_csign),
+		&(wpa_ssid->dpp_csign_len), "dpp csign")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	if (setByteArrayFieldAndResetState(
+		keys.netAccessKey.data(), keys.netAccessKey.size(), &(wpa_ssid->dpp_netaccesskey),
+		&(wpa_ssid->dpp_netaccesskey_len), "dpp netAccessKey")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	return ndk::ScopedAStatus::ok();
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+ndk::ScopedAStatus StaNetwork::setScanSsidInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->scan_ssid = enable ? 1 : 0;
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setAuthAlgInternal(
+	AuthAlgMask mask)
+{
+	uint32_t auth_alg_mask = static_cast<uint32_t>(mask);
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (auth_alg_mask & ~kAllowedAuthAlgMask) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	wpa_ssid->auth_alg = auth_alg_mask;
+	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", wpa_ssid->auth_alg);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEdmgInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->enable_edmg = enable ? 1 : 0;
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setPskPassphraseInternal(const std::string &rawPsk)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::string psk = rawPsk;
+#ifdef CONFIG_WAPI_INTERFACE
+	if (wpa_ssid->key_mgmt & WPA_KEY_MGMT_WAPI_PSK) {
+		if (rawPsk.size() > 2 && rawPsk.front()== '"' && rawPsk.back() == '"') {
+			psk = rawPsk.substr(1, rawPsk.size() - 2);
+		} else {
+			if ((rawPsk.size() & 1)) {
+				return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+			}
+			size_t len = psk.size() / 2;
+			uint8_t *buf = (uint8_t *) os_malloc(len);
+			if (hexstr2bin(psk.c_str(), buf, len) < 0) {
+					os_free(buf);
+				return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+			}
+			std::vector<uint8_t> bytes(buf, buf + len);
+			os_free(buf);
+			return setWapiPskInternal(bytes);
+		}
+	}
+#endif
+	if (isPskPassphraseValid(psk)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	if (wpa_ssid->passphrase &&
+		os_strlen(wpa_ssid->passphrase) == psk.size() &&
+		os_memcmp(wpa_ssid->passphrase, psk.c_str(), psk.size()) == 0) {
+		return ndk::ScopedAStatus::ok();
+	}
+	// Flag to indicate if raw psk is calculated or not using
+	// |wpa_config_update_psk|. Deferred if ssid not already set.
+	wpa_ssid->psk_set = 0;
+	if (setStringKeyFieldAndResetState(
+		psk.c_str(), &(wpa_ssid->passphrase), "psk passphrase")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	if (wpa_ssid->ssid_len) {
+		wpa_config_update_psk(wpa_ssid);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setPskInternal(const std::vector<uint8_t> &psk)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
+	str_clear_free(wpa_ssid->passphrase);
+	wpa_ssid->passphrase = nullptr;
+	os_memcpy(wpa_ssid->psk, psk.data(), sizeof(wpa_ssid->psk));
+	wpa_ssid->psk_set = 1;
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setWepKeyInternal(
+	uint32_t key_idx, const std::vector<uint8_t> &wep_key)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_idx >=
+		static_cast<uint32_t>(
+		ISupplicantStaNetwork::WEP_KEYS_MAX_NUM)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	if (wep_key.size() !=
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  WEP40_KEY_LEN_IN_BYTES) &&
+		wep_key.size() !=
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  WEP104_KEY_LEN_IN_BYTES)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	os_memcpy(wpa_ssid->wep_key[key_idx], wep_key.data(), wep_key.size());
+	wpa_ssid->wep_key_len[key_idx] = wep_key.size();
+	std::string msg_dump_title("wep_key" + std::to_string(key_idx));
+	wpa_hexdump_key(
+		MSG_MSGDUMP, msg_dump_title.c_str(), wpa_ssid->wep_key[key_idx],
+		wpa_ssid->wep_key_len[key_idx]);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setWepTxKeyIdxInternal(uint32_t key_idx)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_idx >=
+		static_cast<uint32_t>(
+		ISupplicantStaNetwork::WEP_KEYS_MAX_NUM)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	wpa_ssid->wep_tx_keyidx = key_idx;
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setRequirePmfInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (enable) {
+		wpa_ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+	}
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapMethodInternal(
+	EapMethod method)
+{
+	uint32_t eap_method_idx = static_cast<
+		std::underlying_type<EapMethod>::type>(
+		method);
+	if (eap_method_idx >= kEapMethodMax) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	int retrieved_vendor, retrieved_method;
+	const char *method_str = kEapMethodStrings[eap_method_idx];
+	// This string lookup is needed to check if the device supports the
+	// corresponding EAP type.
+	retrieved_method = eap_peer_get_type(method_str, &retrieved_vendor);
+	if (retrieved_vendor == EAP_VENDOR_IETF &&
+		retrieved_method == EAP_TYPE_NONE) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	if (wpa_ssid->eap.eap_methods) {
+		os_free(wpa_ssid->eap.eap_methods);
+	}
+	// wpa_supplicant can support setting multiple eap methods for each
+	// network. But, this is not really used by Android. So, just adding
+	// support for setting one EAP method for each network. The additional
+	// |eap_method_type| member in the array is used to indicate the end
+	// of list.
+	wpa_ssid->eap.eap_methods =
+		(eap_method_type *)os_malloc(sizeof(eap_method_type) * 2);
+	if (!wpa_ssid->eap.eap_methods) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	wpa_ssid->eap.eap_methods[0].vendor = retrieved_vendor;
+	wpa_ssid->eap.eap_methods[0].method = retrieved_method;
+	wpa_ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
+	wpa_ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
+
+	wpa_ssid->leap = 0;
+	wpa_ssid->non_leap = 0;
+	if (retrieved_vendor == EAP_VENDOR_IETF &&
+		retrieved_method == EAP_TYPE_LEAP) {
+		wpa_ssid->leap++;
+	} else {
+		wpa_ssid->non_leap++;
+	}
+	wpa_hexdump(
+		MSG_MSGDUMP, "eap methods", (u8 *)wpa_ssid->eap.eap_methods,
+		sizeof(eap_method_type) * 2);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapPhase2MethodInternal(
+	EapPhase2Method method)
+{
+	uint32_t eap_phase2_method_idx = static_cast<
+		std::underlying_type<EapPhase2Method>::type>(
+		method);
+	if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// EAP method needs to be set for us to construct the eap
+	// phase 2 method string.
+	ndk::ScopedAStatus status;
+	EapMethod eap_method;
+	std::tie(eap_method, status) = getEapMethodInternal();
+	if (!status.isOk()) {
+		return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+			"EAP method not set");
+	}
+	std::string eap_phase2_str;
+	if (method == EapPhase2Method::NONE) {
+		eap_phase2_str = "";
+	} else if (
+		eap_method == EapMethod::TTLS &&
+		method == EapPhase2Method::GTC) {
+		eap_phase2_str = kEapPhase2AuthEapPrefix;
+	} else {
+		eap_phase2_str = kEapPhase2AuthPrefix;
+	}
+	eap_phase2_str += kEapPhase2MethodStrings[eap_phase2_method_idx];
+	if (setStringFieldAndResetState(
+		eap_phase2_str.c_str(), &(wpa_ssid->eap.phase2),
+		"eap phase2")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapIdentityInternal(
+	const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+		&(wpa_ssid->eap.identity_len), "eap identity")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	// plain IMSI identity
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(),
+		&(wpa_ssid->eap.imsi_identity),
+		&(wpa_ssid->eap.imsi_identity_len), "eap imsi identity")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapEncryptedImsiIdentityInternal(
+	const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// encrypted IMSI identity
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+		&(wpa_ssid->eap.identity_len), "eap encrypted imsi identity")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapAnonymousIdentityInternal(
+	const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// If current supplicant pseudonym is the prefix of new pseudonym,
+	// the credential is not changed, just update the decoration.
+	// As a result, no need to reset the state.
+	// The decorated identity will have a postfix like
+	// @mncXXX.mccYYY.3gppnetwork.org, so the length will be always
+	// greater than the current one.
+	bool resetState = wpa_ssid->eap.anonymous_identity == NULL
+		|| wpa_ssid->eap.anonymous_identity_len == 0
+		|| identity.size() == 0
+		|| wpa_ssid->eap.anonymous_identity_len >= identity.size()
+		|| os_strncmp((char *) identity.data(),
+			(char *) wpa_ssid->eap.anonymous_identity,
+			wpa_ssid->eap.anonymous_identity_len) != 0;
+	if (setByteArrayField(
+		identity.data(), identity.size(),
+		&(wpa_ssid->eap.anonymous_identity),
+		&(wpa_ssid->eap.anonymous_identity_len),
+		"eap anonymous_identity", resetState)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapPasswordInternal(
+	const std::vector<uint8_t> &password)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setByteArrayKeyFieldAndResetState(
+		password.data(), password.size(), &(wpa_ssid->eap.password),
+		&(wpa_ssid->eap.password_len), "eap password")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
+	wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapCACertInternal(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		path.c_str(), &(wpa_ssid->eap.cert.ca_cert), "eap ca_cert")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapCAPathInternal(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		path.c_str(), &(wpa_ssid->eap.cert.ca_path), "eap ca_path")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapClientCertInternal(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		path.c_str(), &(wpa_ssid->eap.cert.client_cert),
+		"eap client_cert")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapPrivateKeyIdInternal(const std::string &id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		id.c_str(), &(wpa_ssid->eap.cert.key_id), "eap key_id")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapSubjectMatchInternal(
+	const std::string &match)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		match.c_str(), &(wpa_ssid->eap.cert.subject_match),
+		"eap subject_match")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapAltSubjectMatchInternal(
+	const std::string &match)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		match.c_str(), &(wpa_ssid->eap.cert.altsubject_match),
+		"eap altsubject_match")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapEngineInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->eap.cert.engine = enable ? 1 : 0;
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapEngineIDInternal(const std::string &id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		id.c_str(), &(wpa_ssid->eap.cert.engine_id), "eap engine_id")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapDomainSuffixMatchInternal(
+	const std::string &match)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		match.c_str(), &(wpa_ssid->eap.cert.domain_suffix_match),
+		"eap domain_suffix_match")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setProactiveKeyCachingInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->proactive_key_caching = enable ? 1 : 0;
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setIdStrInternal(const std::string &id_str)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		id_str.c_str(), &(wpa_ssid->id_str), "id_str")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setUpdateIdentifierInternal(uint32_t id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->update_identifier = id;
+	wpa_printf(
+		MSG_MSGDUMP, "update_identifier: %d", wpa_ssid->update_identifier);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setWapiCertSuiteInternal(const std::string &suite)
+{
+#ifdef CONFIG_WAPI_INTERFACE
+	// Dummy implementation
+	dummyWapiCertSuite = suite;
+	return ndk::ScopedAStatus::ok();
+#else
+	return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN, "Not implemented");
+#endif
+}
+
+ndk::ScopedAStatus StaNetwork::setWapiPskInternal(const std::vector<uint8_t> &psk)
+{
+#ifdef CONFIG_WAPI_INTERFACE
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	str_clear_free(wpa_ssid->passphrase);
+	wpa_ssid->passphrase = nullptr;
+
+	// Dummy implementation
+	dummyWapiPsk = psk;
+
+	wpa_ssid->psk_set = 1;
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> StaNetwork::getSsidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::vector<uint8_t> ssid(
+		wpa_ssid->ssid,
+		wpa_ssid->ssid + wpa_ssid->ssid_len);
+	return {std::move(ssid), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getBssidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::vector<uint8_t> bssid(kZeroBssid, kZeroBssid + ETH_ALEN);
+	if (wpa_ssid->bssid_set) {
+		bssid.assign(wpa_ssid->bssid, wpa_ssid->bssid + ETH_ALEN);
+	}
+	return {std::move(bssid), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getScanSsidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {(wpa_ssid->scan_ssid == 1), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<AuthAlgMask, ndk::ScopedAStatus>
+StaNetwork::getAuthAlgInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t auth_alg_mask = wpa_ssid->auth_alg & kAllowedAuthAlgMask;
+	return {static_cast<AuthAlgMask>(auth_alg_mask), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getPskPassphraseInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+#ifdef CONFIG_WAPI_INTERFACE
+	if (wpa_ssid->key_mgmt & WPA_KEY_MGMT_WAPI_PSK) {
+		if (wpa_ssid->psk_set) {
+			std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> ret = getWapiPskInternal();
+			std::string psk;
+			char buf[3] = {0};
+			for (int i = 0; i < ret.second.size(); i++) {
+				snprintf(buf, sizeof(buf), "%02x", ret.second[i]);
+				psk.append(buf);
+			}
+			return {psk, ndk::ScopedAStatus::ok()};
+		} else {
+			if (!wpa_ssid->passphrase) {
+				return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+			}
+			std::string passphrase;
+			passphrase.append("\"");
+			passphrase.append(wpa_ssid->passphrase);
+			passphrase.append("\"");
+			return {passphrase, ndk::ScopedAStatus::ok()};
+		}
+	}
+#endif
+	if (!wpa_ssid->passphrase) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {wpa_ssid->passphrase, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getPskInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
+	if (!wpa_ssid->psk_set) {
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	std::vector<uint8_t> psk(wpa_ssid->psk, wpa_ssid->psk + 32);
+	return {psk, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getSaePasswordInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->sae_password) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->sae_password),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getSaePasswordIdInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->sae_password_id) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->sae_password_id),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> StaNetwork::getWepKeyInternal(
+	uint32_t key_idx)
+{
+	std::vector<uint8_t> wep_key;
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_idx >=
+		static_cast<uint32_t>(
+		ISupplicantStaNetwork::WEP_KEYS_MAX_NUM)) {
+		return {wep_key,
+			createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+	}
+	wep_key.assign(
+		wpa_ssid->wep_key[key_idx],
+		wpa_ssid->wep_key[key_idx] + wpa_ssid->wep_key_len[key_idx]);
+	return {std::move(wep_key), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> StaNetwork::getWepTxKeyIdxInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {wpa_ssid->wep_tx_keyidx, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getRequirePmfInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {(wpa_ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<EapMethod, ndk::ScopedAStatus>
+StaNetwork::getEapMethodInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.eap_methods) {
+		return {static_cast<EapMethod>(0),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	// wpa_supplicant can support setting multiple eap methods for each
+	// network. But, this is not really used by Android. So, just reading
+	// the first EAP method for each network.
+	const std::string eap_method_str = eap_get_name(
+		wpa_ssid->eap.eap_methods[0].vendor,
+		static_cast<enum eap_type>(wpa_ssid->eap.eap_methods[0].method));
+	size_t eap_method_idx =
+		std::find(
+		std::begin(kEapMethodStrings), std::end(kEapMethodStrings),
+		eap_method_str) -
+		std::begin(kEapMethodStrings);
+	if (eap_method_idx >= kEapMethodMax) {
+		return {static_cast<EapMethod>(0),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {static_cast<EapMethod>(eap_method_idx), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<EapPhase2Method, ndk::ScopedAStatus>
+StaNetwork::getEapPhase2MethodInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.phase2) {
+		return {static_cast<EapPhase2Method>(0),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	const std::string eap_phase2_method_str_with_prefix =
+		wpa_ssid->eap.phase2;
+	std::string eap_phase2_method_str;
+	// Strip out the phase 2 method prefix before doing a reverse lookup
+	// of phase 2 string to the Eap Phase 2 type.
+	if (eap_phase2_method_str_with_prefix.find(kEapPhase2AuthPrefix) == 0) {
+		eap_phase2_method_str =
+			eap_phase2_method_str_with_prefix.substr(
+			strlen(kEapPhase2AuthPrefix),
+			eap_phase2_method_str_with_prefix.size());
+	} else if (
+		eap_phase2_method_str_with_prefix.find(kEapPhase2AuthEapPrefix) ==
+		0) {
+		eap_phase2_method_str =
+			eap_phase2_method_str_with_prefix.substr(
+			strlen(kEapPhase2AuthEapPrefix),
+			eap_phase2_method_str_with_prefix.size());
+	}
+	size_t eap_phase2_method_idx =
+		std::find(
+		std::begin(kEapPhase2MethodStrings),
+		std::end(kEapPhase2MethodStrings), eap_phase2_method_str) -
+		std::begin(kEapPhase2MethodStrings);
+	if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+		return {static_cast<EapPhase2Method>(0),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {static_cast<EapPhase2Method>(eap_phase2_method_idx),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getEapIdentityInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.identity) {
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {std::vector<uint8_t>(
+			wpa_ssid->eap.identity,
+			wpa_ssid->eap.identity + wpa_ssid->eap.identity_len),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getEapAnonymousIdentityInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.anonymous_identity) {
+		return {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {std::vector<uint8_t>(
+			wpa_ssid->eap.anonymous_identity,
+			wpa_ssid->eap.anonymous_identity +
+			wpa_ssid->eap.anonymous_identity_len),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getEapPasswordInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.password) {
+		return {std::vector<uint8_t>(), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {std::vector<uint8_t>(
+			wpa_ssid->eap.password,
+			wpa_ssid->eap.password + wpa_ssid->eap.password_len),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapCACertInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.ca_cert) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->eap.cert.ca_cert),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapCAPathInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.ca_path) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->eap.cert.ca_path),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapClientCertInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.client_cert) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->eap.cert.client_cert),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapPrivateKeyIdInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.key_id) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(reinterpret_cast<char *>(wpa_ssid->eap.cert.key_id)),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapSubjectMatchInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.subject_match) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->eap.cert.subject_match),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapAltSubjectMatchInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.altsubject_match) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->eap.cert.altsubject_match),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getEapEngineInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {wpa_ssid->eap.cert.engine == 1, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapEngineIdInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.engine_id) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->eap.cert.engine_id),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapDomainSuffixMatchInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.cert.domain_suffix_match) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->eap.cert.domain_suffix_match),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getIdStrInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->id_str) {
+		return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::charBufToString(wpa_ssid->id_str),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getEdmgInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {(wpa_ssid->enable_edmg == 1), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+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 {std::vector<uint8_t>(),
+			createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {misc_utils::convertWpaBufToVector(token_buf.get()),
+		ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getWapiCertSuiteInternal()
+{
+#ifdef CONFIG_WAPI_INTERFACE
+	// Dummy implementation
+	return {dummyWapiCertSuite, ndk::ScopedAStatus::ok()};
+#else
+	return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+#endif
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> StaNetwork::getWapiPskInternal()
+{
+#ifdef CONFIG_WAPI_INTERFACE
+	// Dummy implementation
+	return {dummyWapiPsk, ndk::ScopedAStatus::ok()};
+#else
+	return {std::vector<uint8_t>(),
+		createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+#endif
+}
+
+ndk::ScopedAStatus StaNetwork::enableInternal(bool no_connect)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid->disabled == 2) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (no_connect) {
+		wpa_ssid->disabled = 0;
+	} else {
+		wpa_s->scan_min_time.sec = 0;
+		wpa_s->scan_min_time.usec = 0;
+		wpa_supplicant_enable_network(wpa_s, wpa_ssid);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::disableInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid->disabled == 2) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_supplicant_disable_network(wpa_s, wpa_ssid);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::selectInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid->disabled == 2) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->scan_min_time.sec = 0;
+	wpa_s->scan_min_time.usec = 0;
+	wpa_supplicant_select_network(wpa_s, wpa_ssid);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthResponseInternal(
+	const std::vector<NetworkResponseEapSimGsmAuthParams>
+	&vec_params)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// Convert the incoming parameters to a string to pass to
+	// wpa_supplicant.
+	std::string ctrl_rsp_param = std::string(kNetworkEapSimGsmAuthResponse);
+	for (const auto &params : vec_params) {
+		uint32_t kc_hex_len = params.kc.size() * 2 + 1;
+		std::vector<char> kc_hex(kc_hex_len);
+		uint32_t sres_hex_len = params.sres.size() * 2 + 1;
+		std::vector<char> sres_hex(sres_hex_len);
+		wpa_snprintf_hex(
+			kc_hex.data(), kc_hex.size(), params.kc.data(),
+			params.kc.size());
+		wpa_snprintf_hex(
+			sres_hex.data(), sres_hex.size(), params.sres.data(),
+			params.sres.size());
+		ctrl_rsp_param += ":" + std::string(kc_hex.data()) + ":" +
+				  std::string(sres_hex.data());
+	}
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+		MSG_DEBUG, "network sim gsm auth response param",
+		(const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthFailureInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimGsmAuthFailure,
+		strlen(kNetworkEapSimGsmAuthFailure))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal(
+	const NetworkResponseEapSimUmtsAuthParams &params)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// Convert the incoming parameters to a string to pass to
+	// wpa_supplicant.
+	uint32_t ik_hex_len = params.ik.size() * 2 + 1;
+	std::vector<char> ik_hex(ik_hex_len);
+	uint32_t ck_hex_len = params.ck.size() * 2 + 1;
+	std::vector<char> ck_hex(ck_hex_len);
+	uint32_t res_hex_len = params.res.size() * 2 + 1;
+	std::vector<char> res_hex(res_hex_len);
+	wpa_snprintf_hex(
+		ik_hex.data(), ik_hex.size(), params.ik.data(), params.ik.size());
+	wpa_snprintf_hex(
+		ck_hex.data(), ck_hex.size(), params.ck.data(), params.ck.size());
+	wpa_snprintf_hex(
+		res_hex.data(), res_hex.size(), params.res.data(),
+		params.res.size());
+	std::string ctrl_rsp_param =
+		std::string(kNetworkEapSimUmtsAuthResponse) + ":" +
+		std::string(ik_hex.data()) + ":" + std::string(ck_hex.data()) +
+		":" + std::string(res_hex.data());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+		MSG_DEBUG, "network sim umts auth response param",
+		(const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal(
+	const std::vector<uint8_t> &auts)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t auts_hex_len = auts.size() * 2 + 1;
+	std::vector<char> auts_hex(auts_hex_len);
+	wpa_snprintf_hex(
+		auts_hex.data(), auts_hex.size(), auts.data(), auts.size());
+	std::string ctrl_rsp_param =
+		std::string(kNetworkEapSimUmtsAutsResponse) + ":" +
+		std::string(auts_hex.data());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+		MSG_DEBUG, "network sim umts auts response param",
+		(const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimUmtsAuthFailure,
+		strlen(kNetworkEapSimUmtsAuthFailure))) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapIdentityResponseInternal(
+	const std::vector<uint8_t> &identity,
+	const std::vector<uint8_t> &encrypted_imsi_identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::string ctrl_rsp_param(identity.begin(), identity.end());
+	// If encrypted identity is included, format is:
+	// plain identity + ":" + encrypted_identity
+	if (encrypted_imsi_identity.size() != 0) {
+		ctrl_rsp_param += ":" + std::string(
+			encrypted_imsi_identity.begin(), encrypted_imsi_identity.end());
+	}
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+		MSG_DEBUG, "network identity response param",
+		(const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::enableTlsSuiteBEapPhase1ParamInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	int val = enable == true ? 1 : 0;
+	std::string suiteb_phase1("tls_suiteb=" + std::to_string(val));
+
+	if (setStringKeyFieldAndResetState(
+		suiteb_phase1.c_str(), &(wpa_ssid->eap.phase1), "phase1")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::enableSuiteBEapOpenSslCiphersInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	const char openssl_suiteb_cipher[] = "SUITEB192";
+
+	if (setStringKeyFieldAndResetState(
+		openssl_suiteb_cipher, &(wpa_ssid->eap.openssl_ciphers),
+		"openssl_ciphers")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setSaePasswordInternal(
+	const std::string &sae_password)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (sae_password.length() < 1) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	if (wpa_ssid->sae_password &&
+		os_strlen(wpa_ssid->sae_password) == sae_password.length() &&
+		os_memcmp(
+		wpa_ssid->sae_password, sae_password.c_str(),
+		sae_password.length()) == 0) {
+		return ndk::ScopedAStatus::ok();
+	}
+	wpa_ssid->psk_set = 1;
+	if (setStringKeyFieldAndResetState(
+		sae_password.c_str(), &(wpa_ssid->sae_password),
+		"sae password")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setSaePasswordIdInternal(
+	const std::string &sae_password_id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (sae_password_id.length() < 1) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	if (wpa_ssid->sae_password_id &&
+		os_strlen(wpa_ssid->sae_password_id) == sae_password_id.length() &&
+		os_memcmp(
+		wpa_ssid->sae_password_id, sae_password_id.c_str(),
+		sae_password_id.length()) == 0) {
+		return ndk::ScopedAStatus::ok();
+	}
+	wpa_ssid->psk_set = 1;
+	if (setStringKeyFieldAndResetState(
+		sae_password_id.c_str(), &(wpa_ssid->sae_password_id),
+		"sae password id")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setGroupMgmtCipherInternal(
+		GroupMgmtCipherMask mask)
+{
+	uint32_t group_mgmt_cipher_mask = static_cast<uint32_t>(mask);
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (group_mgmt_cipher_mask & ~kAllowedGroupMgmtCipherMask) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	wpa_ssid->group_mgmt_cipher = group_mgmt_cipher_mask;
+	wpa_printf(MSG_MSGDUMP, "group_mgmt_cipher: 0x%x",
+			wpa_ssid->group_mgmt_cipher);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<GroupMgmtCipherMask, ndk::ScopedAStatus>
+StaNetwork::getGroupMgmtCipherInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t group_mgmt_cipher_mask =
+			wpa_ssid->group_mgmt_cipher & kAllowedGroupMgmtCipherMask;
+	return {static_cast<GroupMgmtCipherMask>(group_mgmt_cipher_mask),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setOcspInternal(OcspType ocspType) {
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (ocspType < OcspType::NONE || ocspType > OcspType::REQUIRE_ALL_CERTS_STATUS) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	wpa_ssid->eap.cert.ocsp = (int) ocspType;
+	wpa_printf(
+		MSG_MSGDUMP, "ocsp: %d", wpa_ssid->eap.cert.ocsp);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<OcspType, ndk::ScopedAStatus> StaNetwork::getOcspInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {static_cast<OcspType>(wpa_ssid->eap.cert.ocsp),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setPmkCacheInternal(const std::vector<uint8_t>& serializedEntry) {
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	struct rsn_pmksa_cache_entry *new_entry = NULL;
+
+	new_entry = (struct rsn_pmksa_cache_entry *) os_zalloc(sizeof(*new_entry));
+	if (!new_entry) {
+		return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+			"Allocating memory failed");
+	}
+
+	std::stringstream ss(
+		std::stringstream::in | std::stringstream::out | std::stringstream::binary);
+	ss.write((char *) serializedEntry.data(), std::streamsize(serializedEntry.size()));
+	misc_utils::deserializePmkCacheEntry(ss, new_entry);
+	new_entry->network_ctx = wpa_ssid;
+
+	// If there is an entry has a later expiration, ignore this one.
+	struct rsn_pmksa_cache_entry *existing_entry = wpa_sm_pmksa_cache_get(
+		wpa_s->wpa, new_entry->aa, NULL, NULL, new_entry->akmp);
+	if (NULL != existing_entry &&
+		existing_entry->expiration >= new_entry->expiration) {
+		return ndk::ScopedAStatus::ok();
+	}
+
+	wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, new_entry);
+
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setKeyMgmtInternal(
+	KeyMgmtMask mask)
+{
+	uint32_t key_mgmt_mask = static_cast<uint32_t>(mask);
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_mgmt_mask & ~kAllowedKeyMgmtMask) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	setFastTransitionKeyMgmt(key_mgmt_mask);
+
+	if (key_mgmt_mask & WPA_KEY_MGMT_OWE) {
+		// Do not allow to connect to Open network when OWE is selected
+		wpa_ssid->owe_only = 1;
+	}
+	wpa_ssid->key_mgmt = key_mgmt_mask;
+	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", wpa_ssid->key_mgmt);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<KeyMgmtMask, ndk::ScopedAStatus>
+StaNetwork::getKeyMgmtInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t key_mgmt_mask = wpa_ssid->key_mgmt & kAllowedKeyMgmtMask;
+
+	resetFastTransitionKeyMgmt(key_mgmt_mask);
+	return {static_cast<KeyMgmtMask>(key_mgmt_mask),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setProtoInternal(
+	ProtoMask mask)
+{
+	uint32_t proto_mask = static_cast<uint32_t>(mask);
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (proto_mask & ~kAllowedProtoMask) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	wpa_ssid->proto = proto_mask;
+	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", wpa_ssid->proto);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<ProtoMask, ndk::ScopedAStatus>
+StaNetwork::getProtoInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t proto_mask = wpa_ssid->proto & kAllowedProtoMask;
+	return {static_cast<ProtoMask>(proto_mask), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setGroupCipherInternal(
+	GroupCipherMask mask)
+{
+	uint32_t group_cipher_mask = static_cast<uint32_t>(mask);
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (group_cipher_mask & ~kAllowedGroupCipherMask) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	wpa_ssid->group_cipher = group_cipher_mask;
+	wpa_printf(MSG_MSGDUMP, "group_cipher: 0x%x", wpa_ssid->group_cipher);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<GroupCipherMask, ndk::ScopedAStatus>
+StaNetwork::getGroupCipherInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t group_cipher_mask = wpa_ssid->group_cipher & kAllowedGroupCipherMask;
+	return {static_cast<GroupCipherMask>(group_cipher_mask),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setPairwiseCipherInternal(
+	PairwiseCipherMask mask)
+{
+	uint32_t pairwise_cipher_mask = static_cast<uint32_t>(mask);
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (pairwise_cipher_mask & ~kAllowedPairwisewCipherMask) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	wpa_ssid->pairwise_cipher = pairwise_cipher_mask;
+	wpa_printf(
+		MSG_MSGDUMP, "pairwise_cipher: 0x%x", wpa_ssid->pairwise_cipher);
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<PairwiseCipherMask, ndk::ScopedAStatus>
+StaNetwork::getPairwiseCipherInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t pairwise_cipher_mask = wpa_ssid->pairwise_cipher & kAllowedPairwisewCipherMask;
+	return {static_cast<PairwiseCipherMask>(pairwise_cipher_mask),
+		ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setRoamingConsortiumSelectionInternal(
+	const std::vector<uint8_t> &selectedRcoi)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid == NULL) {
+		return createStatus(SupplicantStatusCode::FAILURE_NETWORK_INVALID);
+	}
+
+	if (setByteArrayFieldAndResetState(
+		selectedRcoi.data(), selectedRcoi.size(),
+		&(wpa_ssid->roaming_consortium_selection),
+		&(wpa_ssid->roaming_consortium_selection_len),
+		"roaming_consortium_selection")) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface
+ * this network belong to
+ * is removed, all RPC method calls on this object will
+ * return failure.
+ */
+struct wpa_ssid *StaNetwork::retrieveNetworkPtr()
+{
+	wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (!wpa_s)
+		return nullptr;
+	return wpa_config_get_network(wpa_s->conf, network_id_);
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for
+ * this network.
+ */
+struct wpa_supplicant *StaNetwork::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+
+/**
+ * Check if the provided psk passhrase is valid or not.
+ *
+ * Returns 0 if valid, 1 otherwise.
+ */
+int StaNetwork::isPskPassphraseValid(const std::string &psk)
+{
+	if (psk.size() <
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+		psk.size() >
+		static_cast<uint32_t>(ISupplicantStaNetwork::
+					  PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
+		return 1;
+	}
+	if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * Reset internal wpa_supplicant state machine state
+ * after params update (except
+ * bssid).
+ */
+void StaNetwork::resetInternalStateAfterParamsUpdate()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+
+	wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_ssid);
+
+	if (wpa_s->current_ssid == wpa_ssid || wpa_s->current_ssid == NULL) {
+		/*
+		 * Invalidate the EAP session cache if
+		 * anything in the
+		 * current or previously used
+		 * configuration changes.
+		 */
+		eapol_sm_invalidate_cached_session(wpa_s->eapol);
+	}
+}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setStringFieldAndResetState(
+	const char *value, uint8_t **to_update_field, const char *hexdump_prefix)
+{
+	return setStringFieldAndResetState(
+		value, (char **)to_update_field, hexdump_prefix);
+}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setStringFieldAndResetState(
+	const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+	int value_len = strlen(value);
+	if (*to_update_field) {
+		os_free(*to_update_field);
+	}
+	*to_update_field = dup_binstr(value, value_len);
+	if (!(*to_update_field)) {
+		return 1;
+	}
+	wpa_hexdump_ascii(
+		MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+	resetInternalStateAfterParamsUpdate();
+	return 0;
+}
+
+/**
+ * Helper function to set value in a string key field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setStringKeyFieldAndResetState(
+	const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+	int value_len = strlen(value);
+	if (*to_update_field) {
+		str_clear_free(*to_update_field);
+	}
+	*to_update_field = dup_binstr(value, value_len);
+	if (!(*to_update_field)) {
+		return 1;
+	}
+	wpa_hexdump_ascii_key(
+		MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+	resetInternalStateAfterParamsUpdate();
+	return 0;
+}
+
+/**
+ * Helper function to set value in a string field with a corresponding length
+ * field in |wpa_ssid| structure instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setByteArrayField(
+	const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+	size_t *to_update_field_len, const char *hexdump_prefix, bool resetState)
+{
+	if (*to_update_field) {
+		os_free(*to_update_field);
+	}
+	*to_update_field = (uint8_t *)os_malloc(value_len);
+	if (!(*to_update_field)) {
+		return 1;
+	}
+	os_memcpy(*to_update_field, value, value_len);
+	*to_update_field_len = value_len;
+
+	wpa_hexdump_ascii(
+		MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+		*to_update_field_len);
+
+	if (resetState) {
+		resetInternalStateAfterParamsUpdate();
+	}
+	return 0;
+}
+
+/**
+ * Helper function to set value in a string field with a corresponding length
+ * field in |wpa_ssid| structure instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setByteArrayFieldAndResetState(
+	const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+	size_t *to_update_field_len, const char *hexdump_prefix)
+{
+	return setByteArrayField(value, value_len, to_update_field,
+		to_update_field_len, hexdump_prefix, true);
+}
+
+/**
+ * Helper function to set value in a string key field with a corresponding
+ * length field in |wpa_ssid| structue instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setByteArrayKeyFieldAndResetState(
+	const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+	size_t *to_update_field_len, const char *hexdump_prefix)
+{
+	if (*to_update_field) {
+		bin_clear_free(*to_update_field, *to_update_field_len);
+	}
+	*to_update_field = (uint8_t *)os_malloc(value_len);
+	if (!(*to_update_field)) {
+		return 1;
+	}
+	os_memcpy(*to_update_field, value, value_len);
+	*to_update_field_len = value_len;
+
+	wpa_hexdump_ascii_key(
+		MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+		*to_update_field_len);
+	resetInternalStateAfterParamsUpdate();
+	return 0;
+}
+
+/**
+ * Helper function to set the fast transition bits in the key management
+ * bitmask, to allow FT support when possible.
+ */
+void StaNetwork::setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	int res;
+	struct wpa_driver_capa capa;
+
+	if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
+		key_mgmt_mask |= WPA_KEY_MGMT_FT_PSK;
+	}
+
+	if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
+		key_mgmt_mask |= WPA_KEY_MGMT_FT_IEEE8021X;
+	}
+
+	res = wpa_drv_get_capa(wpa_s, &capa);
+	if (res == 0) {
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_SAE
+		if ((key_mgmt_mask & WPA_KEY_MGMT_SAE) &&
+			(capa.key_mgmt_iftype[WPA_IF_STATION] & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE)) {
+			key_mgmt_mask |= WPA_KEY_MGMT_FT_SAE;
+		}
+#endif
+#endif
+	}
+
+}
+
+/**
+ * Helper function to reset the fast transition bits in the key management
+ * bitmask.
+ */
+void StaNetwork::resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
+{
+	if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
+		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_PSK;
+	}
+
+	if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
+		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_IEEE8021X;
+	}
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_SAE
+	if (key_mgmt_mask & WPA_KEY_MGMT_SAE) {
+		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_SAE;
+	}
+#endif
+#endif
+}
+
+/**
+ * Helper function to enable erp keys generation while connecting to FILS
+ * enabled APs.
+ */
+ndk::ScopedAStatus StaNetwork::setEapErpInternal(bool enable)
+{
+#ifdef CONFIG_FILS
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->eap.erp = enable ? 1 : 0;
+	return ndk::ScopedAStatus::ok();
+#else /* CONFIG_FILS */
+	return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif /* CONFIG_FILS */
+}
+
+ndk::ScopedAStatus StaNetwork::setSaeH2eModeInternal(
+	SaeH2eMode mode)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	switch (mode) {
+	case SaeH2eMode::DISABLED:
+		wpa_s->conf->sae_pwe = 0;
+		break;
+	case SaeH2eMode::H2E_MANDATORY:
+		wpa_s->conf->sae_pwe = 1;
+		break;
+	case SaeH2eMode::H2E_OPTIONAL:
+		wpa_s->conf->sae_pwe = 2;
+		break;
+	}
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::enableSaePkOnlyModeInternal(bool enable)
+{
+#ifdef CONFIG_SAE_PK
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->sae_pk = enable ? SAE_PK_MODE_ONLY : SAE_PK_MODE_AUTOMATIC;
+	resetInternalStateAfterParamsUpdate();
+	return ndk::ScopedAStatus::ok();
+#else
+	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/wpa_supplicant/aidl/sta_network.h b/wpa_supplicant/aidl/sta_network.h
new file mode 100644
index 0000000..524f44a
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_network.h
@@ -0,0 +1,353 @@
+/*
+ * WPA Supplicant - Sta network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_STA_NETWORK_H
+#define WPA_SUPPLICANT_AIDL_STA_NETWORK_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaNetwork.h>
+#include <aidl/android/hardware/wifi/supplicant/EapMethod.h>
+#include <aidl/android/hardware/wifi/supplicant/EapPhase2Method.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.h>
+#include <aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.h>
+#include <aidl/android/hardware/wifi/supplicant/SaeH2eMode.h>
+#include <aidl/android/hardware/wifi/supplicant/DppConnectionKeys.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "config.h"
+#include "wpa_supplicant_i.h"
+#include "notify.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "eap_peer/eap.h"
+#include "rsn_supp/wpa.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of StaNetwork aidl object. Each unique aidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class StaNetwork : public BnSupplicantStaNetwork
+{
+public:
+	StaNetwork(
+		struct wpa_global* wpa_global, const char ifname[], int network_id);
+	~StaNetwork() override = default;
+	// Refer to |StaIface::invalidate()|.
+	void invalidate();
+	bool isValid();
+
+	// Aidl methods exposed.
+  	::ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
+	::ndk::ScopedAStatus getInterfaceName(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+	::ndk::ScopedAStatus registerCallback(
+		const std::shared_ptr<ISupplicantStaNetworkCallback>& in_callback) override;
+	::ndk::ScopedAStatus setSsid(const std::vector<uint8_t>& in_ssid) override;
+	::ndk::ScopedAStatus setBssid(const std::vector<uint8_t>& in_bssid) override;
+	::ndk::ScopedAStatus setDppKeys(const DppConnectionKeys& in_keys) override;
+	::ndk::ScopedAStatus setScanSsid(bool in_enable) override;
+	::ndk::ScopedAStatus setKeyMgmt(KeyMgmtMask in_keyMgmtMask) override;
+	::ndk::ScopedAStatus setProto(ProtoMask in_protoMask) override;
+	::ndk::ScopedAStatus setAuthAlg(AuthAlgMask in_authAlgMask) override;
+	::ndk::ScopedAStatus setGroupCipher(GroupCipherMask in_groupCipherMask) override;
+	::ndk::ScopedAStatus setPairwiseCipher(
+		PairwiseCipherMask in_pairwiseCipherMask) override;
+	::ndk::ScopedAStatus setPskPassphrase(const std::string& in_psk) override;
+	::ndk::ScopedAStatus setPsk(const std::vector<uint8_t>& in_psk) override;
+	::ndk::ScopedAStatus setWepKey(
+		int32_t in_keyIdx, const std::vector<uint8_t>& in_wepKey) override;
+	::ndk::ScopedAStatus setWepTxKeyIdx(int32_t in_keyIdx) override;
+	::ndk::ScopedAStatus setRequirePmf(bool in_enable) override;
+	::ndk::ScopedAStatus setEapMethod(EapMethod in_method) override;
+	::ndk::ScopedAStatus setEapPhase2Method(EapPhase2Method in_method) override;
+	::ndk::ScopedAStatus setEapIdentity(
+		const std::vector<uint8_t>& in_identity) override;
+	::ndk::ScopedAStatus setEapEncryptedImsiIdentity(
+		const std::vector<uint8_t>& in_identity) override;
+	::ndk::ScopedAStatus setEapAnonymousIdentity(
+		const std::vector<uint8_t>& in_identity) override;
+	::ndk::ScopedAStatus setEapPassword(
+		const std::vector<uint8_t>& in_password) override;
+	::ndk::ScopedAStatus setEapCACert(const std::string& in_path) override;
+	::ndk::ScopedAStatus setEapCAPath(const std::string& in_path) override;
+	::ndk::ScopedAStatus setEapClientCert(const std::string& in_path) override;
+	::ndk::ScopedAStatus setEapPrivateKeyId(const std::string& in_id) override;
+	::ndk::ScopedAStatus setEapSubjectMatch(const std::string& in_match) override;
+	::ndk::ScopedAStatus setEapAltSubjectMatch(const std::string& in_match) override;
+	::ndk::ScopedAStatus setEapEngine(bool in_enable) override;
+	::ndk::ScopedAStatus setEapEngineID(const std::string& in_id) override;
+	::ndk::ScopedAStatus setEapDomainSuffixMatch(
+		const std::string& in_match) override;
+	::ndk::ScopedAStatus setProactiveKeyCaching(bool in_enable) override;
+	::ndk::ScopedAStatus setIdStr(const std::string& in_idStr) override;
+	::ndk::ScopedAStatus setUpdateIdentifier(int32_t in_id) override;
+	::ndk::ScopedAStatus setEdmg(bool in_enable) override;
+	::ndk::ScopedAStatus getSsid(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getBssid(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getScanSsid(bool* _aidl_return) override;
+	::ndk::ScopedAStatus getKeyMgmt(KeyMgmtMask* _aidl_return) override;
+	::ndk::ScopedAStatus getProto(ProtoMask* _aidl_return) override;
+	::ndk::ScopedAStatus getAuthAlg(AuthAlgMask* _aidl_return) override;
+	::ndk::ScopedAStatus getGroupCipher(GroupCipherMask* _aidl_return) override;
+	::ndk::ScopedAStatus getPairwiseCipher(PairwiseCipherMask* _aidl_return) override;
+	::ndk::ScopedAStatus getPskPassphrase(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getPsk(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getSaePassword(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getSaePasswordId(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getWepKey(
+		int32_t in_keyIdx, std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getWepTxKeyIdx(int32_t* _aidl_return) override;
+	::ndk::ScopedAStatus getRequirePmf(bool* _aidl_return) override;
+	::ndk::ScopedAStatus getEapMethod(EapMethod* _aidl_return) override;
+	::ndk::ScopedAStatus getEapPhase2Method(EapPhase2Method* _aidl_return) override;
+	::ndk::ScopedAStatus getEapIdentity(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getEapAnonymousIdentity(
+		std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getEapPassword(std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getEapCACert(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getEapCAPath(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getEapClientCert(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getEapPrivateKeyId(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getEapSubjectMatch(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getEapAltSubjectMatch(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getEapEngine(bool* _aidl_return) override;
+	::ndk::ScopedAStatus getEapEngineId(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getEapDomainSuffixMatch(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getIdStr(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus getWpsNfcConfigurationToken(
+		std::vector<uint8_t>* _aidl_return) override;
+	::ndk::ScopedAStatus getEdmg(bool* _aidl_return) override;
+	::ndk::ScopedAStatus enable(bool in_noConnect) override;
+	::ndk::ScopedAStatus disable() override;
+	::ndk::ScopedAStatus select() override;
+	::ndk::ScopedAStatus sendNetworkEapSimGsmAuthResponse(
+		const std::vector<NetworkResponseEapSimGsmAuthParams>& in_params) override;
+	::ndk::ScopedAStatus sendNetworkEapSimGsmAuthFailure() override;
+	::ndk::ScopedAStatus sendNetworkEapSimUmtsAuthResponse(
+		const NetworkResponseEapSimUmtsAuthParams& in_params) override;
+	::ndk::ScopedAStatus sendNetworkEapSimUmtsAutsResponse(
+		const std::vector<uint8_t>& in_auts) override;
+	::ndk::ScopedAStatus sendNetworkEapSimUmtsAuthFailure() override;
+	::ndk::ScopedAStatus sendNetworkEapIdentityResponse(
+		const std::vector<uint8_t>& in_identity,
+		const std::vector<uint8_t>& in_encryptedIdentity) override;
+	::ndk::ScopedAStatus setGroupMgmtCipher(
+		GroupMgmtCipherMask in_groupMgmtCipherMask) override;
+	::ndk::ScopedAStatus getGroupMgmtCipher(
+		GroupMgmtCipherMask* _aidl_return) override;
+	::ndk::ScopedAStatus enableTlsSuiteBEapPhase1Param(
+		bool in_enable) override;
+	::ndk::ScopedAStatus enableSuiteBEapOpenSslCiphers() override;
+	::ndk::ScopedAStatus setSaePassword(
+		const std::string& in_saePassword) override;
+	::ndk::ScopedAStatus setSaePasswordId(
+		const std::string& in_saePasswordId) override;
+	::ndk::ScopedAStatus setOcsp(OcspType in_ocspType) override;
+	::ndk::ScopedAStatus getOcsp(OcspType* _aidl_return) override;
+	::ndk::ScopedAStatus setPmkCache(
+		const std::vector<uint8_t>& in_serializedEntry) override;
+	::ndk::ScopedAStatus setWapiCertSuite(const std::string& in_suite) override;
+	::ndk::ScopedAStatus getWapiCertSuite(std::string* _aidl_return) override;
+	::ndk::ScopedAStatus setEapErp(bool in_enable) override;
+	::ndk::ScopedAStatus setSaeH2eMode(SaeH2eMode in_mode) override;
+	::ndk::ScopedAStatus enableSaePkOnlyMode(bool in_enable) override;
+	::ndk::ScopedAStatus setRoamingConsortiumSelection(
+		const std::vector<uint8_t>& in_selectedRcoi) override;
+
+private:
+	// Corresponding worker functions for the AIDL methods.
+	std::pair<uint32_t, ndk::ScopedAStatus> getIdInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getInterfaceNameInternal();
+	std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+	ndk::ScopedAStatus registerCallbackInternal(
+		const std::shared_ptr<ISupplicantStaNetworkCallback>& callback);
+	ndk::ScopedAStatus setSsidInternal(const std::vector<uint8_t>& ssid);
+	ndk::ScopedAStatus setBssidInternal(const std::vector<uint8_t>& bssid);
+	ndk::ScopedAStatus setDppKeysInternal(const DppConnectionKeys& keys);
+	ndk::ScopedAStatus setScanSsidInternal(bool enable);
+	ndk::ScopedAStatus setKeyMgmtInternal(
+		KeyMgmtMask mask);
+	ndk::ScopedAStatus setProtoInternal(
+		ProtoMask mask);
+	ndk::ScopedAStatus setAuthAlgInternal(
+		AuthAlgMask mask);
+	ndk::ScopedAStatus setGroupCipherInternal(
+		GroupCipherMask mask);
+	ndk::ScopedAStatus setPairwiseCipherInternal(
+		PairwiseCipherMask mask);
+	ndk::ScopedAStatus setPskPassphraseInternal(const std::string& psk);
+	ndk::ScopedAStatus setPskInternal(const std::vector<uint8_t>& psk);
+	ndk::ScopedAStatus setWepKeyInternal(
+		uint32_t key_idx, const std::vector<uint8_t>& wep_key);
+	ndk::ScopedAStatus setWepTxKeyIdxInternal(uint32_t key_idx);
+	ndk::ScopedAStatus setRequirePmfInternal(bool enable);
+	ndk::ScopedAStatus setEapMethodInternal(
+		EapMethod method);
+	ndk::ScopedAStatus setEapPhase2MethodInternal(
+		EapPhase2Method method);
+	ndk::ScopedAStatus setEapIdentityInternal(
+		const std::vector<uint8_t>& identity);
+	ndk::ScopedAStatus setEapEncryptedImsiIdentityInternal(
+		const std::vector<uint8_t>& identity);
+	ndk::ScopedAStatus setEapAnonymousIdentityInternal(
+		const std::vector<uint8_t>& identity);
+	ndk::ScopedAStatus setEapPasswordInternal(
+		const std::vector<uint8_t>& password);
+	ndk::ScopedAStatus setEapCACertInternal(const std::string& path);
+	ndk::ScopedAStatus setEapCAPathInternal(const std::string& path);
+	ndk::ScopedAStatus setEapClientCertInternal(const std::string& path);
+	ndk::ScopedAStatus setEapPrivateKeyIdInternal(const std::string& id);
+	ndk::ScopedAStatus setEapSubjectMatchInternal(const std::string& match);
+	ndk::ScopedAStatus setEapAltSubjectMatchInternal(
+		const std::string& match);
+	ndk::ScopedAStatus setEapEngineInternal(bool enable);
+	ndk::ScopedAStatus setEapEngineIDInternal(const std::string& id);
+	ndk::ScopedAStatus setEapDomainSuffixMatchInternal(
+		const std::string& match);
+	ndk::ScopedAStatus setProactiveKeyCachingInternal(bool enable);
+	ndk::ScopedAStatus setIdStrInternal(const std::string& id_str);
+	ndk::ScopedAStatus setUpdateIdentifierInternal(uint32_t id);
+	ndk::ScopedAStatus setEdmgInternal(bool enable);
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getSsidInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getBssidInternal();
+	std::pair<bool, ndk::ScopedAStatus> getScanSsidInternal();
+	std::pair<KeyMgmtMask, ndk::ScopedAStatus> getKeyMgmtInternal();
+	std::pair<ProtoMask, ndk::ScopedAStatus> getProtoInternal();
+	std::pair<AuthAlgMask, ndk::ScopedAStatus> getAuthAlgInternal();
+	std::pair<GroupCipherMask, ndk::ScopedAStatus> getGroupCipherInternal();
+	std::pair<PairwiseCipherMask, ndk::ScopedAStatus> getPairwiseCipherInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getPskPassphraseInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getPskInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getSaePasswordInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getSaePasswordIdInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getWepKeyInternal(
+		uint32_t key_idx);
+	std::pair<uint32_t, ndk::ScopedAStatus> getWepTxKeyIdxInternal();
+	std::pair<bool, ndk::ScopedAStatus> getRequirePmfInternal();
+	std::pair<EapMethod, ndk::ScopedAStatus> getEapMethodInternal();
+	std::pair<EapPhase2Method, ndk::ScopedAStatus>
+		getEapPhase2MethodInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		getEapIdentityInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		getEapAnonymousIdentityInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		getEapPasswordInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapCACertInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapCAPathInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapClientCertInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapPrivateKeyIdInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapSubjectMatchInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapAltSubjectMatchInternal();
+	std::pair<bool, ndk::ScopedAStatus> getEapEngineInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapEngineIdInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getEapDomainSuffixMatchInternal();
+	std::pair<std::string, ndk::ScopedAStatus> getIdStrInternal();
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+		getWpsNfcConfigurationTokenInternal();
+	std::pair<bool, ndk::ScopedAStatus> getEdmgInternal();
+	ndk::ScopedAStatus enableInternal(bool no_connect);
+	ndk::ScopedAStatus disableInternal();
+	ndk::ScopedAStatus selectInternal();
+	ndk::ScopedAStatus sendNetworkEapSimGsmAuthResponseInternal(
+		const std::vector<NetworkResponseEapSimGsmAuthParams>&
+		vec_params);
+	ndk::ScopedAStatus sendNetworkEapSimGsmAuthFailureInternal();
+	ndk::ScopedAStatus sendNetworkEapSimUmtsAuthResponseInternal(
+		const NetworkResponseEapSimUmtsAuthParams& params);
+	ndk::ScopedAStatus sendNetworkEapSimUmtsAutsResponseInternal(
+		const std::vector<uint8_t>& auts);
+	ndk::ScopedAStatus sendNetworkEapSimUmtsAuthFailureInternal();
+	ndk::ScopedAStatus sendNetworkEapIdentityResponseInternal(
+		const std::vector<uint8_t>& identity,
+		const std::vector<uint8_t>& imsi_identity);
+	ndk::ScopedAStatus enableTlsSuiteBEapPhase1ParamInternal(bool enable);
+	ndk::ScopedAStatus enableSuiteBEapOpenSslCiphersInternal();
+	ndk::ScopedAStatus setSaePasswordInternal(
+		const std::string& sae_password);
+	ndk::ScopedAStatus setSaePasswordIdInternal(
+		const std::string& sae_password_id);
+	ndk::ScopedAStatus setGroupMgmtCipherInternal(
+		GroupMgmtCipherMask mask);
+	std::pair<GroupMgmtCipherMask, ndk::ScopedAStatus>
+		getGroupMgmtCipherInternal();
+	ndk::ScopedAStatus setOcspInternal(OcspType ocspType);
+	std::pair<OcspType, ndk::ScopedAStatus> getOcspInternal();
+	ndk::ScopedAStatus setPmkCacheInternal(const std::vector<uint8_t>& serializedEntry);
+	ndk::ScopedAStatus setWapiCertSuiteInternal(const std::string& suite);
+	std::pair<std::string, ndk::ScopedAStatus> getWapiCertSuiteInternal();
+	ndk::ScopedAStatus setWapiPskInternal(const std::vector<uint8_t>& psk);
+	std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getWapiPskInternal();
+	ndk::ScopedAStatus setSaeH2eModeInternal(SaeH2eMode mode);
+	ndk::ScopedAStatus enableSaePkOnlyModeInternal(bool enable);
+	ndk::ScopedAStatus setRoamingConsortiumSelectionInternal(
+		const std::vector<uint8_t>& selectedRcoi);
+
+	struct wpa_ssid* retrieveNetworkPtr();
+	struct wpa_supplicant* retrieveIfacePtr();
+	int isPskPassphraseValid(const std::string& psk);
+	void resetInternalStateAfterParamsUpdate();
+	int setStringFieldAndResetState(
+		const char* value, uint8_t** to_update_field,
+		const char* hexdump_prefix);
+	int setStringFieldAndResetState(
+		const char* value, char** to_update_field,
+		const char* hexdump_prefix);
+	int setStringKeyFieldAndResetState(
+		const char* value, char** to_update_field,
+		const char* hexdump_prefix);
+	int setByteArrayFieldAndResetState(
+		const uint8_t* value, const size_t value_len,
+		uint8_t** to_update_field, size_t* to_update_field_len,
+		const char* hexdump_prefix);
+	int setByteArrayKeyFieldAndResetState(
+		const uint8_t* value, const size_t value_len,
+		uint8_t** to_update_field, size_t* to_update_field_len,
+		const char* hexdump_prefix);
+	void setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
+	void resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
+	ndk::ScopedAStatus setEapErpInternal(bool enable);
+	int setByteArrayField(
+		const uint8_t* value, const size_t value_len,
+		uint8_t** to_update_field, size_t* to_update_field_len,
+		const char* hexdump_prefix, bool resetState);
+
+	// Reference to the global wpa_struct. This is assumed to be valid
+	// for the lifetime of the process.
+	struct wpa_global* wpa_global_;
+	// Name of the iface this network belongs to.
+	const std::string ifname_;
+	// Id of the network this aidl object controls.
+	const int network_id_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(StaNetwork);
+};
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // WPA_SUPPLICANT_AIDL_STA_NETWORK_H
diff --git a/wpa_supplicant/aidl/supplicant.cpp b/wpa_supplicant/aidl/supplicant.cpp
new file mode 100644
index 0000000..ee6f809
--- /dev/null
+++ b/wpa_supplicant/aidl/supplicant.cpp
@@ -0,0 +1,545 @@
+/*
+ * WPA Supplicant - Supplicant Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "misc_utils.h"
+#include "supplicant.h"
+#include "p2p_iface.h"
+
+#include <android-base/file.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+namespace {
+
+// Pre-populated interface params for interfaces controlled by wpa_supplicant.
+// Note: This may differ for other OEM's. So, modify this accordingly.
+constexpr char kIfaceDriverName[] = "nl80211";
+constexpr char kStaIfaceConfPath[] =
+	"/data/vendor/wifi/wpa/wpa_supplicant.conf";
+static const char* kStaIfaceConfOverlayPaths[] = {
+    "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant_overlay.conf",
+    "/vendor/etc/wifi/wpa_supplicant_overlay.conf",
+};
+constexpr char kP2pIfaceConfPath[] =
+	"/data/vendor/wifi/wpa/p2p_supplicant.conf";
+static const char* kP2pIfaceConfOverlayPaths[] = {
+    "/apex/com.android.wifi.hal/etc/wifi/p2p_supplicant_overlay.conf",
+    "/vendor/etc/wifi/p2p_supplicant_overlay.conf",
+};
+// Migrate conf files for existing devices.
+static const char* kTemplateConfPaths[] = {
+    "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant.conf",
+    "/vendor/etc/wifi/wpa_supplicant.conf",
+    "/system/etc/wifi/wpa_supplicant.conf",
+};
+constexpr char kOldStaIfaceConfPath[] = "/data/misc/wifi/wpa_supplicant.conf";
+constexpr char kOldP2pIfaceConfPath[] = "/data/misc/wifi/p2p_supplicant.conf";
+constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+
+const char* resolvePath(const char* paths[], size_t size)
+{
+	for (int i = 0; i < size; ++i) {
+		if (access(paths[i], R_OK) == 0) {
+			return paths[i];
+		}
+	}
+	return nullptr;
+}
+
+int copyFile(
+	const std::string& src_file_path, const std::string& dest_file_path)
+{
+	std::string file_contents;
+	if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
+		wpa_printf(
+			MSG_ERROR, "Failed to read from %s. Errno: %s",
+			src_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	if (!android::base::WriteStringToFile(
+		file_contents, dest_file_path, kConfigFileMode, getuid(),
+		getgid())) {
+		wpa_printf(
+			MSG_ERROR, "Failed to write to %s. Errno: %s",
+			dest_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Copy |src_file_path| to |dest_file_path| if it exists.
+ *
+ * Returns 1 if |src_file_path| does not exist or not accessible,
+ * Returns -1 if the copy fails.
+ * Returns 0 if the copy succeeds.
+ */
+int copyFileIfItExists(
+	const std::string& src_file_path, const std::string& dest_file_path)
+{
+	int ret = access(src_file_path.c_str(), R_OK);
+	// Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT.
+	if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) {
+		return 1;
+	}
+	ret = copyFile(src_file_path, dest_file_path);
+	if (ret != 0) {
+		wpa_printf(
+			MSG_ERROR, "Failed copying %s to %s.",
+			src_file_path.c_str(), dest_file_path.c_str());
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Ensure that the specified config file pointed by |config_file_path| exists.
+ * a) If the |config_file_path| exists with the correct permissions, return.
+ * b) If the |config_file_path| does not exist, but |old_config_file_path|
+ * exists, copy over the contents of the |old_config_file_path| to
+ * |config_file_path|.
+ * c) If the |config_file_path| & |old_config_file_path|
+ * does not exists, copy over the contents of |template_config_file_path|.
+ */
+int ensureConfigFileExists(
+	const std::string& config_file_path,
+	const std::string& old_config_file_path)
+{
+	int ret = access(config_file_path.c_str(), R_OK | W_OK);
+	if (ret == 0) {
+		return 0;
+	}
+	if (errno == EACCES) {
+		ret = chmod(config_file_path.c_str(), kConfigFileMode);
+		if (ret == 0) {
+			return 0;
+		} else {
+			wpa_printf(
+				MSG_ERROR, "Cannot set RW to %s. Errno: %s",
+				config_file_path.c_str(), strerror(errno));
+			return -1;
+		}
+	} else if (errno != ENOENT) {
+		wpa_printf(
+			MSG_ERROR, "Cannot acces %s. Errno: %s",
+			config_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	ret = copyFileIfItExists(old_config_file_path, config_file_path);
+	if (ret == 0) {
+		wpa_printf(
+			MSG_INFO, "Migrated conf file from %s to %s",
+			old_config_file_path.c_str(), config_file_path.c_str());
+		unlink(old_config_file_path.c_str());
+		return 0;
+	} else if (ret == -1) {
+		unlink(config_file_path.c_str());
+		return -1;
+	}
+	const char* path =
+	    resolvePath(kTemplateConfPaths,
+	    sizeof(kTemplateConfPaths)/sizeof(kTemplateConfPaths[0]));
+	if (path != nullptr) {
+		ret = copyFileIfItExists(path, config_file_path);
+		if (ret == 0) {
+			wpa_printf(
+			    MSG_INFO, "Copied template conf file from %s to %s",
+			    path, config_file_path.c_str());
+			return 0;
+		} else if (ret == -1) {
+			unlink(config_file_path.c_str());
+			return -1;
+		}
+	}
+	// Did not create the conf file.
+	return -1;
+}
+}  // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+using misc_utils::createStatusWithMsg;
+
+Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
+bool Supplicant::isValid()
+{
+	// This top level object cannot be invalidated.
+	return true;
+}
+
+::ndk::ScopedAStatus Supplicant::addP2pInterface(
+	const std::string& in_name,
+	std::shared_ptr<ISupplicantP2pIface>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::addP2pInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::addStaInterface(
+	const std::string& in_name,
+	std::shared_ptr<ISupplicantStaIface>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::addStaInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::removeInterface(
+	const IfaceInfo& in_ifaceInfo)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::removeInterfaceInternal, in_ifaceInfo);
+}
+
+::ndk::ScopedAStatus Supplicant::getP2pInterface(
+	const std::string& in_name,
+	std::shared_ptr<ISupplicantP2pIface>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::getP2pInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::getStaInterface(
+	const std::string& in_name,
+	std::shared_ptr<ISupplicantStaIface>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::getStaInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::listInterfaces(
+	std::vector<IfaceInfo>* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::listInterfacesInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus Supplicant::registerCallback(
+	const std::shared_ptr<ISupplicantCallback>& in_callback)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus Supplicant::setDebugParams(
+	DebugLevel in_level, bool in_showTimestamp,
+	bool in_showKeys)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::setDebugParamsInternal, in_level,
+		in_showTimestamp, in_showKeys);
+}
+
+::ndk::ScopedAStatus Supplicant::setConcurrencyPriority(
+	IfaceType in_type)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&Supplicant::setConcurrencyPriorityInternal, in_type);
+}
+
+::ndk::ScopedAStatus Supplicant::getDebugLevel(DebugLevel* _aidl_return)
+{
+	*_aidl_return = static_cast<DebugLevel>(wpa_debug_level);
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Supplicant::isDebugShowTimestampEnabled(bool* _aidl_return)
+{
+	*_aidl_return = ((wpa_debug_timestamp != 0) ? true : false);
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Supplicant::isDebugShowKeysEnabled(bool* _aidl_return)
+{
+	*_aidl_return = ((wpa_debug_show_keys != 0) ? true : false);
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Supplicant::terminate()
+{
+	wpa_printf(MSG_INFO, "Terminating...");
+	wpa_supplicant_terminate_proc(wpa_global_);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Supplicant::addP2pDevInterface(struct wpa_interface iface_params)
+{
+	char primary_ifname[IFNAMSIZ];
+	u32 primary_ifname_len =
+		strlen(iface_params.ifname) - strlen(P2P_MGMT_DEVICE_PREFIX);
+
+	if(primary_ifname_len > IFNAMSIZ) {
+		wpa_printf(MSG_DEBUG, "%s, Invalid primary iface name ", __FUNCTION__);
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+
+	strncpy(primary_ifname, iface_params.ifname +
+		strlen(P2P_MGMT_DEVICE_PREFIX), primary_ifname_len);
+	wpa_printf(MSG_DEBUG, "%s, Initialize p2p-dev-wlan0 iface with"
+		"primary_iface = %s", __FUNCTION__, primary_ifname);
+	struct wpa_supplicant* wpa_s =
+		wpa_supplicant_get_iface(wpa_global_, primary_ifname);
+	if (!wpa_s) {
+		wpa_printf(MSG_DEBUG, "%s,NULL wpa_s for wlan0", __FUNCTION__);
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	if (wpas_p2p_add_p2pdev_interface(
+		wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
+		wpa_printf(MSG_INFO,
+			"Failed to enable P2P Device");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+Supplicant::addP2pInterfaceInternal(const std::string& name)
+{
+	std::shared_ptr<ISupplicantP2pIface> iface;
+
+	// Check if required |ifname| argument is empty.
+	if (name.empty()) {
+		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+	}
+	// Try to get the wpa_supplicant record for this iface, return
+	// the iface object with the appropriate status code if it exists.
+	ndk::ScopedAStatus status;
+	std::tie(iface, status) = getP2pInterfaceInternal(name);
+	if (status.isOk()) {
+		wpa_printf(MSG_INFO, "Iface already exists, return existing");
+		return {iface, ndk::ScopedAStatus::ok()};
+	}
+
+	struct wpa_interface iface_params = {};
+	iface_params.driver = kIfaceDriverName;
+	if (ensureConfigFileExists(
+		kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
+		wpa_printf(
+			MSG_ERROR, "Conf file does not exists: %s",
+			kP2pIfaceConfPath);
+		return {nullptr, createStatusWithMsg(
+			SupplicantStatusCode::FAILURE_UNKNOWN, "Conf file does not exist")};
+	}
+	iface_params.confname = kP2pIfaceConfPath;
+	const char* path = resolvePath(
+		    kP2pIfaceConfOverlayPaths,
+		    sizeof(kP2pIfaceConfOverlayPaths)/sizeof(kP2pIfaceConfOverlayPaths[0]));
+	if (path != nullptr) {
+		iface_params.confanother = path;
+	}
+
+	iface_params.ifname = name.c_str();
+	if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
+		strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+		status = addP2pDevInterface(iface_params);
+		if (!status.isOk()) {
+			return {iface, createStatus(static_cast<SupplicantStatusCode>(
+				status.getServiceSpecificError()))};
+		}
+	} else {
+		struct wpa_supplicant* wpa_s =
+			wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
+		if (!wpa_s) {
+			return {nullptr, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+		}
+		// Request the current scan results from the driver and update
+		// the local BSS list wpa_s->bss. This is to avoid a full scan
+		// while processing the connect request on newly created interface.
+		wpa_supplicant_update_scan_results(wpa_s);
+	}
+	// The supplicant core creates a corresponding aidl object via
+	// AidlManager when |wpa_supplicant_add_iface| is called.
+	return getP2pInterfaceInternal(name);
+}
+
+std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+Supplicant::addStaInterfaceInternal(const std::string& name)
+{
+	std::shared_ptr<ISupplicantStaIface> iface;
+
+	// Check if required |ifname| argument is empty.
+	if (name.empty()) {
+		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+	}
+	// Try to get the wpa_supplicant record for this iface, return
+	// the iface object with the appropriate status code if it exists.
+	ndk::ScopedAStatus status;
+	std::tie(iface, status) = getStaInterfaceInternal(name);
+	if (status.isOk()) {
+		wpa_printf(MSG_INFO, "Iface already exists, return existing");
+		return {iface, ndk::ScopedAStatus::ok()};
+	}
+
+	struct wpa_interface iface_params = {};
+	iface_params.driver = kIfaceDriverName;
+	if (ensureConfigFileExists(
+		kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
+		wpa_printf(
+			MSG_ERROR, "Conf file does not exists: %s",
+			kStaIfaceConfPath);
+		return {nullptr, createStatusWithMsg(
+			SupplicantStatusCode::FAILURE_UNKNOWN, "Conf file does not exist")};
+	}
+	iface_params.confname = kStaIfaceConfPath;
+	const char* path = resolvePath(
+		    kStaIfaceConfOverlayPaths,
+		    sizeof(kStaIfaceConfOverlayPaths)/sizeof(kStaIfaceConfOverlayPaths[0]));
+	if (path != nullptr) {
+		iface_params.confanother = path;
+	}
+
+	iface_params.ifname = name.c_str();
+	if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
+		strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+		status = addP2pDevInterface(iface_params);
+		if (!status.isOk()) {
+			return {iface, createStatus(static_cast<SupplicantStatusCode>(
+				status.getServiceSpecificError()))};
+		}
+	} else {
+		struct wpa_supplicant* wpa_s =
+			wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
+		if (!wpa_s) {
+			return {nullptr, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+		}
+		// Request the current scan results from the driver and update
+		// the local BSS list wpa_s->bss. This is to avoid a full scan
+		// while processing the connect request on newly created interface.
+		wpa_supplicant_update_scan_results(wpa_s);
+	}
+	// The supplicant core creates a corresponding aidl object via
+	// AidlManager when |wpa_supplicant_add_iface| is called.
+	return getStaInterfaceInternal(name);
+}
+
+ndk::ScopedAStatus Supplicant::removeInterfaceInternal(
+	const IfaceInfo& iface_info)
+{
+	struct wpa_supplicant* wpa_s =
+		wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
+	if (!wpa_s) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+	}
+	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+Supplicant::getP2pInterfaceInternal(const std::string& name)
+{
+	struct wpa_supplicant* wpa_s =
+		wpa_supplicant_get_iface(wpa_global_, name.c_str());
+	if (!wpa_s) {
+		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
+	}
+	AidlManager* aidl_manager = AidlManager::getInstance();
+	std::shared_ptr<ISupplicantP2pIface> iface;
+	if (!aidl_manager ||
+		aidl_manager->getP2pIfaceAidlObjectByIfname(
+		wpa_s->ifname, &iface)) {
+		return {iface, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	// Set this flag true here, since there is no AIDL initialize
+	// method for the p2p config, and the supplicant interface is
+	// not ready when the p2p iface is created.
+	wpa_s->conf->persistent_reconnect = true;
+	return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+Supplicant::getStaInterfaceInternal(const std::string& name)
+{
+	struct wpa_supplicant* wpa_s =
+		wpa_supplicant_get_iface(wpa_global_, name.c_str());
+	if (!wpa_s) {
+		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
+	}
+	AidlManager* aidl_manager = AidlManager::getInstance();
+	std::shared_ptr<ISupplicantStaIface> iface;
+	if (!aidl_manager ||
+		aidl_manager->getStaIfaceAidlObjectByIfname(
+		wpa_s->ifname, &iface)) {
+		return {iface, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+	return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<IfaceInfo>, ndk::ScopedAStatus>
+Supplicant::listInterfacesInternal()
+{
+	std::vector<IfaceInfo> ifaces;
+	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
+		 wpa_s = wpa_s->next) {
+		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
+			ifaces.emplace_back(IfaceInfo{
+				IfaceType::P2P, wpa_s->ifname});
+		} else {
+			ifaces.emplace_back(IfaceInfo{
+				IfaceType::STA, wpa_s->ifname});
+		}
+	}
+	return {std::move(ifaces), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus Supplicant::registerCallbackInternal(
+	const std::shared_ptr<ISupplicantCallback>& callback)
+{
+	AidlManager* aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager ||
+		aidl_manager->addSupplicantCallbackAidlObject(callback)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Supplicant::setDebugParamsInternal(
+	DebugLevel level, bool show_timestamp, bool show_keys)
+{
+	if (wpa_supplicant_set_debug_params(
+		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
+		show_keys)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
+{
+	if (type == IfaceType::STA) {
+		wpa_global_->conc_pref =
+			wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
+	} else if (type == IfaceType::P2P) {
+		wpa_global_->conc_pref =
+			wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
+	} else {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/wpa_supplicant/aidl/supplicant.h b/wpa_supplicant/aidl/supplicant.h
new file mode 100644
index 0000000..cbe9a67
--- /dev/null
+++ b/wpa_supplicant/aidl/supplicant.h
@@ -0,0 +1,111 @@
+/*
+ * WPA Supplicant - Supplicant Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_SUPPLICANT_H
+#define WPA_SUPPLICANT_AIDL_SUPPLICANT_H
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/DebugLevel.h>
+#include <aidl/android/hardware/wifi/supplicant/IfaceInfo.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.h>
+
+#include <android-base/macros.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "utils/wpa_debug.h"
+#include "wpa_supplicant_i.h"
+#include "scan.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of the supplicant aidl object. This aidl
+ * object is used core for global control operations on
+ * wpa_supplicant.
+ */
+class Supplicant : public BnSupplicant
+{
+public:
+	Supplicant(struct wpa_global* global);
+	~Supplicant() override = default;
+	bool isValid();
+
+	// Aidl methods exposed.
+  	::ndk::ScopedAStatus addP2pInterface(
+		  const std::string& in_name,
+		  std::shared_ptr<ISupplicantP2pIface>* _aidl_return) override;
+	::ndk::ScopedAStatus addStaInterface(
+		const std::string& in_name,
+		std::shared_ptr<ISupplicantStaIface>* _aidl_return) override;
+	::ndk::ScopedAStatus removeInterface(
+		const IfaceInfo& in_ifaceInfo) override;
+	::ndk::ScopedAStatus getP2pInterface(
+		const std::string& in_name,
+		std::shared_ptr<ISupplicantP2pIface>* _aidl_return) override;
+	::ndk::ScopedAStatus getStaInterface(
+		const std::string& in_name,
+		std::shared_ptr<ISupplicantStaIface>* _aidl_return) override;
+	::ndk::ScopedAStatus listInterfaces(
+		std::vector<IfaceInfo>* _aidl_return) override;
+	::ndk::ScopedAStatus registerCallback(
+		const std::shared_ptr<ISupplicantCallback>& in_callback) override;
+	::ndk::ScopedAStatus setDebugParams(
+		DebugLevel in_level, bool in_showTimestamp, bool in_showKeys) override;
+	::ndk::ScopedAStatus getDebugLevel(DebugLevel* _aidl_return) override;
+	::ndk::ScopedAStatus isDebugShowTimestampEnabled(bool* _aidl_return) override;
+	::ndk::ScopedAStatus isDebugShowKeysEnabled(bool* _aidl_return) override;
+	::ndk::ScopedAStatus setConcurrencyPriority(IfaceType in_type) override;
+	::ndk::ScopedAStatus terminate() override;
+
+private:
+	// Corresponding worker functions for the AIDL methods.
+	std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+		addP2pInterfaceInternal(const std::string& name);
+	std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+		addStaInterfaceInternal(const std::string& name);
+	std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+		getP2pInterfaceInternal(const std::string& name);
+	std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+		getStaInterfaceInternal(const std::string& name);
+	
+	ndk::ScopedAStatus removeInterfaceInternal(const IfaceInfo& iface_info);
+	std::pair<std::vector<IfaceInfo>, ndk::ScopedAStatus> listInterfacesInternal();
+	ndk::ScopedAStatus registerCallbackInternal(
+		const std::shared_ptr<ISupplicantCallback>& callback);
+	ndk::ScopedAStatus setDebugParamsInternal(
+		DebugLevel level, bool show_timestamp, bool show_keys);
+	ndk::ScopedAStatus setConcurrencyPriorityInternal(IfaceType type);
+	ndk::ScopedAStatus addP2pDevInterface(struct wpa_interface iface_params);
+
+	// Raw pointer to the global structure maintained by the core.
+	struct wpa_global* wpa_global_;
+	// Driver name to be used for creating interfaces.
+	static const char kDriverName[];
+	// wpa_supplicant.conf file location on the device.
+	static const char kConfigFilePath[];
+
+	DISALLOW_COPY_AND_ASSIGN(Supplicant);
+};
+
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // WPA_SUPPLICANT_AIDL_SUPPLICANT_H
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 3c0431b..52e4c04 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -327,9 +327,9 @@
 # Add introspection support for new DBus control interface
 #CONFIG_CTRL_IFACE_DBUS_INTRO=y
 
-# Add support for Hidl control interface
+# Add support for Aidl control interface
 # Only applicable for Android platforms.
-CONFIG_CTRL_IFACE_HIDL=y
+CONFIG_CTRL_IFACE_AIDL=y
 
 # Add support for loading EAP methods dynamically as shared libraries.
 # When this option is enabled, each EAP method can be either included
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 807e36d..0559822 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -84,6 +84,11 @@
 	/* Use the maximum oper channel width if it's given. */
 	if (ssid->max_oper_chwidth)
 		hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
+	if (hostapd_get_oper_chwidth(conf))
+		ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+					      hostapd_get_oper_chwidth(conf),
+					      &conf->op_class,
+					      &conf->channel);
 
 	if (hostapd_get_oper_chwidth(conf) == CHANWIDTH_80P80MHZ) {
 		ieee80211_freq_to_chan(ssid->vht_center_freq2,
@@ -109,13 +114,15 @@
 	switch (hostapd_get_oper_chwidth(conf)) {
 	case CHANWIDTH_80MHZ:
 	case CHANWIDTH_80P80MHZ:
-		center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
+		center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel,
+							conf->op_class);
 		wpa_printf(MSG_DEBUG,
 			   "VHT center channel %u for 80 or 80+80 MHz bandwidth",
 			   center_chan);
 		break;
 	case CHANWIDTH_160MHZ:
-		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
+		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel,
+							 conf->op_class);
 		wpa_printf(MSG_DEBUG,
 			   "VHT center channel %u for 160 MHz bandwidth",
 			   center_chan);
@@ -127,15 +134,25 @@
 		 * not supported.
 		 */
 		hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ);
-		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
+		ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+					      conf->vht_oper_chwidth,
+					      &conf->op_class,
+					      &conf->channel);
+		center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel,
+							 conf->op_class);
 		if (center_chan && is_chanwidth160_supported(mode, conf)) {
 			wpa_printf(MSG_DEBUG,
 				   "VHT center channel %u for auto-selected 160 MHz bandwidth",
 				   center_chan);
 		} else {
 			hostapd_set_oper_chwidth(conf, CHANWIDTH_80MHZ);
+			ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+						      conf->vht_oper_chwidth,
+						      &conf->op_class,
+						      &conf->channel);
 			center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
-								channel);
+								channel,
+								conf->op_class);
 			wpa_printf(MSG_DEBUG,
 				   "VHT center channel %u for auto-selected 80 MHz bandwidth",
 				   center_chan);
@@ -179,13 +196,79 @@
 }
 
 
+#ifdef CONFIG_P2P
+
+static int get_max_oper_chwidth_6ghz(int chwidth)
+{
+	switch (chwidth) {
+	case CHANWIDTH_USE_HT:
+		return 20;
+	case CHANWIDTH_40MHZ_6GHZ:
+		return 40;
+	case CHANWIDTH_80MHZ:
+		return 80;
+	case CHANWIDTH_80P80MHZ:
+	case CHANWIDTH_160MHZ:
+		return 160;
+	default:
+		return 0;
+	}
+}
+
+
+static void wpas_conf_ap_he_6ghz(struct wpa_supplicant *wpa_s,
+				 struct hostapd_hw_modes *mode,
+				 struct wpa_ssid *ssid,
+				 struct hostapd_config *conf)
+{
+	bool is_chanwidth_40_80, is_chanwidth_160;
+	int he_chanwidth;
+
+	he_chanwidth =
+		mode->he_capab[wpas_mode_to_ieee80211_mode(
+			ssid->mode)].phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
+	is_chanwidth_40_80 = he_chanwidth &
+		HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
+	is_chanwidth_160 = he_chanwidth &
+		HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+
+	wpa_printf(MSG_DEBUG,
+		   "Enable HE support (p2p_group=%d he_chwidth_cap=%d)",
+		   ssid->p2p_group, he_chanwidth);
+
+	if (mode->he_capab[wpas_mode_to_ieee80211_mode(
+			    ssid->mode)].he_supported &&
+	    ssid->he)
+		conf->ieee80211ax = 1;
+
+	if (is_chanwidth_40_80 && ssid->p2p_group &&
+	    get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 40) {
+		conf->secondary_channel =
+			wpas_p2p_get_sec_channel_offset_40mhz(
+				wpa_s, mode, conf->channel);
+		wpa_printf(MSG_DEBUG,
+			   "Secondary channel offset %d for P2P group",
+			   conf->secondary_channel);
+		if (ssid->max_oper_chwidth == CHANWIDTH_40MHZ_6GHZ)
+			ssid->max_oper_chwidth = CHANWIDTH_USE_HT;
+	}
+
+	if ((is_chanwidth_40_80 || is_chanwidth_160) && ssid->p2p_group &&
+	    get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 80)
+		wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
+}
+
+#endif /* CONFIG_P2P */
+
+
 int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
 			      struct wpa_ssid *ssid,
 			      struct hostapd_config *conf)
 {
-	conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
-					       &conf->channel);
-
+	conf->hw_mode = ieee80211_freq_to_channel_ext(ssid->frequency, 0,
+						      CHANWIDTH_USE_HT,
+						      &conf->op_class,
+						      &conf->channel);
 	if (conf->hw_mode == NUM_HOSTAPD_MODES) {
 		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
 			   ssid->frequency);
@@ -206,7 +289,8 @@
 			   "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)",
 			   ssid->frequency, conf->channel);
 
-		mode = wpa_supplicant_find_hw_mode(wpa_s, conf->hw_mode);
+		mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+				conf->hw_mode, is_6ghz_freq(ssid->frequency));
 
 		/* May drop to IEEE 802.11b if the driver does not support IEEE
 		 * 802.11g */
@@ -237,7 +321,12 @@
 			no_ht = 1;
 		}
 
-		if (!no_ht && mode && mode->ht_capab) {
+		if (mode && is_6ghz_freq(ssid->frequency) &&
+		    conf->hw_mode == HOSTAPD_MODE_IEEE80211A) {
+#ifdef CONFIG_P2P
+			wpas_conf_ap_he_6ghz(wpa_s, mode, ssid, conf);
+#endif /* CONFIG_P2P */
+		} else if (!no_ht && mode && mode->ht_capab) {
 			wpa_printf(MSG_DEBUG,
 				   "Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)",
 				   ssid->p2p_group,
@@ -261,8 +350,8 @@
 			     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
 			    ssid->ht40) {
 				conf->secondary_channel =
-					wpas_p2p_get_ht40_mode(wpa_s, mode,
-							       conf->channel);
+					wpas_p2p_get_sec_channel_offset_40mhz(
+						wpa_s, mode, conf->channel);
 				wpa_printf(MSG_DEBUG,
 					   "HT secondary channel offset %d for P2P group",
 					   conf->secondary_channel);
@@ -293,7 +382,7 @@
 					HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
 
 			/*
-			 * white-list capabilities that won't cause issues
+			 * include capabilities that won't cause issues
 			 * to connecting stations, while leaving the current
 			 * capabilities intact (currently disabled SMPS).
 			 */
@@ -512,7 +601,10 @@
 		bss->sae_passwords = pw;
 	}
 
-	bss->sae_pwe = wpa_s->conf->sae_pwe;
+	if (ssid->sae_pwe != DEFAULT_SAE_PWE)
+		bss->sae_pwe = ssid->sae_pwe;
+	else
+		bss->sae_pwe = wpa_s->conf->sae_pwe;
 #endif /* CONFIG_SAE */
 
 	if (wpa_s->conf->go_interworking) {
@@ -680,6 +772,10 @@
 		bss->vendor_elements =
 			wpabuf_dup(wpa_s->conf->ap_vendor_elements);
 	}
+	if (wpa_s->conf->ap_assocresp_elements) {
+		bss->assocresp_elements =
+			wpabuf_dup(wpa_s->conf->ap_assocresp_elements);
+	}
 
 	bss->ftm_responder = wpa_s->conf->ftm_responder;
 	bss->ftm_initiator = wpa_s->conf->ftm_initiator;
@@ -809,11 +905,12 @@
 
 	if (wpa_s->current_ssid) {
 		int acs = 0;
+
 #ifdef CONFIG_ACS
 		acs = wpa_s->current_ssid->acs;
-#endif
+#endif /* CONFIG_ACS */
 		if (acs || (wpa_s->assoc_freq && wpa_s->ap_iface->freq &&
-			    wpa_s->assoc_freq != wpa_s->ap_iface->freq)) {
+			    (int) wpa_s->assoc_freq != wpa_s->ap_iface->freq)) {
 			wpa_s->assoc_freq = wpa_s->ap_iface->freq;
 			wpa_s->current_ssid->frequency = wpa_s->ap_iface->freq;
 		}
@@ -879,6 +976,8 @@
 	params.wpa_proto = ssid->proto;
 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
 		wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
+	else if (ssid->key_mgmt & WPA_KEY_MGMT_SAE)
+		wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
 	else
 		wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
 	params.key_mgmt_suite = wpa_s->key_mgmt;
@@ -1110,6 +1209,7 @@
 	struct wpa_supplicant *wpa_s = ctx;
 	struct hostapd_frame_info fi;
 	os_memset(&fi, 0, sizeof(fi));
+	fi.freq = rx_mgmt->freq;
 	fi.datarate = rx_mgmt->datarate;
 	fi.ssi_signal = rx_mgmt->ssi_signal;
 	ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame,
@@ -1733,6 +1833,32 @@
 #endif /* CONFIG_MESH */
 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
 
+
+int wpas_ap_update_beacon(struct wpa_supplicant *wpa_s)
+{
+	struct hostapd_data *hapd;
+
+	if (!wpa_s->ap_iface)
+		return -1;
+	hapd = wpa_s->ap_iface->bss[0];
+
+	wpabuf_free(hapd->conf->assocresp_elements);
+	hapd->conf->assocresp_elements = NULL;
+	if (wpa_s->conf->ap_assocresp_elements) {
+		hapd->conf->assocresp_elements =
+			wpabuf_dup(wpa_s->conf->ap_assocresp_elements);
+	}
+
+	wpabuf_free(hapd->conf->vendor_elements);
+	hapd->conf->vendor_elements = NULL;
+	if (wpa_s->conf->ap_vendor_elements) {
+		hapd->conf->vendor_elements =
+			wpabuf_dup(wpa_s->conf->ap_vendor_elements);
+	}
+
+	return ieee802_11_set_beacon(hapd);
+}
+
 #endif /* CONFIG_CTRL_IFACE */
 
 
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index 6c6e94c..7bc1b78 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -88,6 +88,7 @@
 int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
 				  char *buf, size_t len);
 int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd);
+int wpas_ap_update_beacon(struct wpa_supplicant *wpa_s);
 
 void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
 				      struct dfs_event *radar);
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 1693631..f344e1d 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2527,6 +2527,7 @@
 #ifdef CONFIG_MESH
 	{ INT_RANGE(mode, 0, 5) },
 	{ INT_RANGE(no_auto_peer, 0, 1) },
+	{ INT_RANGE(mesh_fwding, 0, 1) },
 	{ INT_RANGE(mesh_rssi_threshold, -255, 1) },
 #else /* CONFIG_MESH */
 	{ INT_RANGE(mode, 0, 4) },
@@ -2855,6 +2856,10 @@
 	os_free(cred->client_cert);
 	os_free(cred->private_key);
 	str_clear_free(cred->private_key_passwd);
+	os_free(cred->engine_id);
+	os_free(cred->ca_cert_id);
+	os_free(cred->cert_id);
+	os_free(cred->key_id);
 	os_free(cred->imsi);
 	str_clear_free(cred->milenage);
 	for (i = 0; i < cred->num_domain; i++)
@@ -2951,6 +2956,7 @@
 	os_free(config->ext_password_backend);
 	os_free(config->sae_groups);
 	wpabuf_free(config->ap_vendor_elements);
+	wpabuf_free(config->ap_assocresp_elements);
 	os_free(config->osu_dir);
 	os_free(config->bgscan);
 	os_free(config->wowlan_triggers);
@@ -3106,6 +3112,7 @@
 	ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
 	ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
 	ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
+	ssid->mesh_fwding = DEFAULT_MESH_FWDING;
 	ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
 #endif /* CONFIG_MESH */
 #ifdef CONFIG_HT_OVERRIDES
@@ -3139,6 +3146,7 @@
 #endif /* CONFIG_VHT_OVERRIDES */
 	ssid->proactive_key_caching = -1;
 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
+	ssid->sae_pwe = DEFAULT_SAE_PWE;
 #ifdef CONFIG_MACSEC
 	ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
 #endif /* CONFIG_MACSEC */
@@ -3616,6 +3624,11 @@
 		return 0;
 	}
 
+	if (os_strcmp(var, "engine") == 0) {
+		cred->engine = atoi(value);
+		return 0;
+	}
+
 	val = wpa_config_parse_string(value, &len);
 	if (val == NULL ||
 	    (os_strcmp(var, "excluded_ssid") != 0 &&
@@ -3671,6 +3684,30 @@
 		return 0;
 	}
 
+	if (os_strcmp(var, "engine_id") == 0) {
+		os_free(cred->engine_id);
+		cred->engine_id = val;
+		return 0;
+	}
+
+	if (os_strcmp(var, "ca_cert_id") == 0) {
+		os_free(cred->ca_cert_id);
+		cred->ca_cert_id = val;
+		return 0;
+	}
+
+	if (os_strcmp(var, "cert_id") == 0) {
+		os_free(cred->cert_id);
+		cred->cert_id = val;
+		return 0;
+	}
+
+	if (os_strcmp(var, "key_id") == 0) {
+		os_free(cred->key_id);
+		cred->key_id = val;
+		return 0;
+	}
+
 	if (os_strcmp(var, "imsi") == 0) {
 		os_free(cred->imsi);
 		cred->imsi = val;
@@ -4347,6 +4384,7 @@
 	config->user_mpm = DEFAULT_USER_MPM;
 	config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
 	config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
+	config->mesh_fwding = DEFAULT_MESH_FWDING;
 	config->dot11RSNASAERetransPeriod =
 		DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
 	config->fast_reauth = DEFAULT_FAST_REAUTH;
@@ -4909,33 +4947,46 @@
 	struct wpa_config *config, int line, const char *pos)
 {
 	struct wpabuf *tmp;
-	int len = os_strlen(pos) / 2;
-	u8 *p;
 
-	if (!len) {
+	if (!*pos) {
+		wpabuf_free(config->ap_vendor_elements);
+		config->ap_vendor_elements = NULL;
+		return 0;
+	}
+
+	tmp = wpabuf_parse_bin(pos);
+	if (!tmp) {
 		wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements",
 			   line);
 		return -1;
 	}
+	wpabuf_free(config->ap_vendor_elements);
+	config->ap_vendor_elements = tmp;
 
-	tmp = wpabuf_alloc(len);
-	if (tmp) {
-		p = wpabuf_put(tmp, len);
+	return 0;
+}
 
-		if (hexstr2bin(pos, p, len)) {
-			wpa_printf(MSG_ERROR, "Line %d: invalid "
-				   "ap_vendor_elements", line);
-			wpabuf_free(tmp);
-			return -1;
-		}
 
-		wpabuf_free(config->ap_vendor_elements);
-		config->ap_vendor_elements = tmp;
-	} else {
-		wpa_printf(MSG_ERROR, "Cannot allocate memory for "
-			   "ap_vendor_elements");
+static int wpa_config_process_ap_assocresp_elements(
+	const struct global_parse_data *data,
+	struct wpa_config *config, int line, const char *pos)
+{
+	struct wpabuf *tmp;
+
+	if (!*pos) {
+		wpabuf_free(config->ap_assocresp_elements);
+		config->ap_assocresp_elements = NULL;
+		return 0;
+	}
+
+	tmp = wpabuf_parse_bin(pos);
+	if (!tmp) {
+		wpa_printf(MSG_ERROR, "Line %d: invalid ap_assocresp_elements",
+			   line);
 		return -1;
 	}
+	wpabuf_free(config->ap_assocresp_elements);
+	config->ap_assocresp_elements = tmp;
 
 	return 0;
 }
@@ -5047,6 +5098,7 @@
 	{ INT(user_mpm), 0 },
 	{ INT_RANGE(max_peer_links, 0, 255), 0 },
 	{ INT(mesh_max_inactivity), 0 },
+	{ INT_RANGE(mesh_fwding, 0, 1), 0 },
 	{ INT(dot11RSNASAERetransPeriod), 0 },
 #endif /* CONFIG_MESH */
 	{ INT(disable_scan_offload), 0 },
@@ -5155,6 +5207,7 @@
 	{ INT_RANGE(sae_pmkid_in_assoc, 0, 1), 0 },
 	{ INT(dtim_period), 0 },
 	{ INT(beacon_int), 0 },
+	{ FUNC(ap_assocresp_elements), 0 },
 	{ FUNC(ap_vendor_elements), 0 },
 	{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
 	{ FUNC(freq_list), 0 },
@@ -5210,6 +5263,7 @@
 #ifdef CONFIG_PASN
 #ifdef CONFIG_TESTING_OPTIONS
 	{ INT_RANGE(force_kdk_derivation, 0, 1), 0 },
+	{ INT_RANGE(pasn_corrupt_mic, 0, 1), 0 },
 #endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN */
 };
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 914b5d9..696fb38 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -18,6 +18,7 @@
 #define DEFAULT_USER_MPM 1
 #define DEFAULT_MAX_PEER_LINKS 99
 #define DEFAULT_MESH_MAX_INACTIVITY 300
+#define DEFAULT_MESH_FWDING 1
 /*
  * The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard,
  * but use 1000 ms in practice to avoid issues on low power CPUs.
@@ -181,6 +182,31 @@
 	char *milenage;
 
 	/**
+	 * engine - Use an engine for private key operations
+	 */
+	int engine;
+
+	/**
+	 * engine_id - String identifying the engine to use
+	 */
+	char *engine_id;
+
+	/**
+	 * ca_cert_id - The CA certificate identifier when using an engine
+	 */
+	char *ca_cert_id;
+
+	/**
+	 * cert_id - The certificate identifier when using an engine
+	 */
+	char *cert_id;
+
+	/**
+	 * key_id - The private key identifier when using an engine
+	 */
+	char *key_id;
+
+	/**
 	 * domain_suffix_match - Constraint for server domain name
 	 *
 	 * If set, this FQDN is used as a suffix match requirement for the AAA
@@ -1244,6 +1270,17 @@
 	struct wpabuf *ap_vendor_elements;
 
 	/**
+	 * ap_assocresp_elements: Vendor specific elements for (Re)Association
+	 * Response frames
+	 *
+	 * This parameter can be used to define additional vendor specific
+	 * elements for (Re)Association Response frames in AP/P2P GO mode. The
+	 * format for these element(s) is a hexdump of the raw information
+	 * elements (id+len+payload for one or more elements).
+	 */
+	struct wpabuf *ap_assocresp_elements;
+
+	/**
 	 * ignore_old_scan_res - Ignore scan results older than request
 	 *
 	 * The driver may have a cache of scan results that makes it return
@@ -1380,6 +1417,14 @@
 	int mesh_max_inactivity;
 
 	/**
+	 * mesh_fwding - Mesh network layer-2 forwarding (dot11MeshForwarding)
+	 *
+	 * This controls whether to enable layer-2 forwarding.
+	 * By default: 1: enabled
+	 */
+	int mesh_fwding;
+
+	/**
 	 * dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame
 	 *
 	 * This timeout value is used in mesh STA to retransmit
@@ -1665,6 +1710,10 @@
 	 * secure LTF. Allow forcing KDK derivation for testing purposes.
 	 */
 	int force_kdk_derivation;
+
+	/* If set, corrupt the MIC in the 3rd Authentication frame of PASN */
+	int pasn_corrupt_mic;
+
 #endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN*/
 };
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 9fbfbf9..778da45 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -675,6 +675,7 @@
 	INT(mem_only_psk);
 	STR(sae_password);
 	STR(sae_password_id);
+	write_int(f, "sae_pwe", ssid->sae_pwe, DEFAULT_SAE_PWE);
 	write_proto(f, ssid);
 	write_key_mgmt(f, ssid);
 	INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
@@ -768,6 +769,7 @@
 #endif /* IEEE8021X_EAPOL */
 	INT(mode);
 	INT(no_auto_peer);
+	INT(mesh_fwding);
 	INT(frequency);
 	INT(enable_edmg);
 	INT(edmg_channel);
@@ -1025,6 +1027,17 @@
 
 	if (cred->sim_num != DEFAULT_USER_SELECTED_SIM)
 		fprintf(f, "\tsim_num=%d\n", cred->sim_num);
+
+	if (cred->engine)
+		fprintf(f, "\tengine=%d\n", cred->engine);
+	if (cred->engine_id)
+		fprintf(f, "\tengine_id=\"%s\"\n", cred->engine_id);
+	if (cred->key_id)
+		fprintf(f, "\tkey_id=\"%s\"\n", cred->key_id);
+	if (cred->cert_id)
+		fprintf(f, "\tcert_id=\"%s\"\n", cred->cert_id);
+	if (cred->ca_cert_id)
+		fprintf(f, "\tca_cert_id=\"%s\"\n", cred->ca_cert_id);
 }
 
 
@@ -1364,6 +1377,18 @@
 		}
 	}
 
+	if (config->ap_assocresp_elements) {
+		int i, len = wpabuf_len(config->ap_assocresp_elements);
+		const u8 *p = wpabuf_head_u8(config->ap_assocresp_elements);
+
+		if (len > 0) {
+			fprintf(f, "ap_assocresp_elements=");
+			for (i = 0; i < len; i++)
+				fprintf(f, "%02x", *p++);
+			fprintf(f, "\n");
+		}
+	}
+
 	if (config->ignore_old_scan_res)
 		fprintf(f, "ignore_old_scan_res=%d\n",
 			config->ignore_old_scan_res);
@@ -1449,6 +1474,9 @@
 		fprintf(f, "mesh_max_inactivity=%d\n",
 			config->mesh_max_inactivity);
 
+	if (config->mesh_fwding != DEFAULT_MESH_FWDING)
+		fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding);
+
 	if (config->dot11RSNASAERetransPeriod !=
 	    DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD)
 		fprintf(f, "dot11RSNASAERetransPeriod=%d\n",
diff --git a/wpa_supplicant/config_none.c b/wpa_supplicant/config_none.c
index 2aac28f..0bc977e 100644
--- a/wpa_supplicant/config_none.c
+++ b/wpa_supplicant/config_none.c
@@ -5,7 +5,7 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  *
- * This file implements dummy example of a configuration backend. None of the
+ * This file implements stub example of a configuration backend. None of the
  * functions are actually implemented so this can be used as a simple
  * compilation test or a starting point for a new configuration backend.
  */
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index d1ff5f8..dd8b1d9 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -45,6 +45,9 @@
 #define DEFAULT_USER_SELECTED_SIM 1
 #define DEFAULT_MAX_OPER_CHWIDTH -1
 
+/* Consider global sae_pwe for SAE mechanism for PWE derivation */
+#define DEFAULT_SAE_PWE 4
+
 struct psk_list_entry {
 	struct dl_list list;
 	u8 addr[ETH_ALEN];
@@ -545,6 +548,11 @@
 	int dot11MeshConfirmTimeout; /* msec */
 	int dot11MeshHoldingTimeout; /* msec */
 
+	/**
+	 * Mesh network layer-2 forwarding (dot11MeshForwarding)
+	 */
+	int mesh_fwding;
+
 	int ht;
 	int ht40;
 
@@ -1155,6 +1163,19 @@
 	 * configuration.
 	 */
 	bool was_recently_reconfigured;
+
+	/**
+	 * sae_pwe - SAE mechanism for PWE derivation
+	 *
+	 * Internally, special value 4 (DEFAULT_SAE_PWE) is used to indicate
+	 * that the parameter is not set and the global sae_pwe value needs to
+	 * be considered.
+	 *
+	 * 0 = hunting-and-pecking loop only
+	 * 1 = hash-to-element only
+	 * 2 = both hunting-and-pecking loop and hash-to-element enabled
+	 */
+	int sae_pwe;
 };
 
 #endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index dffcd1b..dc6c772 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -39,6 +39,7 @@
 #include "driver_i.h"
 #include "wps_supplicant.h"
 #include "ibss_rsn.h"
+#include "wpas_glue.h"
 #include "ap.h"
 #include "p2p_supplicant.h"
 #include "p2p/p2p.h"
@@ -512,6 +513,19 @@
 	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
 		eapol_sm_configure(wpa_s->eapol,
 				   -1, -1, -1, atoi(value));
+#ifdef CONFIG_TESTING_OPTIONS
+	} else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
+		if (os_strcmp(value, "Auto") == 0)
+			eapol_sm_notify_portControl(wpa_s->eapol, Auto);
+		else if (os_strcmp(value, "ForceUnauthorized") == 0)
+			eapol_sm_notify_portControl(wpa_s->eapol,
+						    ForceUnauthorized);
+		else if (os_strcmp(value, "ForceAuthorized") == 0)
+			eapol_sm_notify_portControl(wpa_s->eapol,
+						    ForceAuthorized);
+		else
+			ret = -1;
+#endif /* CONFIG_TESTING_OPTIONS */
 	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
 				     atoi(value))) {
@@ -554,10 +568,10 @@
 				   (wps_version_number & 0xf0) >> 4,
 				   wps_version_number & 0x0f);
 		}
-	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
-		wps_testing_dummy_cred = atoi(value);
-		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
-			   wps_testing_dummy_cred);
+	} else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) {
+		wps_testing_stub_cred = atoi(value);
+		wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d",
+			   wps_testing_stub_cred);
 	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
 		wps_corrupt_pkhash = atoi(value);
 		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
@@ -818,6 +832,10 @@
 		ret = wpas_ctrl_iface_set_dso(wpa_s, value);
 	} else if (os_strcasecmp(cmd, "force_hunting_and_pecking_pwe") == 0) {
 		wpa_s->force_hunting_and_pecking_pwe = (atoi(value) != 0) ? 1 : 0;
+	} else if (os_strcasecmp(cmd, "disable_scs_support") == 0) {
+		wpa_s->disable_scs_support = !!atoi(value);
+	} else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) {
+		wpa_s->disable_mscs_support = !!atoi(value);
 #ifdef CONFIG_DPP
 	} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
 		os_free(wpa_s->dpp_config_obj_override);
@@ -906,6 +924,8 @@
 			return -1;
 		wnm_set_coloc_intf_elems(wpa_s, elems);
 #endif /* CONFIG_WNM */
+	} else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) {
+		wpa_s->enable_dscp_policy_capa = !!atoi(value);
 	} else {
 		value[-1] = '=';
 		ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -3001,19 +3021,17 @@
 					    ie2, 2 + ie2[1]);
 	}
 	rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
-	if (rsnxe && rsnxe[1] >= 1) {
-		if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
-			ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
-			if (os_snprintf_error(end - pos, ret))
-				return -1;
-			pos += ret;
-		}
-		if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
-			ret = os_snprintf(pos, end - pos, "[SAE-PK]");
-			if (os_snprintf_error(end - pos, ret))
-				return -1;
-			pos += ret;
-		}
+	if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
+		ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
+		if (os_snprintf_error(end - pos, ret))
+			return -1;
+		pos += ret;
+	}
+	if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
+		ret = os_snprintf(pos, end - pos, "[SAE-PK]");
+		if (os_snprintf_error(end - pos, ret))
+			return -1;
+		pos += ret;
 	}
 	osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
 	if (osen_ie)
@@ -3777,47 +3795,6 @@
 }
 
 
-static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s,
-				 struct wpa_cred *cred)
-{
-	struct wpa_ssid *ssid;
-	char str[20];
-	int id;
-
-	if (cred == NULL) {
-		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
-		return -1;
-	}
-
-	id = cred->id;
-	if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
-		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
-		return -1;
-	}
-
-	wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
-
-	/* Remove any network entry created based on the removed credential */
-	ssid = wpa_s->conf->ssid;
-	while (ssid) {
-		if (ssid->parent_cred == cred) {
-			int res;
-
-			wpa_printf(MSG_DEBUG, "Remove network id %d since it "
-				   "used the removed credential", ssid->id);
-			res = os_snprintf(str, sizeof(str), "%d", ssid->id);
-			if (os_snprintf_error(sizeof(str), res))
-				str[sizeof(str) - 1] = '\0';
-			ssid = ssid->next;
-			wpa_supplicant_ctrl_iface_remove_network(wpa_s, str);
-		} else
-			ssid = ssid->next;
-	}
-
-	return 0;
-}
-
-
 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
 						 char *cmd)
 {
@@ -3828,13 +3805,7 @@
 	 * "provisioning_sp=<FQDN> */
 	if (os_strcmp(cmd, "all") == 0) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
-		cred = wpa_s->conf->cred;
-		while (cred) {
-			prev = cred;
-			cred = cred->next;
-			wpas_ctrl_remove_cred(wpa_s, prev);
-		}
-		return 0;
+		return wpas_remove_all_creds(wpa_s);
 	}
 
 	if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) {
@@ -3850,7 +3821,7 @@
 					if (os_strcmp(prev->domain[i], cmd + 8)
 					    != 0)
 						continue;
-					wpas_ctrl_remove_cred(wpa_s, prev);
+					wpas_remove_cred(wpa_s, prev);
 					break;
 				}
 			}
@@ -3867,7 +3838,7 @@
 			cred = cred->next;
 			if (prev->provisioning_sp &&
 			    os_strcmp(prev->provisioning_sp, cmd + 16) == 0)
-				wpas_ctrl_remove_cred(wpa_s, prev);
+				wpas_remove_cred(wpa_s, prev);
 		}
 		return 0;
 	}
@@ -3876,7 +3847,7 @@
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
 
 	cred = wpa_config_get_cred(wpa_s->conf, id);
-	return wpas_ctrl_remove_cred(wpa_s, cred);
+	return wpas_remove_cred(wpa_s, cred);
 }
 
 
@@ -4810,7 +4781,9 @@
 
 #ifdef CONFIG_DPP
 	if (os_strcmp(field, "dpp") == 0) {
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+		res = os_snprintf(buf, buflen, "DPP=3");
+#elif defined(CONFIG_DPP2)
 		res = os_snprintf(buf, buflen, "DPP=2");
 #else /* CONFIG_DPP2 */
 		res = os_snprintf(buf, buflen, "DPP=1");
@@ -5101,19 +5074,17 @@
 						    mesh ? "RSN" : "WPA2", ie2,
 						    2 + ie2[1]);
 		rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
-		if (rsnxe && rsnxe[1] >= 1) {
-			if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
-				ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
-				if (os_snprintf_error(end - pos, ret))
-					return -1;
-				pos += ret;
-			}
-			if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
-				ret = os_snprintf(pos, end - pos, "[SAE-PK]");
-				if (os_snprintf_error(end - pos, ret))
-					return -1;
-				pos += ret;
-			}
+		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
+			ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
+			if (os_snprintf_error(end - pos, ret))
+				return -1;
+			pos += ret;
+		}
+		if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
+			ret = os_snprintf(pos, end - pos, "[SAE-PK]");
+			if (os_snprintf_error(end - pos, ret))
+				return -1;
+			pos += ret;
 		}
 		osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
 		if (osen_ie)
@@ -5658,6 +5629,7 @@
 	u8 bssid[ETH_ALEN];
 	struct wpa_bss *bss;
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	struct wpa_radio_work *already_connecting;
 
 	if (hwaddr_aton(addr, bssid)) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
@@ -5685,9 +5657,18 @@
 	 * allow roaming to other networks
 	 */
 
+	already_connecting = radio_work_pending(wpa_s, "sme-connect");
 	wpa_s->reassociate = 1;
 	wpa_supplicant_connect(wpa_s, bss, ssid);
 
+	/*
+	 * Indicate that an explicitly requested roam is in progress so scan
+	 * results that come in before the 'sme-connect' radio work gets
+	 * executed do not override the original connection attempt.
+	 */
+	if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
+		wpa_s->roam_in_progress = true;
+
 	return 0;
 #endif /* CONFIG_NO_SCAN_PROCESSING */
 }
@@ -5705,12 +5686,16 @@
 	const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
 	u8 seek_count = 0;
 	int freq = 0;
+	bool include_6ghz = false;
 
 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
 		wpa_dbg(wpa_s, MSG_INFO,
 			"Reject P2P_FIND since interface is disabled");
 		return -1;
 	}
+
+	if (os_strstr(cmd, " include_6ghz"))
+		include_6ghz = true;
 	if (os_strstr(cmd, "type=social"))
 		type = P2P_FIND_ONLY_SOCIAL;
 	else if (os_strstr(cmd, "type=progressive"))
@@ -5770,7 +5755,8 @@
 	}
 
 	return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
-			     _dev_id, search_delay, seek_count, seek, freq);
+			     _dev_id, search_delay, seek_count, seek, freq,
+			     include_6ghz);
 }
 
 
@@ -5895,7 +5881,7 @@
 	for (i = 0; p2ps_prov->cpt_priority[i]; i++)
 		p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i];
 
-	/* force conncap with tstCap (no sanity checks) */
+	/* force conncap with tstCap (no validity checks) */
 	pos = os_strstr(cmd, "tstCap=");
 	if (pos) {
 		role = strtol(pos + 7, NULL, 16);
@@ -6023,6 +6009,7 @@
 	u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
 	size_t group_ssid_len = 0;
 	int he;
+	bool allow_6ghz;
 
 	if (!wpa_s->global->p2p_init_wpa_s)
 		return -1;
@@ -6060,6 +6047,7 @@
 		}
 	}
 	join = os_strstr(pos, " join") != NULL;
+	allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
 	auth = os_strstr(pos, " auth") != NULL;
 	automatic = os_strstr(pos, " auto") != NULL;
 	pd = os_strstr(pos, " provdisc") != NULL;
@@ -6097,6 +6085,9 @@
 	if (max_oper_chwidth < 0)
 		return -1;
 
+	if (allow_6ghz && chwidth == 40)
+		max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
+
 	pos2 = os_strstr(pos, " ssid=");
 	if (pos2) {
 		char *end;
@@ -6139,7 +6130,7 @@
 				   persistent_group, automatic, join,
 				   auth, go_intent, freq, freq2, persistent_id,
 				   pd, ht40, vht, max_oper_chwidth, he, edmg,
-				   group_ssid, group_ssid_len);
+				   group_ssid, group_ssid_len, allow_6ghz);
 	if (new_pin == -2) {
 		os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
 		return 25;
@@ -6696,6 +6687,7 @@
 	int freq = 0, pref_freq = 0;
 	int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
 	int edmg;
+	bool allow_6ghz;
 
 	id = atoi(cmd);
 	pos = os_strstr(cmd, " peer=");
@@ -6747,8 +6739,14 @@
 	if (max_oper_chwidth < 0)
 		return -1;
 
+	allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
+
+	if (allow_6ghz && chwidth == 40)
+		max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
+
 	return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
-			       max_oper_chwidth, pref_freq, he, edmg);
+			       max_oper_chwidth, pref_freq, he, edmg,
+			       allow_6ghz);
 }
 
 
@@ -6756,6 +6754,7 @@
 {
 	char *pos;
 	u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL;
+	bool allow_6ghz;
 
 	pos = os_strstr(cmd, " peer=");
 	if (!pos)
@@ -6768,6 +6767,8 @@
 		return -1;
 	}
 
+	allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL;
+
 	pos = os_strstr(pos, " go_dev_addr=");
 	if (pos) {
 		pos += 13;
@@ -6779,7 +6780,7 @@
 		go_dev = go_dev_addr;
 	}
 
-	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev);
+	return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz);
 }
 
 
@@ -6797,7 +6798,7 @@
 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
 					 int id, int freq, int vht_center_freq2,
 					 int ht40, int vht, int vht_chwidth,
-					 int he, int edmg)
+					 int he, int edmg, bool allow_6ghz)
 {
 	struct wpa_ssid *ssid;
 
@@ -6812,13 +6813,14 @@
 	return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
 					     vht_center_freq2, 0, ht40, vht,
 					     vht_chwidth, he, edmg,
-					     NULL, 0, 0);
+					     NULL, 0, 0, allow_6ghz);
 }
 
 
 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
 {
 	int freq = 0, persistent = 0, group_id = -1;
+	bool allow_6ghz = false;
 	int vht = wpa_s->conf->p2p_go_vht;
 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
 	int he = wpa_s->conf->p2p_go_he;
@@ -6851,6 +6853,8 @@
 			edmg = 1;
 		} else if (os_strcmp(token, "persistent") == 0) {
 			persistent = 1;
+		} else if (os_strcmp(token, "allow_6ghz") == 0) {
+			allow_6ghz = true;
 		} else {
 			wpa_printf(MSG_DEBUG,
 				   "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'",
@@ -6883,14 +6887,21 @@
 	if (max_oper_chwidth < 0)
 		return -1;
 
+	if (allow_6ghz && chwidth == 40)
+		max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
+
+	/* Allow DFS to be used for Autonomous GO */
+	wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags &
+				     WPA_DRIVER_FLAGS_DFS_OFFLOAD);
+
 	if (group_id >= 0)
 		return p2p_ctrl_group_add_persistent(wpa_s, group_id,
 						     freq, freq2, ht40, vht,
 						     max_oper_chwidth, he,
-						     edmg);
+						     edmg, allow_6ghz);
 
 	return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
-				  max_oper_chwidth, he, edmg);
+				  max_oper_chwidth, he, edmg, allow_6ghz);
 }
 
 
@@ -8393,7 +8404,7 @@
 
 #ifdef CONFIG_WPS_TESTING
 	wps_version_number = 0x20;
-	wps_testing_dummy_cred = 0;
+	wps_testing_stub_cred = 0;
 	wps_corrupt_pkhash = 0;
 	wps_force_auth_types_in_use = 0;
 	wps_force_encr_types_in_use = 0;
@@ -8423,7 +8434,9 @@
 	dpp_pkex_ephemeral_key_override_len = 0;
 	dpp_protocol_key_override_len = 0;
 	dpp_nonce_override_len = 0;
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+	dpp_version_override = 3;
+#elif defined(CONFIG_DPP2)
 	dpp_version_override = 2;
 #else /* CONFIG_DPP2 */
 	dpp_version_override = 1;
@@ -8516,6 +8529,9 @@
 	wpabuf_free(wpa_s->rsnxe_override_eapol);
 	wpa_s->rsnxe_override_eapol = NULL;
 	wpas_clear_driver_signal_override(wpa_s);
+	wpa_s->disable_scs_support = 0;
+	wpa_s->disable_mscs_support = 0;
+	wpa_s->enable_dscp_policy_capa = 0;
 	wpa_s->oci_freq_override_eapol = 0;
 	wpa_s->oci_freq_override_saquery_req = 0;
 	wpa_s->oci_freq_override_saquery_resp = 0;
@@ -9292,6 +9308,132 @@
 }
 
 
+static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
+					      char *param)
+{
+	union wpa_event_data event;
+	struct assoc_info *ai;
+	char *ctx = NULL;
+	int ret = -1;
+	struct wpabuf *req_ies = NULL;
+	struct wpabuf *resp_ies = NULL;
+	struct wpabuf *resp_frame = NULL;
+	struct wpabuf *beacon_ies = NULL;
+	struct wpabuf *key_replay_ctr = NULL;
+	struct wpabuf *ptk_kck = NULL;
+	struct wpabuf *ptk_kek = NULL;
+	struct wpabuf *fils_pmk = NULL;
+	char *str, *pos;
+	u8 addr[ETH_ALEN];
+	u8 fils_pmkid[PMKID_LEN];
+
+	os_memset(&event, 0, sizeof(event));
+	ai = &event.assoc_info;
+
+	while ((str = str_token(param, " ", &ctx))) {
+		pos = os_strchr(str, '=');
+		if (!pos)
+			goto fail;
+		*pos++ = '\0';
+
+		if (os_strcmp(str, "reassoc") == 0) {
+			ai->reassoc = atoi(pos);
+		} else if (os_strcmp(str, "req_ies") == 0) {
+			wpabuf_free(req_ies);
+			req_ies = wpabuf_parse_bin(pos);
+			if (!req_ies)
+				goto fail;
+			ai->req_ies = wpabuf_head(req_ies);
+			ai->req_ies_len = wpabuf_len(req_ies);
+		} else if (os_strcmp(str, "resp_ies") == 0) {
+			wpabuf_free(resp_ies);
+			resp_ies = wpabuf_parse_bin(pos);
+			if (!resp_ies)
+				goto fail;
+			ai->resp_ies = wpabuf_head(resp_ies);
+			ai->resp_ies_len = wpabuf_len(resp_ies);
+		} else if (os_strcmp(str, "resp_frame") == 0) {
+			wpabuf_free(resp_frame);
+			resp_frame = wpabuf_parse_bin(pos);
+			if (!resp_frame)
+				goto fail;
+			ai->resp_frame = wpabuf_head(resp_frame);
+			ai->resp_frame_len = wpabuf_len(resp_frame);
+		} else if (os_strcmp(str, "beacon_ies") == 0) {
+			wpabuf_free(beacon_ies);
+			beacon_ies = wpabuf_parse_bin(pos);
+			if (!beacon_ies)
+				goto fail;
+			ai->beacon_ies = wpabuf_head(beacon_ies);
+			ai->beacon_ies_len = wpabuf_len(beacon_ies);
+		} else if (os_strcmp(str, "freq") == 0) {
+			ai->freq = atoi(pos);
+		} else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
+			ai->wmm_params.info_bitmap = atoi(pos);
+		} else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
+			ai->wmm_params.uapsd_queues = atoi(pos);
+		} else if (os_strcmp(str, "addr") == 0) {
+			if (hwaddr_aton(pos, addr))
+				goto fail;
+			ai->addr = addr;
+		} else if (os_strcmp(str, "authorized") == 0) {
+			ai->authorized = atoi(pos);
+		} else if (os_strcmp(str, "key_replay_ctr") == 0) {
+			wpabuf_free(key_replay_ctr);
+			key_replay_ctr = wpabuf_parse_bin(pos);
+			if (!key_replay_ctr)
+				goto fail;
+			ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
+			ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
+		} else if (os_strcmp(str, "ptk_kck") == 0) {
+			wpabuf_free(ptk_kck);
+			ptk_kck = wpabuf_parse_bin(pos);
+			if (!ptk_kck)
+				goto fail;
+			ai->ptk_kck = wpabuf_head(ptk_kck);
+			ai->ptk_kck_len = wpabuf_len(ptk_kck);
+		} else if (os_strcmp(str, "ptk_kek") == 0) {
+			wpabuf_free(ptk_kek);
+			ptk_kek = wpabuf_parse_bin(pos);
+			if (!ptk_kek)
+				goto fail;
+			ai->ptk_kek = wpabuf_head(ptk_kek);
+			ai->ptk_kek_len = wpabuf_len(ptk_kek);
+		} else if (os_strcmp(str, "subnet_status") == 0) {
+			ai->subnet_status = atoi(pos);
+		} else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
+			ai->fils_erp_next_seq_num = atoi(pos);
+		} else if (os_strcmp(str, "fils_pmk") == 0) {
+			wpabuf_free(fils_pmk);
+			fils_pmk = wpabuf_parse_bin(pos);
+			if (!fils_pmk)
+				goto fail;
+			ai->fils_pmk = wpabuf_head(fils_pmk);
+			ai->fils_pmk_len = wpabuf_len(fils_pmk);
+		} else if (os_strcmp(str, "fils_pmkid") == 0) {
+			if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
+				goto fail;
+			ai->fils_pmkid = fils_pmkid;
+		} else {
+			goto fail;
+		}
+	}
+
+	wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
+	ret = 0;
+fail:
+	wpabuf_free(req_ies);
+	wpabuf_free(resp_ies);
+	wpabuf_free(resp_frame);
+	wpabuf_free(beacon_ies);
+	wpabuf_free(key_replay_ctr);
+	wpabuf_free(ptk_kck);
+	wpabuf_free(ptk_kek);
+	wpabuf_free(fils_pmk);
+	return ret;
+}
+
+
 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
 {
 	char *pos, *param;
@@ -9324,6 +9466,8 @@
 		return 0;
 	} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
 		return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
+	} else if (os_strcmp(cmd, "ASSOC") == 0) {
+		return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
 	} else {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
 			cmd);
@@ -9374,6 +9518,45 @@
 }
 
 
+static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd)
+{
+	char *pos;
+	u8 dst[ETH_ALEN], *buf;
+	int used, ret;
+	size_t len;
+	unsigned int prev;
+
+	wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd);
+
+	pos = cmd;
+	used = hwaddr_aton2(pos, dst);
+	if (used < 0)
+		return -1;
+	pos += used;
+	while (*pos == ' ')
+		pos++;
+
+	len = os_strlen(pos);
+	if (len & 1)
+		return -1;
+	len /= 2;
+
+	buf = os_malloc(len);
+	if (!buf || hexstr2bin(pos, buf, len) < 0) {
+		os_free(buf);
+		return -1;
+	}
+
+	prev = wpa_s->ext_eapol_frame_io;
+	wpa_s->ext_eapol_frame_io = 0;
+	ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len);
+	wpa_s->ext_eapol_frame_io = prev;
+	os_free(buf);
+
+	return ret;
+}
+
+
 static u16 ipv4_hdr_checksum(const void *buf, size_t len)
 {
 	size_t i;
@@ -9784,6 +9967,103 @@
 #endif /* CONFIG_SME */
 }
 
+
+static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s,
+					  const char *cmd)
+{
+	u8 dtok = 1;
+	int exponent = 10;
+	int mantissa = 8192;
+	u8 min_twt = 255;
+	unsigned long long twt = 0;
+	bool requestor = true;
+	int setup_cmd = 0;
+	bool trigger = true;
+	bool implicit = true;
+	bool flow_type = true;
+	int flow_id = 0;
+	bool protection = false;
+	u8 twt_channel = 0;
+	u8 control = BIT(4); /* Control field (IEEE P802.11ax/D8.0 Figure
+			      * 9-687): B4 = TWT Information Frame Disabled */
+	const char *tok_s;
+
+	tok_s = os_strstr(cmd, " dialog=");
+	if (tok_s)
+		dtok = atoi(tok_s + os_strlen(" dialog="));
+
+	tok_s = os_strstr(cmd, " exponent=");
+	if (tok_s)
+		exponent = atoi(tok_s + os_strlen(" exponent="));
+
+	tok_s = os_strstr(cmd, " mantissa=");
+	if (tok_s)
+		mantissa = atoi(tok_s + os_strlen(" mantissa="));
+
+	tok_s = os_strstr(cmd, " min_twt=");
+	if (tok_s)
+		min_twt = atoi(tok_s + os_strlen(" min_twt="));
+
+	tok_s = os_strstr(cmd, " setup_cmd=");
+	if (tok_s)
+		setup_cmd = atoi(tok_s + os_strlen(" setup_cmd="));
+
+	tok_s = os_strstr(cmd, " twt=");
+	if (tok_s)
+		sscanf(tok_s + os_strlen(" twt="), "%llu", &twt);
+
+	tok_s = os_strstr(cmd, " requestor=");
+	if (tok_s)
+		requestor = atoi(tok_s + os_strlen(" requestor="));
+
+	tok_s = os_strstr(cmd, " trigger=");
+	if (tok_s)
+		trigger = atoi(tok_s + os_strlen(" trigger="));
+
+	tok_s = os_strstr(cmd, " implicit=");
+	if (tok_s)
+		implicit = atoi(tok_s + os_strlen(" implicit="));
+
+	tok_s = os_strstr(cmd, " flow_type=");
+	if (tok_s)
+		flow_type = atoi(tok_s + os_strlen(" flow_type="));
+
+	tok_s = os_strstr(cmd, " flow_id=");
+	if (tok_s)
+		flow_id = atoi(tok_s + os_strlen(" flow_id="));
+
+	tok_s = os_strstr(cmd, " protection=");
+	if (tok_s)
+		protection = atoi(tok_s + os_strlen(" protection="));
+
+	tok_s = os_strstr(cmd, " twt_channel=");
+	if (tok_s)
+		twt_channel = atoi(tok_s + os_strlen(" twt_channel="));
+
+	tok_s = os_strstr(cmd, " control=");
+	if (tok_s)
+		control = atoi(tok_s + os_strlen(" control="));
+
+	return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt,
+				   setup_cmd, twt, requestor, trigger, implicit,
+				   flow_type, flow_id, protection, twt_channel,
+				   control);
+}
+
+
+static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
+					     const char *cmd)
+{
+	u8 flags = 0x1;
+	const char *tok_s;
+
+	tok_s = os_strstr(cmd, " flags=");
+	if (tok_s)
+		flags = atoi(tok_s + os_strlen(" flags="));
+
+	return wpas_twt_send_teardown(wpa_s, flags);
+}
+
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
@@ -10303,6 +10583,8 @@
 	if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration,
 		   &entry->akmp, &entry->opportunistic) != 4)
 		goto fail;
+	if (reauth_time > expiration)
+		goto fail;
 	for (i = 0; i < 4; i++) {
 		pos = os_strchr(pos, ' ');
 		if (!pos) {
@@ -10324,6 +10606,8 @@
 
 	entry->network_ctx = ssid;
 
+	entry->external = true;
+
 	wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
 	entry = NULL;
 	ret = 0;
@@ -10493,15 +10777,18 @@
 	u8 bssid[ETH_ALEN];
 	int akmp = -1, cipher = -1, got_bssid = 0;
 	u16 group = 0xFFFF;
-	int id = 0;
+	u8 *comeback = NULL;
+	size_t comeback_len = 0;
+	int id = 0, ret = -1;
 
 	/*
 	 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
+	 *    [comeback=<hexdump>]
 	 */
 	while ((token = str_token(cmd, " ", &context))) {
 		if (os_strncmp(token, "bssid=", 6) == 0) {
 			if (hwaddr_aton(token + 6, bssid))
-				return -1;
+				goto out;
 			got_bssid = 1;
 		} else if (os_strcmp(token, "akmp=PASN") == 0) {
 			akmp = WPA_KEY_MGMT_PASN;
@@ -10535,24 +10822,629 @@
 			group = atoi(token + 6);
 		} else if (os_strncmp(token, "nid=", 4) == 0) {
 			id = atoi(token + 4);
+		} else if (os_strncmp(token, "comeback=", 9) == 0) {
+			comeback_len = os_strlen(token + 9);
+			if (comeback || !comeback_len || comeback_len % 2)
+				goto out;
+
+			comeback_len /= 2;
+			comeback = os_malloc(comeback_len);
+			if (!comeback ||
+			    hexstr2bin(token + 9, comeback, comeback_len))
+				goto out;
 		} else {
 			wpa_printf(MSG_DEBUG,
 				   "CTRL: PASN Invalid parameter: '%s'",
 				   token);
-			return -1;
+			goto out;
 		}
 	}
 
 	if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
 		wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
+		goto out;
+	}
+
+	ret = wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id,
+				   comeback, comeback_len);
+out:
+	os_free(comeback);
+	return ret;
+}
+
+
+static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
+					       const char *cmd)
+{
+	u8 bssid[ETH_ALEN];
+
+	if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
+		wpa_printf(MSG_DEBUG,
+			   "CTRL: PASN_DEAUTH without valid BSSID");
 		return -1;
 	}
 
-	return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id);
+	return wpas_pasn_deauthenticate(wpa_s, bssid);
 }
+
 #endif /* CONFIG_PASN */
 
 
+static int set_type4_frame_classifier(const char *cmd,
+				      struct type4_params *param)
+{
+	const char *pos, *end;
+	u8 classifier_mask = 0;
+	int ret;
+	char addr[INET6_ADDRSTRLEN];
+	size_t alen;
+
+	if (os_strstr(cmd, "ip_version=ipv4")) {
+		param->ip_version = IPV4;
+	} else if (os_strstr(cmd, "ip_version=ipv6")) {
+		param->ip_version = IPV6;
+	} else {
+		wpa_printf(MSG_ERROR, "IP version missing/invalid");
+		return -1;
+	}
+
+	classifier_mask |= BIT(0);
+
+	pos = os_strstr(cmd, "src_ip=");
+	if (pos) {
+		pos += 7;
+		end = os_strchr(pos, ' ');
+		if (!end)
+			end = pos + os_strlen(pos);
+
+		alen = end - pos;
+		if (alen >= INET6_ADDRSTRLEN)
+			return -1;
+		os_memcpy(addr, pos, alen);
+		addr[alen] = '\0';
+		if (param->ip_version == IPV4)
+			ret = inet_pton(AF_INET, addr,
+					&param->ip_params.v4.src_ip);
+		else
+			ret = inet_pton(AF_INET6, addr,
+					&param->ip_params.v6.src_ip);
+
+		if (ret != 1) {
+			wpa_printf(MSG_ERROR,
+				   "Error converting src IP address to binary ret=%d",
+				   ret);
+			return -1;
+		}
+
+		classifier_mask |= BIT(1);
+	}
+
+	pos = os_strstr(cmd, "dst_ip=");
+	if (pos) {
+		pos += 7;
+		end = os_strchr(pos, ' ');
+		if (!end)
+			end = pos + os_strlen(pos);
+
+		alen = end - pos;
+		if (alen >= INET6_ADDRSTRLEN)
+			return -1;
+		os_memcpy(addr, pos, alen);
+		addr[alen] = '\0';
+		if (param->ip_version == IPV4)
+			ret = inet_pton(AF_INET, addr,
+					&param->ip_params.v4.dst_ip);
+		else
+			ret = inet_pton(AF_INET6, addr,
+					&param->ip_params.v6.dst_ip);
+
+		if (ret != 1) {
+			wpa_printf(MSG_ERROR,
+				   "Error converting dst IP address to binary ret=%d",
+				   ret);
+			return -1;
+		}
+
+		classifier_mask |= BIT(2);
+	}
+
+	pos = os_strstr(cmd, "src_port=");
+	if (pos && atoi(pos + 9) > 0) {
+		if (param->ip_version == IPV4)
+			param->ip_params.v4.src_port = atoi(pos + 9);
+		else
+			param->ip_params.v6.src_port = atoi(pos + 9);
+		classifier_mask |= BIT(3);
+	}
+
+	pos = os_strstr(cmd, "dst_port=");
+	if (pos && atoi(pos + 9) > 0) {
+		if (param->ip_version == IPV4)
+			param->ip_params.v4.dst_port = atoi(pos + 9);
+		else
+			param->ip_params.v6.dst_port = atoi(pos + 9);
+		classifier_mask |= BIT(4);
+	}
+
+	pos = os_strstr(cmd, "dscp=");
+	if (pos && atoi(pos + 5) > 0) {
+		if (param->ip_version == IPV4)
+			param->ip_params.v4.dscp = atoi(pos + 5);
+		else
+			param->ip_params.v6.dscp = atoi(pos + 5);
+		classifier_mask |= BIT(5);
+	}
+
+	if (param->ip_version == IPV4) {
+		pos = os_strstr(cmd, "protocol=");
+		if (pos) {
+			if (os_strstr(pos, "udp")) {
+				param->ip_params.v4.protocol = 17;
+			} else if (os_strstr(pos, "tcp")) {
+				param->ip_params.v4.protocol = 6;
+			} else if (os_strstr(pos, "esp")) {
+				param->ip_params.v4.protocol = 50;
+			} else {
+				wpa_printf(MSG_ERROR, "Invalid protocol");
+				return -1;
+			}
+			classifier_mask |= BIT(6);
+		}
+	} else {
+		pos = os_strstr(cmd, "next_header=");
+		if (pos) {
+			if (os_strstr(pos, "udp")) {
+				param->ip_params.v6.next_header = 17;
+			} else if (os_strstr(pos, "tcp")) {
+				param->ip_params.v6.next_header = 6;
+			} else if (os_strstr(pos, "esp")) {
+				param->ip_params.v6.next_header = 50;
+			} else {
+				wpa_printf(MSG_ERROR, "Invalid next header");
+				return -1;
+			}
+
+			classifier_mask |= BIT(6);
+		}
+
+		pos = os_strstr(cmd, "flow_label=");
+		if (pos) {
+			pos += 11;
+			end = os_strchr(pos, ' ');
+			if (!end)
+				end = pos + os_strlen(pos);
+
+			if (end - pos != 6 ||
+			    hexstr2bin(pos, param->ip_params.v6.flow_label,
+				       3) ||
+			    param->ip_params.v6.flow_label[0] > 0x0F) {
+				wpa_printf(MSG_ERROR, "Invalid flow label");
+				return -1;
+			}
+
+			classifier_mask |= BIT(7);
+		}
+	}
+
+	param->classifier_mask = classifier_mask;
+	return 0;
+}
+
+
+static int set_type10_frame_classifier(const char *cmd,
+				       struct type10_params *param)
+{
+	const char *pos, *end;
+	size_t filter_len;
+
+	pos = os_strstr(cmd, "prot_instance=");
+	if (!pos) {
+		wpa_printf(MSG_ERROR, "Protocol instance missing");
+		return -1;
+	}
+	param->prot_instance = atoi(pos + 14);
+
+	pos = os_strstr(cmd, "prot_number=");
+	if (!pos) {
+		wpa_printf(MSG_ERROR, "Protocol number missing");
+		return -1;
+	}
+	if (os_strstr(pos, "udp")) {
+		param->prot_number = 17;
+	} else if (os_strstr(pos, "tcp")) {
+		param->prot_number = 6;
+	} else if (os_strstr(pos, "esp")) {
+		param->prot_number = 50;
+	} else {
+		wpa_printf(MSG_ERROR, "Invalid protocol number");
+		return -1;
+	}
+
+	pos = os_strstr(cmd, "filter_value=");
+	if (!pos) {
+		wpa_printf(MSG_ERROR,
+			   "Classifier parameter filter_value missing");
+		return -1;
+	}
+
+	pos += 13;
+	end = os_strchr(pos, ' ');
+	if (!end)
+		end = pos + os_strlen(pos);
+
+	filter_len = (end - pos) / 2;
+	param->filter_value = os_malloc(filter_len);
+	if (!param->filter_value)
+		return -1;
+
+	if (hexstr2bin(pos, param->filter_value, filter_len)) {
+		wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos);
+		goto free;
+	}
+
+	pos = os_strstr(cmd, "filter_mask=");
+	if (!pos) {
+		wpa_printf(MSG_ERROR,
+			   "Classifier parameter filter_mask missing");
+		goto free;
+	}
+
+	pos += 12;
+	end = os_strchr(pos, ' ');
+	if (!end)
+		end = pos + os_strlen(pos);
+
+	if (filter_len != (size_t) (end - pos) / 2) {
+		wpa_printf(MSG_ERROR,
+			   "Filter mask length mismatch expected=%zu received=%zu",
+			   filter_len, (size_t) (end - pos) / 2);
+		goto free;
+	}
+
+	param->filter_mask = os_malloc(filter_len);
+	if (!param->filter_mask)
+		goto free;
+
+	if (hexstr2bin(pos, param->filter_mask, filter_len)) {
+		wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos);
+		os_free(param->filter_mask);
+		param->filter_mask = NULL;
+		goto free;
+	}
+
+	param->filter_len = filter_len;
+	return 0;
+free:
+	os_free(param->filter_value);
+	param->filter_value = NULL;
+	return -1;
+}
+
+
+static int scs_parse_type4(struct tclas_element *elem, const char *pos)
+{
+	struct type4_params type4_param = { 0 };
+
+	if (set_type4_frame_classifier(pos, &type4_param) == -1) {
+		wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4");
+		return -1;
+	}
+
+	os_memcpy(&elem->frame_classifier.type4_param,
+		  &type4_param, sizeof(struct type4_params));
+	return 0;
+}
+
+
+static int scs_parse_type10(struct tclas_element *elem, const char *pos)
+{
+	struct type10_params type10_param = { 0 };
+
+	if (set_type10_frame_classifier(pos, &type10_param) == -1) {
+		wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10");
+		return -1;
+	}
+
+	os_memcpy(&elem->frame_classifier.type10_param,
+		  &type10_param, sizeof(struct type10_params));
+	return 0;
+}
+
+
+static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s,
+					 char *cmd)
+{
+	char *pos1, *pos;
+	struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req;
+	struct scs_desc_elem desc_elem = { 0 };
+	int val;
+	unsigned int num_scs_desc = 0;
+
+	if (wpa_s->ongoing_scs_req) {
+		wpa_printf(MSG_ERROR, "%s: SCS Request already in queue",
+			   __func__);
+		return -1;
+	}
+
+	/**
+	 * format:
+	 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>]
+	 * [classifier_type=<4|10>]
+	 * [classifier params based on classifier type]
+	 * [tclas_processing=<0|1>] [scs_id=<decimal number>] ...
+	 */
+	pos1 = os_strstr(cmd, "scs_id=");
+	if (!pos1) {
+		wpa_printf(MSG_ERROR, "SCSID not present");
+		return -1;
+	}
+
+	free_up_scs_desc(scs_data);
+
+	while (pos1) {
+		struct scs_desc_elem *n1;
+		struct active_scs_elem *active_scs_desc;
+		char *next_scs_desc;
+		unsigned int num_tclas_elem = 0;
+		bool scsid_active = false;
+
+		desc_elem.scs_id = atoi(pos1 + 7);
+		pos1 += 7;
+
+		next_scs_desc = os_strstr(pos1, "scs_id=");
+		if (next_scs_desc) {
+			char temp[20];
+
+			os_snprintf(temp, sizeof(temp), "scs_id=%d ",
+				    desc_elem.scs_id);
+			if (os_strstr(next_scs_desc, temp)) {
+				wpa_printf(MSG_ERROR,
+					   "Multiple SCS descriptors configured with same SCSID(=%d)",
+					   desc_elem.scs_id);
+				goto free_scs_desc;
+			}
+			pos1[next_scs_desc - pos1 - 1] = '\0';
+		}
+
+		dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids,
+				 struct active_scs_elem, list) {
+			if (desc_elem.scs_id == active_scs_desc->scs_id) {
+				scsid_active = true;
+				break;
+			}
+		}
+
+		if (os_strstr(pos1, "add ")) {
+			desc_elem.request_type = SCS_REQ_ADD;
+			if (scsid_active) {
+				wpa_printf(MSG_ERROR, "SCSID %d already active",
+					   desc_elem.scs_id);
+				return -1;
+			}
+		} else if (os_strstr(pos1, "remove")) {
+			desc_elem.request_type = SCS_REQ_REMOVE;
+			if (!scsid_active) {
+				wpa_printf(MSG_ERROR, "SCSID %d not active",
+					   desc_elem.scs_id);
+				return -1;
+			}
+			goto scs_desc_end;
+		} else if (os_strstr(pos1, "change ")) {
+			desc_elem.request_type = SCS_REQ_CHANGE;
+			if (!scsid_active) {
+				wpa_printf(MSG_ERROR, "SCSID %d not active",
+					   desc_elem.scs_id);
+				return -1;
+			}
+		} else {
+			wpa_printf(MSG_ERROR, "SCS Request type invalid");
+			goto free_scs_desc;
+		}
+
+		pos1 = os_strstr(pos1, "scs_up=");
+		if (!pos1) {
+			wpa_printf(MSG_ERROR,
+				   "Intra-Access user priority not present");
+			goto free_scs_desc;
+		}
+
+		val = atoi(pos1 + 7);
+		if (val < 0 || val > 7) {
+			wpa_printf(MSG_ERROR,
+				   "Intra-Access user priority invalid %d",
+				   val);
+			goto free_scs_desc;
+		}
+
+		desc_elem.intra_access_priority = val;
+		desc_elem.scs_up_avail = true;
+
+		pos = os_strstr(pos1, "classifier_type=");
+		if (!pos) {
+			wpa_printf(MSG_ERROR, "classifier type empty");
+			goto free_scs_desc;
+		}
+
+		while (pos) {
+			struct tclas_element elem = { 0 }, *n;
+			char *next_tclas_elem;
+
+			val = atoi(pos + 16);
+			if (val != 4 && val != 10) {
+				wpa_printf(MSG_ERROR,
+					   "classifier type invalid %d", val);
+				goto free_scs_desc;
+			}
+
+			elem.classifier_type = val;
+			pos += 16;
+
+			next_tclas_elem = os_strstr(pos, "classifier_type=");
+			if (next_tclas_elem) {
+				pos1 = next_tclas_elem;
+				pos[next_tclas_elem - pos - 1] = '\0';
+			}
+
+			switch (val) {
+			case 4:
+				if (scs_parse_type4(&elem, pos) < 0)
+					goto free_scs_desc;
+				break;
+			case 10:
+				if (scs_parse_type10(&elem, pos) < 0)
+					goto free_scs_desc;
+				break;
+			}
+
+			n = os_realloc(desc_elem.tclas_elems,
+				       (num_tclas_elem + 1) * sizeof(elem));
+			if (!n)
+				goto free_scs_desc;
+
+			desc_elem.tclas_elems = n;
+			os_memcpy((u8 *) desc_elem.tclas_elems +
+				  num_tclas_elem * sizeof(elem),
+				  &elem, sizeof(elem));
+			num_tclas_elem++;
+			desc_elem.num_tclas_elem = num_tclas_elem;
+			pos = next_tclas_elem;
+		}
+
+		if (desc_elem.num_tclas_elem > 1) {
+			pos1 = os_strstr(pos1, "tclas_processing=");
+			if (!pos1) {
+				wpa_printf(MSG_ERROR, "tclas_processing empty");
+				goto free_scs_desc;
+			}
+
+			val = atoi(pos1 + 17);
+			if (val != 0 && val != 1) {
+				wpa_printf(MSG_ERROR,
+					   "tclas_processing invalid");
+				goto free_scs_desc;
+			}
+
+			desc_elem.tclas_processing = val;
+		}
+
+scs_desc_end:
+		n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) *
+				sizeof(struct scs_desc_elem));
+		if (!n1)
+			goto free_scs_desc;
+
+		scs_data->scs_desc_elems = n1;
+		os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc *
+			  sizeof(desc_elem), &desc_elem, sizeof(desc_elem));
+		num_scs_desc++;
+		scs_data->num_scs_desc = num_scs_desc;
+		pos1 = next_scs_desc;
+		os_memset(&desc_elem, 0, sizeof(desc_elem));
+	}
+
+	return wpas_send_scs_req(wpa_s);
+
+free_scs_desc:
+	free_up_tclas_elem(&desc_elem);
+	free_up_scs_desc(scs_data);
+	return -1;
+}
+
+
+static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s,
+					  const char *cmd)
+{
+	char *pos;
+	struct dscp_policy_status *policy = NULL, *n;
+	int num_policies = 0, ret = -1;
+	struct dscp_resp_data resp_data;
+
+	/*
+	 * format:
+	 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
+	 */
+
+	os_memset(&resp_data, 0, sizeof(resp_data));
+
+	resp_data.more = os_strstr(cmd, "more") != NULL;
+
+	if (os_strstr(cmd, "reset")) {
+		resp_data.reset = true;
+		resp_data.solicited = false;
+		goto send_resp;
+	}
+
+	resp_data.solicited = os_strstr(cmd, "solicited") != NULL;
+
+	pos = os_strstr(cmd, "policy_id=");
+	while (pos) {
+		n = os_realloc(policy, (num_policies + 1) * sizeof(*policy));
+		if (!n)
+			goto fail;
+
+		policy = n;
+		pos += 10;
+		policy[num_policies].id = atoi(pos);
+		if (policy[num_policies].id == 0) {
+			wpa_printf(MSG_ERROR, "DSCP: Invalid policy id");
+			goto fail;
+		}
+
+		pos = os_strstr(pos, "status=");
+		if (!pos) {
+			wpa_printf(MSG_ERROR,
+				   "DSCP: Status is not found for a policy");
+			goto fail;
+		}
+
+		pos += 7;
+		policy[num_policies].status = atoi(pos);
+		num_policies++;
+
+		pos = os_strstr(pos, "policy_id");
+	}
+
+	resp_data.policy = policy;
+	resp_data.num_policies = num_policies;
+send_resp:
+	ret = wpas_send_dscp_response(wpa_s, &resp_data);
+	if (ret)
+		wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response");
+fail:
+	os_free(policy);
+	return ret;
+}
+
+
+static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
+					   const char *cmd)
+{
+	char *pos;
+
+	/*
+	 * format:
+	 * Wildcard DSCP query
+	 * <wildcard>
+	 *
+	 * DSCP query with a domain name attribute:
+	 * [domain_name=<string>]
+	 */
+
+	if (os_strstr(cmd, "wildcard")) {
+		wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
+		return wpas_send_dscp_query(wpa_s, NULL, 0);
+	}
+
+	pos = os_strstr(cmd, "domain_name=");
+	if (!pos || !os_strlen(pos + 12)) {
+		wpa_printf(MSG_ERROR, "QM: Domain name not preset");
+		return -1;
+	}
+
+	return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
+}
+
+
 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 					 char *buf, size_t *resp_len)
 {
@@ -11124,6 +12016,9 @@
 	} else if (os_strcmp(buf, "STOP_AP") == 0) {
 		if (wpas_ap_stop_ap(wpa_s))
 			reply_len = -1;
+	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
+		if (wpas_ap_update_beacon(wpa_s))
+			reply_len = -1;
 #endif /* CONFIG_AP */
 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
 		wpas_notify_suspend(wpa_s->global);
@@ -11239,6 +12134,9 @@
 	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
 		if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0)
 			reply_len = -1;
+	} else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) {
+		if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0)
+			reply_len = -1;
 	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
 		if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0)
 			reply_len = -1;
@@ -11277,6 +12175,18 @@
 		sme_event_unprot_disconnect(
 			wpa_s, wpa_s->bssid, NULL,
 			WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
+	} else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) {
+		if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "TWT_SETUP") == 0) {
+		if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
+		if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) {
+		if (wpas_ctrl_iface_send_twt_teardown(wpa_s, ""))
+			reply_len = -1;
 #endif /* CONFIG_TESTING_OPTIONS */
 	} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
 		if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
@@ -11426,6 +12336,9 @@
 	} else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) {
 		if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0)
 			reply_len = -1;
+	} else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) {
+		if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0)
+			reply_len = -1;
 #ifdef CONFIG_DPP2
 	} else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) {
 		if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0)
@@ -11459,7 +12372,19 @@
 		wpas_pasn_auth_stop(wpa_s);
 	} else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
 		reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
+	} else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
+		if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
+			reply_len = -1;
 #endif /* CONFIG_PASN */
+	} else if (os_strncmp(buf, "SCS ", 4) == 0) {
+		if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
+		if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
+		if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
+			reply_len = -1;
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h
index a408288..dfbd25a 100644
--- a/wpa_supplicant/ctrl_iface.h
+++ b/wpa_supplicant/ctrl_iface.h
@@ -131,7 +131,8 @@
 }
 
 static inline void
-wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
+wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
+				 struct ctrl_iface_priv *priv)
 {
 }
 
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 2c01943..9279ae4 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -937,6 +937,95 @@
 #endif /* CONFIG_MESH */
 
 
+#ifdef CONFIG_INTERWORKING
+
+void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
+					    struct wpa_bss *bss,
+					    struct wpa_cred *cred,
+					    const char *type,
+					    int excluded,
+					    int bh,
+					    int bss_load,
+					    int conn_capab)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+	DBusMessageIter iter, dict_iter;
+	char bss_path[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path;
+	char cred_path[WPAS_DBUS_OBJECT_PATH_MAX], *cred_obj_path;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (!iface || !wpa_s->dbus_new_path)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE,
+				      "InterworkingAPAdded");
+	if (!msg)
+		return;
+
+	os_snprintf(bss_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+		    wpa_s->dbus_new_path, bss->id);
+	bss_obj_path = bss_path;
+
+	os_snprintf(cred_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%u",
+		    wpa_s->dbus_new_path, cred->id);
+	cred_obj_path = cred_path;
+
+	dbus_message_iter_init_append(msg, &iter);
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+					    &bss_obj_path) ||
+	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+					    &cred_obj_path) ||
+	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+	    !wpa_dbus_dict_append_string(&dict_iter, "type", type) ||
+	    !wpa_dbus_dict_append_int32(&dict_iter, "excluded", excluded) ||
+	    !wpa_dbus_dict_append_int32(&dict_iter, "priority",
+					cred->priority) ||
+	    !wpa_dbus_dict_append_int32(&dict_iter, "sp_priority",
+					cred->sp_priority) ||
+	    !wpa_dbus_dict_append_int32(&dict_iter, "below_min_backhaul", bh) ||
+	    !wpa_dbus_dict_append_int32(&dict_iter, "over_max_bss_load",
+					bss_load) ||
+	    !wpa_dbus_dict_append_int32(&dict_iter, "conn_capab_missing",
+					conn_capab) ||
+	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	else
+		dbus_connection_send(iface->con, msg, NULL);
+	dbus_message_unref(msg);
+}
+
+
+void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (!iface || !wpa_s->dbus_new_path)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE,
+				      "InterworkingSelectDone");
+	if (!msg)
+		return;
+
+	dbus_connection_send(iface->con, msg, NULL);
+
+	dbus_message_unref(msg);
+}
+
+#endif /* CONFIG_INTERWORKING */
+
+
 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
 				    int depth, const char *subject,
 				    const char *altsubject[],
@@ -3570,6 +3659,35 @@
 		  END_ARGS
 	  }
 	},
+#ifdef CONFIG_INTERWORKING
+	{ "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) wpas_dbus_handler_add_cred,
+	  {
+		  { "args", "a{sv}", ARG_IN },
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) wpas_dbus_handler_remove_cred,
+	  {
+		  { "path", "o", ARG_IN },
+		  END_ARGS
+	  }
+	},
+	{ "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds,
+	  {
+		  END_ARGS
+	  }
+	},
+	{ "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) wpas_dbus_handler_interworking_select,
+	  {
+		  END_ARGS
+	  }
+	},
+#endif /* CONFIG_INTERWORKING */
 	{ NULL, NULL, NULL, { END_ARGS } }
 };
 
@@ -4137,6 +4255,21 @@
 	  }
 	},
 #endif /* CONFIG_MESH */
+#ifdef CONFIG_INTERWORKING
+	{ "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "bss", "o", ARG_OUT },
+		  { "cred", "o", ARG_OUT },
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  END_ARGS
+	  }
+	},
+#endif /* CONFIG_INTERWORKING */
 	{ NULL, NULL, { END_ARGS } }
 };
 
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 42db389..26bdcb5 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -16,6 +16,8 @@
 struct wpa_global;
 struct wpa_supplicant;
 struct wpa_ssid;
+struct wpa_cred;
+struct wpa_bss;
 struct wps_event_m2d;
 struct wps_event_fail;
 struct wps_credential;
@@ -96,6 +98,9 @@
 #define WPAS_DBUS_NEW_P2P_PEERS_PART	"Peers"
 #define	WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
 
+#define WPAS_DBUS_NEW_CREDENTIALS_PART "Credentials"
+#define WPAS_DBUS_NEW_IFACE_CREDENTIAL WPAS_DBUS_NEW_INTERFACE ".Credential"
+
 /* Top-level Errors */
 #define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
 	WPAS_DBUS_NEW_INTERFACE ".UnknownError"
@@ -264,6 +269,13 @@
 					  const u8 *peer_addr);
 void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
 					     const u8 *peer_addr, int reason);
+void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
+					    struct wpa_bss *bss,
+					    struct wpa_cred *cred,
+					    const char *type, int excluded,
+					    int bh, int bss_load,
+					    int conn_capab);
+void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s);
 
 #else /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
@@ -616,6 +628,21 @@
 {
 }
 
+static inline
+void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
+					    struct wpa_bss *bss,
+					    struct wpa_cred *cred,
+					    const char *type, int excluded,
+					    int bh, int bss_load,
+					    int conn_capab)
+{
+}
+
+static inline
+void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
+{
+}
+
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
 #endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 7d20f21..959a68b 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -26,6 +26,7 @@
 #include "../scan.h"
 #include "../autoscan.h"
 #include "../ap.h"
+#include "../interworking.h"
 #include "dbus_new_helpers.h"
 #include "dbus_new.h"
 #include "dbus_new_handlers.h"
@@ -148,6 +149,9 @@
 #ifdef CONFIG_P2P
 	"go_p2p_dev_addr", "p2p_client_list", "psk_list",
 #endif /* CONFIG_P2P */
+#ifdef CONFIG_INTERWORKING
+	"roaming_consortium", "required_roaming_consortium",
+#endif /* CONFIG_INTERWORKING */
 	NULL
 };
 
@@ -329,6 +333,110 @@
 
 
 /**
+ * set_cred_properties - Set the properties of a configured credential
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @cred: wpa_cred structure for a configured credential
+ * @iter: DBus message iterator containing dictionary of network
+ * properties to set.
+ * @error: On failure, an error describing the failure
+ * Returns: TRUE if the request succeeds, FALSE if it failed
+ */
+static dbus_bool_t set_cred_properties(struct wpa_supplicant *wpa_s,
+				       struct wpa_cred *cred,
+				       DBusMessageIter *iter,
+				       DBusError *error)
+{
+	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
+	DBusMessageIter	iter_dict;
+	char *value = NULL;
+
+	if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
+		return FALSE;
+
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		size_t size = 50;
+		int ret;
+
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+			goto error;
+
+		value = NULL;
+		if (entry.type == DBUS_TYPE_ARRAY &&
+		    entry.array_type == DBUS_TYPE_BYTE) {
+			if (entry.array_len <= 0)
+				goto error;
+
+			size = entry.array_len * 2 + 1;
+			value = os_zalloc(size);
+			if (!value)
+				goto error;
+
+			ret = wpa_snprintf_hex(value, size,
+					       (u8 *) entry.bytearray_value,
+					       entry.array_len);
+			if (ret <= 0)
+				goto error;
+		} else if (entry.type == DBUS_TYPE_STRING) {
+			if (should_quote_opt(entry.key)) {
+				size = os_strlen(entry.str_value);
+
+				size += 3;
+				value = os_zalloc(size);
+				if (!value)
+					goto error;
+
+				ret = os_snprintf(value, size, "\"%s\"",
+						  entry.str_value);
+				if (os_snprintf_error(size, ret))
+					goto error;
+			} else {
+				value = os_strdup(entry.str_value);
+				if (!value)
+					goto error;
+			}
+		} else if (entry.type == DBUS_TYPE_UINT32) {
+			value = os_zalloc(size);
+			if (!value)
+				goto error;
+
+			ret = os_snprintf(value, size, "%u",
+					  entry.uint32_value);
+			if (os_snprintf_error(size, ret))
+				goto error;
+		} else if (entry.type == DBUS_TYPE_INT32) {
+			value = os_zalloc(size);
+			if (!value)
+				goto error;
+
+			ret = os_snprintf(value, size, "%d",
+					  entry.int32_value);
+			if (os_snprintf_error(size, ret))
+				goto error;
+		} else {
+			goto error;
+		}
+
+		ret = wpa_config_set_cred(cred, entry.key, value, 0);
+		if (ret < 0)
+			goto error;
+
+		os_free(value);
+		value = NULL;
+		wpa_dbus_dict_entry_clear(&entry);
+	}
+
+	return TRUE;
+
+error:
+	os_free(value);
+	wpa_dbus_dict_entry_clear(&entry);
+	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
+			     "invalid message format");
+	return FALSE;
+}
+
+
+/**
  * wpas_dbus_simple_property_getter - Get basic type property
  * @iter: Message iter to use when appending arguments
  * @type: DBus type of property (must be basic type)
@@ -1516,6 +1624,187 @@
 
 
 /**
+ * wpas_dbus_new_iface_add_cred - Add a new credential
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing the object path of the new credential
+ *
+ * Handler function for "AddCred" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter	iter;
+	struct wpa_cred *cred = NULL;
+	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
+	DBusError error;
+
+	dbus_message_iter_init(message, &iter);
+
+	if (wpa_s->dbus_new_path)
+		cred = wpa_config_add_cred(wpa_s->conf);
+	if (!cred) {
+		wpa_printf(MSG_ERROR, "%s[dbus]: can't add new credential.",
+			   __func__);
+		reply = wpas_dbus_error_unknown_error(
+			message,
+			"wpa_supplicant could not add a credential on this interface.");
+		goto err;
+	}
+
+	dbus_error_init(&error);
+	if (!set_cred_properties(wpa_s, cred, &iter, &error)) {
+		wpa_printf(MSG_DEBUG,
+			   "%s[dbus]: control interface couldn't set credential properties",
+			   __func__);
+		reply = wpas_dbus_reply_new_from_error(message, &error,
+						       DBUS_ERROR_INVALID_ARGS,
+						       "Failed to add credential");
+		dbus_error_free(&error);
+		goto err;
+	}
+
+	/* Construct the object path for this network. */
+	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%d",
+		    wpa_s->dbus_new_path, cred->id);
+
+	reply = dbus_message_new_method_return(message);
+	if (!reply) {
+		reply = wpas_dbus_error_no_memory(message);
+		goto err;
+	}
+	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
+				      DBUS_TYPE_INVALID)) {
+		dbus_message_unref(reply);
+		reply = wpas_dbus_error_no_memory(message);
+		goto err;
+	}
+
+	return reply;
+
+err:
+	if (cred)
+		wpa_config_remove_cred(wpa_s->conf, cred->id);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_handler_remove_cred - Remove a configured credential
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL on success or dbus error on failure
+ *
+ * Handler function for "RemoveCred" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *op;
+	char *iface, *cred_id;
+	int id;
+	struct wpa_cred *cred;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
+			      DBUS_TYPE_INVALID);
+
+	/* Extract the network ID and ensure the network is actually a child of
+	 * this interface */
+	iface = wpas_dbus_new_decompose_object_path(
+		op, WPAS_DBUS_NEW_CREDENTIALS_PART, &cred_id);
+	if (!iface || !cred_id || !wpa_s->dbus_new_path ||
+	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
+		reply = wpas_dbus_error_invalid_args(message, op);
+		goto out;
+	}
+
+	errno = 0;
+	id = strtoul(cred_id, NULL, 10);
+	if (errno != 0) {
+		reply = wpas_dbus_error_invalid_args(message, op);
+		goto out;
+	}
+
+	cred = wpa_config_get_cred(wpa_s->conf, id);
+	if (!cred) {
+		wpa_printf(MSG_ERROR, "%s[dbus]: could not find credential %s",
+			   __func__, op);
+		reply = wpas_dbus_error_invalid_args(
+			message, "could not find credential");
+		goto out;
+	}
+
+	if (wpas_remove_cred(wpa_s, cred) < 0) {
+		wpa_printf(MSG_ERROR,
+			   "%s[dbus]: error occurred when removing cred %d",
+			   __func__, id);
+		reply = wpas_dbus_error_unknown_error(
+			message,
+			"error removing the specified credential on its interface.");
+		goto out;
+	}
+
+out:
+	os_free(iface);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_handler_remove_all_creds - Remove all the configured credentials
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL indicating success or DBus error message on failure
+ *
+ * Handler function for "RemoveAllCreds" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
+						 struct wpa_supplicant *wpa_s)
+{
+	int res;
+	DBusMessage *reply = NULL;
+
+	res = wpas_remove_all_creds(wpa_s);
+	if (res < 0) {
+		wpa_printf(MSG_ERROR,
+			   "%s[dbus]: failed to remove all credentials",
+			   __func__);
+		reply = wpas_dbus_error_unknown_error(
+			message, "failed to remove all credentials");
+	}
+
+	return reply;
+}
+
+
+#ifdef CONFIG_INTERWORKING
+DBusMessage *
+wpas_dbus_handler_interworking_select(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s)
+{
+	int result;
+	DBusMessage *reply = NULL;
+
+	/* Automatic selection is disabled and no constraint on channels */
+	result = interworking_select(wpa_s, 0, NULL);
+	if (result < 0) {
+		wpa_printf(MSG_ERROR,
+			   "%s[dbus]: failed to start Interworking selection",
+			   __func__);
+		reply = wpas_dbus_error_scan_error(
+			message,
+			"error starting Interworking selection.");
+	}
+
+	return reply;
+}
+#endif /* CONFIG_INTERWORKING */
+
+
+/**
  * wpas_dbus_handler_signal_poll - Request immediate signal properties
  * @message: Pointer to incoming dbus message
  * @wpa_s: wpa_supplicant structure for a network interface
@@ -1979,6 +2268,7 @@
 	struct wpa_bss *bss;
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
 	char *addr;
+	struct wpa_radio_work *already_connecting;
 
 	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &addr,
 				   DBUS_TYPE_INVALID))
@@ -2002,9 +2292,18 @@
 			message, "Target BSS not found");
 	}
 
+	already_connecting = radio_work_pending(wpa_s, "sme-connect");
 	wpa_s->reassociate = 1;
 	wpa_supplicant_connect(wpa_s, bss, ssid);
 
+	/*
+	 * Indicate that an explicitly requested roam is in progress so scan
+	 * results that come in before the 'sme-connect' radio work gets
+	 * executed do not override the original connection attempt.
+	 */
+	if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
+		wpa_s->roam_in_progress = true;
+
 	return NULL;
 #endif /* CONFIG_NO_SCAN_PROCESSING */
 }
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index c36383f..a421083 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -144,6 +144,19 @@
 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
 					  struct wpa_supplicant *wpa_s);
 
+DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
+						 struct wpa_supplicant *wpa_s);
+
+DBusMessage *
+wpas_dbus_handler_interworking_select(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s);
+
 DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
 DECLARE_ACCESSOR(wpas_dbus_getter_state);
 DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 7a65673..de79178 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -175,7 +175,7 @@
 	}
 
 	if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
-			  req_dev_types, NULL, 0, 0, NULL, freq))
+			  req_dev_types, NULL, 0, 0, NULL, freq, false))
 		reply = wpas_dbus_error_unknown_error(
 			message, "Could not start P2P find");
 
@@ -425,14 +425,15 @@
 			goto inv_args;
 
 		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
-						  0, 0, 0, 0, NULL, 0, 0)) {
+						  0, 0, 0, 0, NULL, 0, 0,
+						  false)) {
 			reply = wpas_dbus_error_unknown_error(
 				message,
 				"Failed to reinvoke a persistent group");
 			goto out;
 		}
 	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
-				      0, 0, 0))
+				      0, 0, 0, false))
 		goto inv_args;
 
 out:
@@ -653,7 +654,7 @@
 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
 				   persistent_group, 0, join, authorize_only,
 				   go_intent, freq, 0, -1, 0, 0, 0, 0, 0, 0,
-				   NULL, 0);
+				   NULL, 0, false);
 
 	if (new_pin >= 0) {
 		char npin[9];
@@ -743,6 +744,7 @@
 	unsigned int group_id = 0;
 	int persistent = 0;
 	struct wpa_ssid *ssid;
+	const char *group_ifname;
 
 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
 		return reply;
@@ -776,6 +778,8 @@
 	    !p2p_peer_known(wpa_s->global->p2p, peer_addr))
 		goto err;
 
+	/* Capture the interface name for the group first */
+	group_ifname = wpa_s->ifname;
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (persistent) {
@@ -810,7 +814,7 @@
 			goto err;
 
 		if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
-				    0, 0, 0) < 0) {
+				    0, 0, 0, false) < 0) {
 			reply = wpas_dbus_error_unknown_error(
 				message,
 				"Failed to reinvoke a persistent group");
@@ -820,8 +824,8 @@
 		/*
 		 * No group ID means propose to a peer to join my active group
 		 */
-		if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
-					  peer_addr, NULL)) {
+		if (wpas_p2p_invite_group(wpa_s, group_ifname,
+					  peer_addr, NULL, false)) {
 			reply = wpas_dbus_error_unknown_error(
 				message, "Failed to join to an active group");
 			goto out;
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index a6cd933..6208e9e 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -603,8 +603,13 @@
 # Experimental implementation of draft-harkins-owe-07.txt
 #CONFIG_OWE=y
 
-# Device Provisioning Protocol (DPP)
+# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
 CONFIG_DPP=y
+# DPP version 2 support
+CONFIG_DPP2=y
+# DPP version 3 support (experimental and still changing; do not enable for
+# production use)
+#CONFIG_DPP3=y
 
 # WLAN Authentication and Privacy Infrastructure (WAPI): interface only.
 # Configure the building of the interface which allows WAPI configuration.
diff --git a/wpa_supplicant/doc/docbook/eapol_test.sgml b/wpa_supplicant/doc/docbook/eapol_test.sgml
index 4cfa3c1..b9b0a95 100644
--- a/wpa_supplicant/doc/docbook/eapol_test.sgml
+++ b/wpa_supplicant/doc/docbook/eapol_test.sgml
@@ -198,7 +198,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2019,
+    <para>wpa_supplicant is copyright (c) 2003-2022,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_background.sgml b/wpa_supplicant/doc/docbook/wpa_background.sgml
index 22241cc..b0592e2 100644
--- a/wpa_supplicant/doc/docbook/wpa_background.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -94,7 +94,7 @@
 
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2019,
+    <para>wpa_supplicant is copyright (c) 2003-2022,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_cli.sgml b/wpa_supplicant/doc/docbook/wpa_cli.sgml
index 2ba1fe4..b3d95ee 100644
--- a/wpa_supplicant/doc/docbook/wpa_cli.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -349,7 +349,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2019,
+    <para>wpa_supplicant is copyright (c) 2003-2022,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index cb0c735..c391645 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -95,7 +95,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2019,
+    <para>wpa_supplicant is copyright (c) 2003-2022,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
index 0772969..5934e79 100644
--- a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -66,7 +66,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2019,
+    <para>wpa_supplicant is copyright (c) 2003-2022,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_priv.sgml b/wpa_supplicant/doc/docbook/wpa_priv.sgml
index 0d5c94a..4053eda 100644
--- a/wpa_supplicant/doc/docbook/wpa_priv.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_priv.sgml
@@ -141,7 +141,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2019,
+    <para>wpa_supplicant is copyright (c) 2003-2022,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
index 144654a..02012d1 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -46,7 +46,7 @@
     can be used to improve the network security, but even that has inherited
     security issues due to the use of WEP for encryption. Wi-Fi Protected
     Access and IEEE 802.11i amendment to the wireless LAN standard introduce
-    a much improvement mechanism for securing wireless networks. IEEE 802.11i
+    a much improved mechanism for securing wireless networks. IEEE 802.11i
     enabled networks that are using CCMP (encryption mechanism based on strong
     cryptographic algorithm AES) can finally be called secure used for
     applications which require efficient protection against unauthorized
@@ -753,7 +753,7 @@
   </refsect1>
   <refsect1>
     <title>Legal</title>
-    <para>wpa_supplicant is copyright (c) 2003-2019,
+    <para>wpa_supplicant is copyright (c) 2003-2022,
     Jouni Malinen <email>j@w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index d935215..d570cfe 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -2,6 +2,7 @@
  * wpa_supplicant - DPP
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -27,7 +28,7 @@
 #include "scan.h"
 #include "notify.h"
 #include "dpp_supplicant.h"
-#include "hidl.h"
+#include "aidl.h"
 
 
 static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
@@ -48,12 +49,14 @@
 			const u8 *src, const u8 *bssid,
 			const u8 *data, size_t data_len,
 			enum offchannel_send_action_result result);
+static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx);
 #ifdef CONFIG_DPP2
 static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
 						 void *timeout_ctx);
 static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s);
 static int wpas_dpp_process_conf_obj(void *ctx,
 				     struct dpp_authentication *auth);
+static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth);
 #endif /* CONFIG_DPP2 */
 
 static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -296,7 +299,8 @@
 	struct dpp_authentication *auth = wpa_s->dpp_auth;
 	enum dpp_status_error result;
 
-	if (!auth || !auth->conn_status_requested)
+	if ((!auth || !auth->conn_status_requested) &&
+	    !dpp_tcp_conn_status_requested(wpa_s->dpp))
 		return;
 
 	wpa_printf(MSG_DEBUG,
@@ -372,9 +376,10 @@
 
 	eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
 
-	if (!auth || !auth->conn_status_requested)
+	if ((!auth || !auth->conn_status_requested) &&
+	    !dpp_tcp_conn_status_requested(wpa_s->dpp))
 		return;
-	auth->conn_status_requested = 0;
+
 	wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
 		   result);
 
@@ -383,6 +388,19 @@
 		channel_list = channel_list_buf;
 	}
 
+	if (!auth || !auth->conn_status_requested) {
+		dpp_tcp_send_conn_status(wpa_s->dpp, result,
+					 ssid ? ssid->ssid :
+					 wpa_s->dpp_last_ssid,
+					 ssid ? ssid->ssid_len :
+					 wpa_s->dpp_last_ssid_len,
+					 channel_list);
+		os_free(channel_list_buf);
+		return;
+	}
+
+	auth->conn_status_requested = 0;
+
 	msg = dpp_build_conn_status_result(auth, result,
 					   ssid ? ssid->ssid :
 					   wpa_s->dpp_last_ssid,
@@ -417,7 +435,8 @@
 {
 	struct dpp_authentication *auth = wpa_s->dpp_auth;
 
-	if (auth && auth->conn_status_requested)
+	if ((auth && auth->conn_status_requested) ||
+	    dpp_tcp_conn_status_requested(wpa_s->dpp))
 		wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
 }
 
@@ -762,6 +781,7 @@
 #endif /* CONFIG_DPP2 */
 
 	wpa_s->dpp_gas_client = 0;
+	wpa_s->dpp_gas_server = 0;
 
 	pos = os_strstr(cmd, " peer=");
 	if (!pos)
@@ -877,7 +897,8 @@
 	if (tcp)
 		return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
 				    wpa_s->conf->dpp_name, DPP_NETROLE_STA,
-				    wpa_s, wpa_s, wpas_dpp_process_conf_obj);
+				    wpa_s, wpa_s, wpas_dpp_process_conf_obj,
+				    wpas_dpp_tcp_msg_sent);
 #endif /* CONFIG_DPP2 */
 
 	wpa_s->dpp_auth = auth;
@@ -1024,6 +1045,7 @@
 	wpa_drv_dpp_listen(wpa_s, false);
 	wpa_s->dpp_listen_freq = 0;
 	wpas_dpp_listen_work_done(wpa_s);
+	radio_remove_works(wpa_s, "dpp-listen", 0);
 }
 
 
@@ -1127,6 +1149,7 @@
 	}
 
 	wpa_s->dpp_gas_client = 0;
+	wpa_s->dpp_gas_server = 0;
 	wpa_s->dpp_auth_ok_on_ack = 0;
 	wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
 					  wpa_s->dpp_allowed_roles,
@@ -1164,9 +1187,33 @@
 }
 
 
+void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
+{
+	struct dpp_authentication *auth = wpa_s->dpp_auth;
+	int freq;
+
+	if (!wpa_s->dpp_gas_server || !auth)
+		return;
+
+	freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
+	if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
+		return; /* listen state is already in progress */
+
+	wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
+	wpa_s->dpp_in_response_listen = 1;
+	wpas_dpp_listen_start(wpa_s, freq);
+}
+
+
 static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
 {
-	/* TODO: stop wait and start ROC */
+	struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
+		   auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
+		   !!wpa_s->dpp_listen_work);
+	wpa_s->dpp_gas_server = 1;
 }
 
 
@@ -1626,6 +1673,7 @@
 	enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
 	unsigned int i;
 
+	eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
 	wpa_s->dpp_gas_dialog_token = -1;
 
 	if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
@@ -1729,6 +1777,22 @@
 }
 
 
+static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+	if (!wpa_s->dpp_gas_client || !auth ||
+	    (!auth->auth_success && !auth->reconfig_success))
+		return;
+
+	wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
+	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
+	dpp_auth_deinit(wpa_s->dpp_auth);
+	wpa_s->dpp_auth = NULL;
+}
+
+
 static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
 {
 	struct dpp_authentication *auth = wpa_s->dpp_auth;
@@ -1755,6 +1819,16 @@
 	wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
 		   MAC2STR(auth->peer_mac_addr), auth->curr_freq);
 
+	/* Use a 120 second timeout since the gas_query_req() operation could
+	 * remain waiting indefinitely for the response if the Configurator
+	 * keeps sending out comeback responses with additional delay. The
+	 * DPP technical specification expects the Enrollee to continue sending
+	 * out new Config Requests for 60 seconds, so this gives an extra 60
+	 * second time after the last expected new Config Request for the
+	 * Configurator to determine what kind of configuration to provide. */
+	eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
+			       wpa_s, NULL);
+
 	res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
 			    1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
 	if (res < 0) {
@@ -1958,6 +2032,8 @@
 	status = dpp_conf_result_rx(auth, hdr, buf, len);
 
 	if (status == DPP_STATUS_OK && auth->send_conn_status) {
+		int freq;
+
 		wpa_msg(wpa_s, MSG_INFO,
 			DPP_EVENT_CONF_SENT "wait_conn_status=1");
 		wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
@@ -1971,8 +2047,10 @@
 				       wpas_dpp_conn_status_result_wait_timeout,
 				       wpa_s, NULL);
 		offchannel_send_action_done(wpa_s);
-		wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
-				      auth->curr_freq);
+		freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
+		if (!wpa_s->dpp_in_response_listen ||
+		    (int) wpa_s->dpp_listen_freq != freq)
+			wpas_dpp_listen_start(wpa_s, freq);
 		return;
 	}
 	offchannel_send_action_done(wpa_s);
@@ -2047,6 +2125,34 @@
 }
 
 
+static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
+
+	if (auth->connect_on_tx_status) {
+		auth->connect_on_tx_status = 0;
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Try to connect after completed configuration result");
+		wpas_dpp_try_to_connect(wpa_s);
+		if (auth->conn_status_requested) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: Start 15 second timeout for reporting connection status result");
+			eloop_cancel_timeout(
+				wpas_dpp_conn_status_result_timeout,
+				wpa_s, NULL);
+			eloop_register_timeout(
+				15, 0, wpas_dpp_conn_status_result_timeout,
+				wpa_s, NULL);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+
 static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
 {
 	struct wpa_supplicant *wpa_s = ctx;
@@ -2482,6 +2588,16 @@
 			       &version_len);
 	if (version && version_len >= 1)
 		peer_version = version[0];
+#ifdef CONFIG_DPP3
+	if (intro.peer_version && intro.peer_version >= 2 &&
+	    peer_version != intro.peer_version) {
+		wpa_printf(MSG_INFO,
+			   "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
+			   intro.peer_version, peer_version);
+		wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
+		goto fail;
+	}
+#endif /* CONFIG_DPP3 */
 	entry->dpp_pfs = peer_version >= 2;
 #endif /* CONFIG_DPP2 */
 	if (expiry) {
@@ -2566,6 +2682,131 @@
 }
 
 
+#ifdef CONFIG_DPP2
+static int wpas_dpp_pkex_done(void *ctx, void *conn,
+			      struct dpp_bootstrap_info *peer_bi)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	const char *cmd = wpa_s->dpp_pkex_auth_cmd;
+	const char *pos;
+	u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
+	struct dpp_bootstrap_info *own_bi = NULL;
+	struct dpp_authentication *auth;
+
+	if (!cmd)
+		cmd = "";
+	wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
+		   cmd);
+
+	pos = os_strstr(cmd, " own=");
+	if (pos) {
+		pos += 5;
+		own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
+		if (!own_bi) {
+			wpa_printf(MSG_INFO,
+				   "DPP: Could not find bootstrapping info for the identified local entry");
+			return -1;
+		}
+
+		if (peer_bi->curve != own_bi->curve) {
+			wpa_printf(MSG_INFO,
+				   "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
+				   peer_bi->curve->name, own_bi->curve->name);
+			return -1;
+		}
+	}
+
+	pos = os_strstr(cmd, " role=");
+	if (pos) {
+		pos += 6;
+		if (os_strncmp(pos, "configurator", 12) == 0)
+			allowed_roles = DPP_CAPAB_CONFIGURATOR;
+		else if (os_strncmp(pos, "enrollee", 8) == 0)
+			allowed_roles = DPP_CAPAB_ENROLLEE;
+		else if (os_strncmp(pos, "either", 6) == 0)
+			allowed_roles = DPP_CAPAB_CONFIGURATOR |
+				DPP_CAPAB_ENROLLEE;
+		else
+			return -1;
+	}
+
+	auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
+			     0, wpa_s->hw.modes, wpa_s->hw.num_modes);
+	if (!auth)
+		return -1;
+
+	wpas_dpp_set_testing_options(wpa_s, auth);
+	if (dpp_set_configurator(auth, cmd) < 0) {
+		dpp_auth_deinit(auth);
+		return -1;
+	}
+
+	return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
+			    DPP_NETROLE_STA, wpas_dpp_process_conf_obj,
+			    wpas_dpp_tcp_msg_sent);
+}
+#endif /* CONFIG_DPP2 */
+
+
+enum wpas_dpp_pkex_ver {
+	PKEX_VER_AUTO,
+	PKEX_VER_ONLY_1,
+	PKEX_VER_ONLY_2,
+};
+
+static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
+			      enum wpas_dpp_pkex_ver ver,
+			      const struct hostapd_ip_addr *ipaddr,
+			      int tcp_port)
+{
+	struct dpp_pkex *pkex;
+	struct wpabuf *msg;
+	unsigned int wait_time;
+	bool v2 = ver != PKEX_VER_ONLY_1;
+
+	wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
+	dpp_pkex_free(wpa_s->dpp_pkex);
+	wpa_s->dpp_pkex = NULL;
+	pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
+			     wpa_s->dpp_pkex_identifier,
+			     wpa_s->dpp_pkex_code, v2);
+	if (!pkex)
+		return -1;
+	pkex->forced_ver = ver != PKEX_VER_AUTO;
+
+	if (ipaddr) {
+#ifdef CONFIG_DPP2
+		return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
+					 wpa_s, wpa_s, wpas_dpp_pkex_done);
+#else /* CONFIG_DPP2 */
+		return -1;
+#endif /* CONFIG_DPP2 */
+	}
+
+	wpa_s->dpp_pkex = pkex;
+	msg = pkex->exchange_req;
+	wait_time = wpa_s->max_remain_on_chan;
+	if (wait_time > 2000)
+		wait_time = 2000;
+	pkex->freq = 2437;
+	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
+		" freq=%u type=%d",
+		MAC2STR(broadcast), pkex->freq,
+		v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
+		DPP_PA_PKEX_V1_EXCHANGE_REQ);
+	offchannel_send_action(wpa_s, pkex->freq, broadcast,
+			       wpa_s->own_addr, broadcast,
+			       wpabuf_head(msg), wpabuf_len(msg),
+			       wait_time, wpas_dpp_tx_pkex_status, 0);
+	if (wait_time == 0)
+		wait_time = 2000;
+	pkex->exch_req_wait_time = wait_time;
+	pkex->exch_req_tries = 1;
+
+	return 0;
+}
+
+
 static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -2575,6 +2816,15 @@
 		return;
 	if (pkex->exch_req_tries >= 5) {
 		if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
+#ifdef CONFIG_DPP3
+			if (pkex->v2 && !pkex->forced_ver) {
+				wpa_printf(MSG_DEBUG,
+					   "DPP: Fall back to PKEXv1");
+				wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
+						   NULL, 0);
+				return;
+			}
+#endif /* CONFIG_DPP3 */
 			wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
 				"No response from PKEX peer");
 			dpp_pkex_free(pkex);
@@ -2588,7 +2838,9 @@
 	wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
 		   pkex->exch_req_tries);
 	wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
-		MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
+		MAC2STR(broadcast), pkex->freq,
+		pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
+		DPP_PA_PKEX_V1_EXCHANGE_REQ);
 	offchannel_send_action(wpa_s, pkex->freq, broadcast,
 			       wpa_s->own_addr, broadcast,
 			       wpabuf_head(pkex->exchange_req),
@@ -2647,7 +2899,8 @@
 
 static void
 wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
-			      const u8 *buf, size_t len, unsigned int freq)
+			      const u8 *buf, size_t len, unsigned int freq,
+			      bool v2)
 {
 	struct wpabuf *msg;
 	unsigned int wait_time;
@@ -2675,7 +2928,7 @@
 						   wpa_s->own_addr, src,
 						   wpa_s->dpp_pkex_identifier,
 						   wpa_s->dpp_pkex_code,
-						   buf, len);
+						   buf, len, v2);
 	if (!wpa_s->dpp_pkex) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Failed to process the request - ignore it");
@@ -2898,8 +3151,17 @@
 	case DPP_PA_PEER_DISCOVERY_RESP:
 		wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
 		break;
+#ifdef CONFIG_DPP3
 	case DPP_PA_PKEX_EXCHANGE_REQ:
-		wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
+		/* This is for PKEXv2, but for now, process only with
+		 * CONFIG_DPP3 to avoid issues with a capability that has not
+		 * been tested with other implementations. */
+		wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
+		break;
+#endif /* CONFIG_DPP3 */
+	case DPP_PA_PKEX_V1_EXCHANGE_REQ:
+		wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
+					      false);
 		break;
 	case DPP_PA_PKEX_EXCHANGE_RESP:
 		wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
@@ -2956,9 +3218,25 @@
 }
 
 
+static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
+					      void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+	if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+		   "DPP: No configuration available from upper layers - send initial response with comeback delay");
+	gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
+				      500);
+}
+
+
 static struct wpabuf *
 wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
-			 const u8 *query, size_t query_len, u16 *comeback_delay)
+			 const u8 *query, size_t query_len, int *comeback_delay)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	struct dpp_authentication *auth = wpa_s->dpp_auth;
@@ -2990,21 +3268,75 @@
 		MAC2STR(sa));
 	resp = dpp_conf_req_rx(auth, query, query_len);
 
+	auth->gas_server_ctx = resp_ctx;
+
 #ifdef CONFIG_DPP2
 	if (!resp && auth->waiting_cert) {
 		wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
-		auth->cert_resp_ctx = resp_ctx;
+		auth->config_resp_ctx = resp_ctx;
 		*comeback_delay = 500;
 		return NULL;
 	}
 #endif /* CONFIG_DPP2 */
 
+	if (!resp && auth->waiting_config &&
+	    (auth->peer_bi || auth->tmp_peer_bi)) {
+		char *buf = NULL, *name = "";
+		char band[200], *pos, *end;
+		int i, res, *opclass = auth->e_band_support;
+		char *mud_url = "N/A";
+
+		wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
+		auth->config_resp_ctx = resp_ctx;
+		*comeback_delay = -1;
+		if (auth->e_name) {
+			size_t len = os_strlen(auth->e_name);
+
+			buf = os_malloc(len * 4 + 1);
+			if (buf) {
+				printf_encode(buf, len * 4 + 1,
+					      (const u8 *) auth->e_name, len);
+				name = buf;
+			}
+		}
+		band[0] = '\0';
+		pos = band;
+		end = band + sizeof(band);
+		for (i = 0; opclass && opclass[i]; i++) {
+			res = os_snprintf(pos, end - pos, "%s%d",
+					  pos == band ? "" : ",", opclass[i]);
+			if (os_snprintf_error(end - pos, res)) {
+				*pos = '\0';
+				break;
+			}
+			pos += res;
+		}
+		if (auth->e_mud_url) {
+			size_t len = os_strlen(auth->e_mud_url);
+
+			if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
+				mud_url = auth->e_mud_url;
+		}
+		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
+			MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
+			auth->peer_bi ? auth->peer_bi->id :
+			auth->tmp_peer_bi->id, MAC2STR(sa),
+			dpp_netrole_str(auth->e_netrole), name, band, mud_url);
+		os_free(buf);
+
+		eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
+				     NULL);
+		eloop_register_timeout(0, 50000,
+				       wpas_dpp_gas_initial_resp_timeout, wpa_s,
+				       NULL);
+		return NULL;
+	}
+
 	if (!resp) {
 		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
 		wpas_notify_dpp_configuration_failure(wpa_s);
 	}
 	auth->conf_resp = resp;
-	auth->gas_server_ctx = resp_ctx;
 	return resp;
 }
 
@@ -3219,17 +3551,45 @@
 
 #ifdef CONFIG_TESTING_OPTIONS
 skip_connector:
+	if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
+		goto skip_proto_ver;
+	}
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_DPP2
 	if (DPP_VERSION > 1) {
+		u8 ver = DPP_VERSION;
+#ifdef CONFIG_DPP3
+		int conn_ver;
+
+		conn_ver = dpp_get_connector_version(ssid->dpp_connector);
+		if (conn_ver > 0 && ver != conn_ver) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: Use Connector version %d instead of current protocol version %d",
+				   conn_ver, ver);
+			ver = conn_ver;
+		}
+#endif /* CONFIG_DPP3 */
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
+		ver = 1;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 		/* Protocol Version */
 		wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
 		wpabuf_put_le16(msg, 1);
-		wpabuf_put_u8(msg, DPP_VERSION);
+		wpabuf_put_u8(msg, ver);
 	}
 #endif /* CONFIG_DPP2 */
 
+#ifdef CONFIG_TESTING_OPTIONS
+skip_proto_ver:
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	/* TODO: Timeout on AP response */
 	wait_time = wpa_s->max_remain_on_chan;
 	if (wait_time > 2000)
@@ -3254,7 +3614,29 @@
 {
 	struct dpp_bootstrap_info *own_bi;
 	const char *pos, *end;
-	unsigned int wait_time;
+	int tcp_port = DPP_TCP_PORT;
+	struct hostapd_ip_addr *ipaddr = NULL;
+#ifdef CONFIG_DPP2
+	struct hostapd_ip_addr ipaddr_buf;
+	char *addr;
+
+	pos = os_strstr(cmd, " tcp_port=");
+	if (pos) {
+		pos += 10;
+		tcp_port = atoi(pos);
+	}
+
+	addr = get_param(cmd, " tcp_addr=");
+	if (addr) {
+		int res;
+
+		res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
+		os_free(addr);
+		if (res)
+			return -1;
+		ipaddr = &ipaddr_buf;
+	}
+#endif /* CONFIG_DPP2 */
 
 	pos = os_strstr(cmd, " own=");
 	if (!pos)
@@ -3298,35 +3680,34 @@
 		return -1;
 
 	if (os_strstr(cmd, " init=1")) {
-		struct dpp_pkex *pkex;
-		struct wpabuf *msg;
+#ifdef CONFIG_DPP3
+		enum wpas_dpp_pkex_ver ver = PKEX_VER_AUTO;
+#else /* CONFIG_DPP3 */
+		enum wpas_dpp_pkex_ver ver = PKEX_VER_ONLY_1;
+#endif /* CONFIG_DPP3 */
 
-		wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
-		dpp_pkex_free(wpa_s->dpp_pkex);
-		wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
-						wpa_s->dpp_pkex_identifier,
-						wpa_s->dpp_pkex_code);
-		pkex = wpa_s->dpp_pkex;
-		if (!pkex)
+		pos = os_strstr(cmd, " ver=");
+		if (pos) {
+			int v;
+
+			pos += 5;
+			v = atoi(pos);
+			if (v == 1)
+				ver = PKEX_VER_ONLY_1;
+			else if (v == 2)
+				ver = PKEX_VER_ONLY_2;
+			else
+				return -1;
+		}
+
+		if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
 			return -1;
-
-		msg = pkex->exchange_req;
-		wait_time = wpa_s->max_remain_on_chan;
-		if (wait_time > 2000)
-			wait_time = 2000;
-		pkex->freq = 2437;
-		wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
-			" freq=%u type=%d",
-			MAC2STR(broadcast), pkex->freq,
-			DPP_PA_PKEX_EXCHANGE_REQ);
-		offchannel_send_action(wpa_s, pkex->freq, broadcast,
-				       wpa_s->own_addr, broadcast,
-				       wpabuf_head(msg), wpabuf_len(msg),
-				       wait_time, wpas_dpp_tx_pkex_status, 0);
-		if (wait_time == 0)
-			wait_time = 2000;
-		pkex->exch_req_wait_time = wait_time;
-		pkex->exch_req_tries = 1;
+	} else {
+#ifdef CONFIG_DPP2
+		dpp_controller_pkex_add(wpa_s->dpp, own_bi,
+					wpa_s->dpp_pkex_code,
+					wpa_s->dpp_pkex_identifier);
+#endif /* CONFIG_DPP2 */
 	}
 
 	/* TODO: Support multiple PKEX info entries */
@@ -3425,6 +3806,8 @@
 	eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
+	eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
+	eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
 #ifdef CONFIG_DPP2
 	eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
 	eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
@@ -3450,6 +3833,87 @@
 }
 
 
+static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
+				    struct dpp_authentication *auth, bool tcp)
+{
+	struct wpabuf *resp;
+
+	resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
+				   auth->e_netrole, true);
+	if (!resp)
+		return -1;
+
+	if (tcp) {
+		auth->conf_resp_tcp = resp;
+		return 0;
+	}
+
+	eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
+	if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
+				resp) < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Could not find pending GAS response");
+		wpabuf_free(resp);
+		return -1;
+	}
+	auth->conf_resp = resp;
+	return 0;
+}
+
+
+int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+	int peer;
+	const char *pos;
+	struct dpp_authentication *auth = wpa_s->dpp_auth;
+	bool tcp = false;
+
+	pos = os_strstr(cmd, " peer=");
+	if (!pos)
+		return -1;
+	peer = atoi(pos + 6);
+#ifdef CONFIG_DPP2
+	if (!auth || !auth->waiting_config ||
+	    (auth->peer_bi &&
+	     (unsigned int) peer != auth->peer_bi->id)) {
+		auth = dpp_controller_get_auth(wpa_s->dpp, peer);
+		tcp = true;
+	}
+#endif /* CONFIG_DPP2 */
+
+	if (!auth || !auth->waiting_config) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: No authentication exchange waiting for configuration information");
+		return -1;
+	}
+
+	if ((!auth->peer_bi ||
+	     (unsigned int) peer != auth->peer_bi->id) &&
+	    (!auth->tmp_peer_bi ||
+	     (unsigned int) peer != auth->tmp_peer_bi->id)) {
+		wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
+		return -1;
+	}
+
+	pos = os_strstr(cmd, " comeback=");
+	if (pos) {
+		eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
+				     NULL);
+		gas_server_set_comeback_delay(wpa_s->gas_server,
+					      auth->config_resp_ctx,
+					      atoi(pos + 10));
+		return 0;
+	}
+
+	if (dpp_set_configurator(auth, cmd) < 0)
+		return -1;
+
+	auth->use_config_query = false;
+	auth->waiting_config = false;
+	return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
+}
+
+
 #ifdef CONFIG_DPP2
 
 int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
@@ -3463,6 +3927,7 @@
 	config.msg_ctx = wpa_s;
 	config.cb_ctx = wpa_s;
 	config.process_conf_obj = wpas_dpp_process_conf_obj;
+	config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
 	if (cmd) {
 		pos = os_strstr(cmd, " tcp_port=");
 		if (pos) {
@@ -3573,7 +4038,7 @@
 	struct hostapd_hw_modes *mode;
 	int c;
 	struct wpa_bss *bss;
-	bool chan6;
+	bool chan6 = wpa_s->hw.modes == NULL;
 
 	if (!bi && !wpa_s->dpp_reconfig_ssid)
 		return;
@@ -3593,7 +4058,6 @@
 	/* Preferred chirping channels */
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
 			HOSTAPD_MODE_IEEE80211G, false);
-	chan6 = mode == NULL;
 	if (mode) {
 		for (c = 0; c < mode->num_channels; c++) {
 			struct hostapd_channel_data *chan = &mode->channels[c];
@@ -3868,33 +4332,6 @@
 }
 
 
-static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
-				    struct dpp_authentication *auth, bool tcp)
-{
-	struct wpabuf *resp;
-
-	resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
-				   auth->e_netrole, true);
-	if (!resp)
-		return -1;
-
-	if (tcp) {
-		auth->conf_resp_tcp = resp;
-		return 0;
-	}
-
-	if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx,
-				resp) < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not find pending GAS response");
-		wpabuf_free(resp);
-		return -1;
-	}
-	auth->conf_resp = resp;
-	return 0;
-}
-
-
 int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
 {
 	int peer = -1;
diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h
index b0d5fcf..2b03a54 100644
--- a/wpa_supplicant/dpp_supplicant.h
+++ b/wpa_supplicant/dpp_supplicant.h
@@ -2,6 +2,7 @@
  * wpa_supplicant - DPP
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -23,6 +24,7 @@
 				   unsigned int freq, unsigned int duration);
 void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 					  unsigned int freq);
+void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s);
 void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
 			const u8 *buf, size_t len, unsigned int freq);
 int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd);
@@ -41,5 +43,6 @@
 void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s);
 int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd);
 int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd);
 
 #endif /* DPP_SUPPLICANT_H */
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 11eee98..e256ac5 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -1023,6 +1023,7 @@
 		*pos++ = a[1];
 		*pos++ = a[2];
 		*pos++ = a[3];
+		as->addr.af = AF_INET;
 	}
 #else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
 	if (hostapd_parse_ip_addr(authsrv, &as->addr) < 0) {
diff --git a/wpa_supplicant/eapol_test.py b/wpa_supplicant/eapol_test.py
index 734428d..88c83f3 100644
--- a/wpa_supplicant/eapol_test.py
+++ b/wpa_supplicant/eapol_test.py
@@ -72,7 +72,7 @@
                 break
         return None
 
-def run(ifname, count, no_fast_reauth, res):
+def run(ifname, count, no_fast_reauth, res, conf):
     et = eapol_test(ifname)
 
     et.request("AP_SCAN 0")
@@ -81,14 +81,20 @@
     else:
         et.request("SET fast_reauth 1")
     id = et.add_network()
-    et.set_network(id, "key_mgmt", "IEEE8021X")
-    et.set_network(id, "eapol_flags", "0")
-    et.set_network(id, "eap", "TLS")
-    et.set_network_quoted(id, "identity", "user")
-    et.set_network_quoted(id, "ca_cert", 'ca.pem')
-    et.set_network_quoted(id, "client_cert", 'client.pem')
-    et.set_network_quoted(id, "private_key", 'client.key')
-    et.set_network_quoted(id, "private_key_passwd", 'whatever')
+
+    if len(conf):
+        for item in conf:
+            et.set_network(id, item, conf[item])
+    else:
+        et.set_network(id, "key_mgmt", "IEEE8021X")
+        et.set_network(id, "eapol_flags", "0")
+        et.set_network(id, "eap", "TLS")
+        et.set_network_quoted(id, "identity", "user")
+        et.set_network_quoted(id, "ca_cert", 'ca.pem')
+        et.set_network_quoted(id, "client_cert", 'client.pem')
+        et.set_network_quoted(id, "private_key", 'client.key')
+        et.set_network_quoted(id, "private_key_passwd", 'whatever')
+
     et.set_network(id, "disabled", "0")
 
     fail = False
@@ -114,6 +120,7 @@
     parser.add_argument('--no-fast-reauth', action='store_true',
                         dest='no_fast_reauth',
                         help='disable TLS session resumption')
+    parser.add_argument('--conf', help='file of network conf items')
     args = parser.parse_args()
 
     num = int(args.num)
@@ -122,12 +129,22 @@
         global wpas_ctrl
         wpas_ctrl = args.ctrl
 
+    conf = {}
+    if args.conf:
+        f = open(args.conf, "r")
+        for line in f:
+            confitem = line.split("=")
+            if len(confitem) == 2:
+                conf[confitem[0].strip()] = confitem[1].strip()
+        f.close()
+
     t = {}
     res = {}
     for i in range(num):
         res[i] = Queue.Queue()
         t[i] = threading.Thread(target=run, args=(str(i), iter,
-                                                  args.no_fast_reauth, res[i]))
+                                                  args.no_fast_reauth, res[i],
+                                                  conf))
     for i in range(num):
         t[i].start()
     for i in range(num):
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 01bbde6..0003d1f 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -357,9 +357,14 @@
 	struct wpa_ie_data ie;
 	int pmksa_set = -1;
 	size_t i;
+	struct rsn_pmksa_cache_entry *cur_pmksa;
 
-	/* Start with assumption of no PMKSA cache entry match */
-	pmksa_cache_clear_current(wpa_s->wpa);
+	/* Start with assumption of no PMKSA cache entry match for cases other
+	 * than SAE. In particular, this is needed to generate the PMKSA cache
+	 * entries for Suite B cases with driver-based roaming indication. */
+	cur_pmksa = pmksa_cache_get_current(wpa_s->wpa);
+	if (cur_pmksa && !wpa_key_mgmt_sae(cur_pmksa->akmp))
+		pmksa_cache_clear_current(wpa_s->wpa);
 
 	if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 ||
 	    ie.pmkid == NULL)
@@ -1103,14 +1108,11 @@
 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 		int count;
 		const u8 *ie;
-		u8 rsnxe_capa = 0;
 
 		if (bss == orig_bss)
 			continue;
 		ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
-		if (ie && ie[1] >= 1)
-			rsnxe_capa = ie[2];
-		if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)))
+		if (!(ieee802_11_rsnx_capab(ie, WLAN_RSNX_CAPAB_SAE_PK)))
 			continue;
 
 		/* TODO: Could be more thorough in checking what kind of
@@ -1317,6 +1319,9 @@
 #ifdef CONFIG_SAE
 	if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) &&
 	    wpa_s->conf->sae_pwe != 3 && wpa_key_mgmt_sae(ssid->key_mgmt) &&
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	    !(wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt)) &&
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 	    !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
 		if (debug_print)
 			wpa_dbg(wpa_s, MSG_DEBUG,
@@ -1857,7 +1862,7 @@
 	const u8 *ies = wpa_bss_ie_ptr(bss);
 	size_t ie_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
 
-	return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr);
+	return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr, bss->freq);
 }
 
 
@@ -2176,7 +2181,7 @@
 	if (wnm_scan_process(wpa_s, 1) > 0)
 		goto scan_work_done;
 
-	if (sme_proc_obss_scan(wpa_s, scan_res) > 0)
+	if (sme_proc_obss_scan(wpa_s) > 0)
 		goto scan_work_done;
 
 	if (own_request && data &&
@@ -2685,6 +2690,205 @@
 #endif /* CONFIG_FST */
 
 
+static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
+					      union wpa_event_data *data)
+{
+	int sel;
+	const u8 *p;
+	int l, len;
+	bool found = false;
+	struct wpa_ie_data ie;
+	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	struct wpa_bss *bss = wpa_s->current_bss;
+	int pmf;
+
+	if (!ssid)
+		return 0;
+
+	p = data->assoc_info.req_ies;
+	l = data->assoc_info.req_ies_len;
+
+	while (p && l >= 2) {
+		len = p[1] + 2;
+		if (len > l) {
+			wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info",
+				    p, l);
+			break;
+		}
+		if (((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+		      (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
+		     (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4 &&
+		      (os_memcmp(&p[2], "\x50\x6F\x9A\x12", 4) == 0)) ||
+		     (p[0] == WLAN_EID_RSN && p[1] >= 2))) {
+			found = true;
+			break;
+		}
+		l -= len;
+		p += len;
+	}
+
+	if (!found || wpa_parse_wpa_ie(p, len, &ie) < 0)
+		return 0;
+
+	wpa_hexdump(MSG_DEBUG,
+		    "WPA: Update cipher suite selection based on IEs in driver-generated WPA/RSNE in AssocReq",
+		    p, l);
+
+	/* Update proto from (Re)Association Request frame info */
+	wpa_s->wpa_proto = ie.proto;
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, wpa_s->wpa_proto);
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
+			 !!(wpa_s->wpa_proto &
+			    (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
+
+	/* Update AKMP suite from (Re)Association Request frame info */
+	sel = ie.key_mgmt;
+	if (ssid->key_mgmt)
+		sel &= ssid->key_mgmt;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"WPA: AP key_mgmt 0x%x network key_mgmt 0x%x; available key_mgmt 0x%x",
+		ie.key_mgmt, ssid->key_mgmt, sel);
+	if (ie.key_mgmt && !sel) {
+		wpa_supplicant_deauthenticate(
+			wpa_s, WLAN_REASON_AKMP_NOT_VALID);
+		return -1;
+	}
+
+	wpa_s->key_mgmt = ie.key_mgmt;
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
+	wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT %s and proto %d",
+		wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->wpa_proto),
+		wpa_s->wpa_proto);
+
+	/* Update pairwise cipher from (Re)Association Request frame info */
+	sel = ie.pairwise_cipher;
+	if (ssid->pairwise_cipher)
+		sel &= ssid->pairwise_cipher;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"WPA: AP pairwise cipher 0x%x network pairwise cipher 0x%x; available pairwise cipher 0x%x",
+		ie.pairwise_cipher, ssid->pairwise_cipher, sel);
+	if (ie.pairwise_cipher && !sel) {
+		wpa_supplicant_deauthenticate(
+			wpa_s, WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID);
+		return -1;
+	}
+
+	wpa_s->pairwise_cipher = ie.pairwise_cipher;
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
+			 wpa_s->pairwise_cipher);
+	wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
+		wpa_cipher_txt(wpa_s->pairwise_cipher));
+
+	/* Update other parameters based on AP's WPA IE/RSNE, if available */
+	if (!bss) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WPA: current_bss == NULL - skip AP IE check");
+		return 0;
+	}
+
+	/* Update GTK and IGTK from AP's RSNE */
+	found = false;
+
+	if (wpa_s->wpa_proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) {
+		const u8 *bss_rsn;
+
+		bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+		if (bss_rsn) {
+			p = bss_rsn;
+			len = 2 + bss_rsn[1];
+			found = true;
+		}
+	} else if (wpa_s->wpa_proto & WPA_PROTO_WPA) {
+		const u8 *bss_wpa;
+
+		bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+		if (bss_wpa) {
+			p = bss_wpa;
+			len = 2 + bss_wpa[1];
+			found = true;
+		}
+	}
+
+	if (!found || wpa_parse_wpa_ie(p, len, &ie) < 0)
+		return 0;
+
+	pmf = wpas_get_ssid_pmf(wpa_s, ssid);
+	if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
+	    pmf == MGMT_FRAME_PROTECTION_REQUIRED) {
+		/* AP does not support MFP, local configuration requires it */
+		wpa_supplicant_deauthenticate(
+			wpa_s, WLAN_REASON_INVALID_RSN_IE_CAPAB);
+		return -1;
+	}
+	if ((ie.capabilities & WPA_CAPABILITY_MFPR) &&
+	    pmf == NO_MGMT_FRAME_PROTECTION) {
+		/* AP requires MFP, local configuration disables it */
+		wpa_supplicant_deauthenticate(
+			wpa_s, WLAN_REASON_INVALID_RSN_IE_CAPAB);
+		return -1;
+	}
+
+	/* Update PMF from local configuration now that MFP validation was done
+	 * above */
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, pmf);
+
+	/* Update GTK from AP's RSNE */
+	sel = ie.group_cipher;
+	if (ssid->group_cipher)
+		sel &= ssid->group_cipher;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"WPA: AP group cipher 0x%x network group cipher 0x%x; available group cipher 0x%x",
+		ie.group_cipher, ssid->group_cipher, sel);
+	if (ie.group_cipher && !sel) {
+		wpa_supplicant_deauthenticate(
+			wpa_s, WLAN_REASON_GROUP_CIPHER_NOT_VALID);
+		return -1;
+	}
+
+	wpa_s->group_cipher = ie.group_cipher;
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
+	wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
+		wpa_cipher_txt(wpa_s->group_cipher));
+
+	/* Update IGTK from AP RSN IE */
+	sel = ie.mgmt_group_cipher;
+	if (ssid->group_mgmt_cipher)
+		sel &= ssid->group_mgmt_cipher;
+
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"WPA: AP mgmt_group_cipher 0x%x network mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
+		ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
+
+	if (pmf == NO_MGMT_FRAME_PROTECTION ||
+	    !(ie.capabilities & WPA_CAPABILITY_MFPC)) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WPA: STA/AP is not MFP capable; AP RSNE caps 0x%x",
+			ie.capabilities);
+		ie.mgmt_group_cipher = 0;
+	}
+
+	if (ie.mgmt_group_cipher && !sel) {
+		wpa_supplicant_deauthenticate(
+			wpa_s, WLAN_REASON_CIPHER_SUITE_REJECTED);
+		return -1;
+	}
+
+	wpa_s->mgmt_group_cipher = ie.mgmt_group_cipher;
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
+			 wpa_s->mgmt_group_cipher);
+	if (wpa_s->mgmt_group_cipher)
+		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher %s",
+			wpa_cipher_txt(wpa_s->mgmt_group_cipher));
+	else
+		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
+
+	return 0;
+}
+
+
 static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
 					  union wpa_event_data *data)
 {
@@ -2692,6 +2896,9 @@
 	const u8 *p;
 	u8 bssid[ETH_ALEN];
 	bool bssid_known;
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	struct wpa_ie_data ie;
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
 	bssid_known = wpa_drv_get_bssid(wpa_s, bssid) == 0;
@@ -2816,6 +3023,52 @@
 	if (!found_x && data->assoc_info.req_ies)
 		wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	/* The WPA/RSN IE has been updated at this point. Since the Firmware could have roamed
+	 * to a different security type, update the current supplicant configuration to use the AKM
+	 * and pairwise suites from the assoc IE passed by the driver.
+	 */
+	if (wpas_driver_bss_selection(wpa_s)) {
+		if (!(wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0)) {
+			/* Check if firmware has roamed to a different security network */
+			if(wpa_s->key_mgmt != ie.key_mgmt) {
+				wpa_dbg(wpa_s, MSG_DEBUG, "Update to AKM suite 0x%x from Assoc IE",
+					ie.key_mgmt);
+				wpa_s->key_mgmt = ie.key_mgmt;
+				wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
+
+				if (wpa_key_mgmt_wpa_psk_no_sae(wpa_s->key_mgmt)) {
+					/* Restore PMK as it can get overwritten if the previous
+					* association was to 802.1X.
+					*/
+					if ((!(wpa_s->drv_flags &
+					    WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK)) &&
+					    (wpa_s->current_ssid) &&
+					    (wpa_s->current_ssid->psk_set)) {
+						if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
+							wpa_dbg(wpa_s, MSG_ERROR, "Failed to get "
+								"BSSID");
+							wpa_supplicant_deauthenticate(
+								wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+							return -1;
+						}
+						wpa_sm_set_pmk(wpa_s->wpa, wpa_s->current_ssid->psk,
+							PMK_LEN, NULL, bssid);
+					}
+				}
+			}
+			if(wpa_s->pairwise_cipher != ie.pairwise_cipher) {
+				wpa_dbg(wpa_s, MSG_DEBUG, "Update to pairwise cipher suite 0x%x "
+					"from Assoc IE", ie.pairwise_cipher);
+				wpa_s->pairwise_cipher = ie.pairwise_cipher;
+				wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
+					wpa_s->pairwise_cipher);
+			}
+			// TODO: Notify the framework about security type change b/230766005
+		}
+	}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
 #ifdef CONFIG_FILS
 #ifdef CONFIG_SME
 	if ((wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
@@ -3017,6 +3270,9 @@
 
 	wpa_s->assoc_freq = data->assoc_info.freq;
 
+	wpas_handle_assoc_resp_qos_mgmt(wpa_s, data->assoc_info.resp_ies,
+					data->assoc_info.resp_ies_len);
+
 	return 0;
 }
 
@@ -3194,6 +3450,10 @@
 		}
 	}
 
+	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+	    data && wpa_supplicant_use_own_rsne_params(wpa_s, data) < 0)
+		return;
+
 	multi_ap_set_4addr_mode(wpa_s);
 
 	if (wpa_s->conf->ap_scan == 1 &&
@@ -4248,7 +4508,7 @@
 
 #ifdef CONFIG_SME
 	if (category == WLAN_ACTION_SA_QUERY) {
-		sme_sa_query_rx(wpa_s, mgmt->sa, payload, plen);
+		sme_sa_query_rx(wpa_s, mgmt->da, mgmt->sa, payload, plen);
 		return;
 	}
 #endif /* CONFIG_SME */
@@ -4346,12 +4606,26 @@
 #endif /* CONFIG_DPP */
 
 	if (category == WLAN_ACTION_ROBUST_AV_STREAMING &&
+	    payload[0] == ROBUST_AV_SCS_RESP) {
+		wpas_handle_robust_av_scs_recv_action(wpa_s, mgmt->sa,
+						      payload + 1, plen - 1);
+		return;
+	}
+
+	if (category == WLAN_ACTION_ROBUST_AV_STREAMING &&
 	    payload[0] == ROBUST_AV_MSCS_RESP) {
 		wpas_handle_robust_av_recv_action(wpa_s, mgmt->sa,
 						  payload + 1, plen - 1);
 		return;
 	}
 
+	if (category == WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED && plen > 4 &&
+	    WPA_GET_BE32(payload) == QM_ACTION_VENDOR_TYPE) {
+		wpas_handle_qos_mgmt_recv_action(wpa_s, mgmt->sa,
+						 payload + 4, plen - 4);
+		return;
+	}
+
 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
 			   category, payload, plen, freq);
 	if (wpa_s->ifmsh)
@@ -4488,6 +4762,8 @@
 
 	wpa_supplicant_event_port_authorized(wpa_s);
 
+	wpa_s->last_eapol_matches_bssid = 1;
+
 	wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr);
 	wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck,
 			       data->assoc_info.ptk_kck_len,
@@ -4706,6 +4982,7 @@
 #ifdef CONFIG_FILS
 	/* Update ERP next sequence number */
 	if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) {
+		fils_pmksa_cache_flush(wpa_s);
 		eapol_sm_update_erp_next_seq_num(
 			wpa_s->eapol,
 			data->assoc_reject.fils_erp_next_seq_num);
@@ -5068,6 +5345,10 @@
 		if (event == EVENT_CH_SWITCH_STARTED)
 			break;
 
+		if (wpa_s->assoc_freq && data->ch_switch.freq &&
+			    (int) wpa_s->assoc_freq != data->ch_switch.freq) {
+			wpas_notify_frequency_changed(wpa_s, data->ch_switch.freq);
+		}
 		wpa_s->assoc_freq = data->ch_switch.freq;
 		wpa_s->current_ssid->frequency = data->ch_switch.freq;
 		if (wpa_s->current_bss &&
@@ -5322,13 +5603,21 @@
 		break;
 	case EVENT_INTERFACE_MAC_CHANGED:
 		wpa_supplicant_update_mac_addr(wpa_s);
+		wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
 		break;
 	case EVENT_INTERFACE_ENABLED:
 		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+			u8 addr[ETH_ALEN];
+
 			eloop_cancel_timeout(wpas_clear_disabled_interface,
 					     wpa_s, NULL);
+			os_memcpy(addr, wpa_s->own_addr, ETH_ALEN);
 			wpa_supplicant_update_mac_addr(wpa_s);
+			if (os_memcmp(addr, wpa_s->own_addr, ETH_ALEN) != 0)
+				wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
+			else
+				wpa_sm_pmksa_cache_reconfig(wpa_s->wpa);
 			wpa_supplicant_set_default_scan_ies(wpa_s);
 			if (wpa_s->p2p_mgmt) {
 				wpa_supplicant_set_state(wpa_s,
@@ -5589,6 +5878,11 @@
 	case EVENT_UNPROT_BEACON:
 		wpas_event_unprot_beacon(wpa_s, &data->unprot_beacon);
 		break;
+	case EVENT_TX_WAIT_EXPIRE:
+#ifdef CONFIG_DPP
+		wpas_dpp_tx_wait_expire(wpa_s);
+#endif /* CONFIG_DPP */
+		break;
 	default:
 		wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
 		break;
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index e60a8c1..a6172d6 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -273,16 +273,6 @@
 }
 
 
-int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
-{
-	if (wpa_s->current_ssid == NULL ||
-	    wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
-	    os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
-		return 0;
-	return wpa_sm_pmf_enabled(wpa_s->wpa);
-}
-
-
 static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
 			struct wpabuf *req, unsigned int wait_time)
 {
diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h
index f9ce7b6..6ccecd4 100644
--- a/wpa_supplicant/gas_query.h
+++ b/wpa_supplicant/gas_query.h
@@ -19,7 +19,6 @@
 int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
 		 const u8 *bssid, u8 categ, const u8 *data, size_t len,
 		 int freq);
-int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr);
 
 /**
  * enum gas_query_result - GAS query result
diff --git a/wpa_supplicant/hidl/1.4/android.hardware.wifi.supplicant-service.rc b/wpa_supplicant/hidl/1.4/android.hardware.wifi.supplicant-service.rc
deleted file mode 100644
index 71318d4..0000000
--- a/wpa_supplicant/hidl/1.4/android.hardware.wifi.supplicant-service.rc
+++ /dev/null
@@ -1,16 +0,0 @@
-service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
-    -O/data/vendor/wifi/wpa/sockets -dd \
-    -g@android:wpa_wlan0
-    #   we will start as root and wpa_supplicant will switch to user wifi
-    #   after setting up the capabilities required for WEXT
-    #   user wifi
-    #   group wifi inet keystore
-    interface android.hardware.wifi.supplicant@1.0::ISupplicant default
-    interface android.hardware.wifi.supplicant@1.1::ISupplicant default
-    interface android.hardware.wifi.supplicant@1.2::ISupplicant default
-    interface android.hardware.wifi.supplicant@1.3::ISupplicant default
-    interface android.hardware.wifi.supplicant@1.4::ISupplicant default
-    class main
-    socket wpa_wlan0 dgram 660 wifi wifi
-    disabled
-    oneshot
diff --git a/wpa_supplicant/hidl/1.4/android.hardware.wifi.supplicant.xml b/wpa_supplicant/hidl/1.4/android.hardware.wifi.supplicant.xml
deleted file mode 100644
index 772096c..0000000
--- a/wpa_supplicant/hidl/1.4/android.hardware.wifi.supplicant.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
-    <hal format="hidl">
-        <name>android.hardware.wifi.supplicant</name>
-        <transport>hwbinder</transport>
-        <version>1.4</version>
-        <interface>
-            <name>ISupplicant</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/wpa_supplicant/hidl/1.4/hidl.cpp b/wpa_supplicant/hidl/1.4/hidl.cpp
deleted file mode 100644
index 649772a..0000000
--- a/wpa_supplicant/hidl/1.4/hidl.cpp
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * 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.
- */
-
-#include <hwbinder/IPCThreadState.h>
-
-#include <hidl/HidlTransportSupport.h>
-#include "hidl_manager.h"
-
-extern "C"
-{
-#include "hidl.h"
-#include "hidl_i.h"
-#include "utils/common.h"
-#include "utils/eloop.h"
-#include "utils/includes.h"
-#include "dpp.h"
-}
-
-using android::hardware::configureRpcThreadpool;
-using android::hardware::handleTransportPoll;
-using android::hardware::setupTransportPolling;
-using android::hardware::wifi::supplicant::V1_3::DppFailureCode;
-using android::hardware::wifi::supplicant::V1_3::DppProgressCode;
-using android::hardware::wifi::supplicant::V1_3::DppSuccessCode;
-using android::hardware::wifi::supplicant::V1_4::implementation::HidlManager;
-
-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);
-static void wpas_hidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppSuccessCode code);
-
-void wpas_hidl_sock_handler(
-    int sock, void * /* eloop_ctx */, void * /* sock_ctx */)
-{
-	handleTransportPoll(sock);
-}
-
-struct wpas_hidl_priv *wpas_hidl_init(struct wpa_global *global)
-{
-	struct wpas_hidl_priv *priv;
-	HidlManager *hidl_manager;
-
-	priv = (wpas_hidl_priv *)os_zalloc(sizeof(*priv));
-	if (!priv)
-		return NULL;
-	priv->global = global;
-
-	wpa_printf(MSG_DEBUG, "Initing hidl control");
-
-	configureRpcThreadpool(1, true /* callerWillJoin */);
-	priv->hidl_fd = setupTransportPolling();
-	if (priv->hidl_fd < 0)
-		goto err;
-
-	wpa_printf(MSG_INFO, "Processing hidl events on FD %d", priv->hidl_fd);
-	// Look for read events from the hidl socket in the eloop.
-	if (eloop_register_read_sock(
-		priv->hidl_fd, wpas_hidl_sock_handler, global, priv) < 0)
-		goto err;
-
-	hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		goto err;
-	if (hidl_manager->registerHidlService(global)) {
-		goto err;
-	}
-	// We may not need to store this hidl manager reference in the
-	// global data strucure because we've made it a singleton class.
-	priv->hidl_manager = (void *)hidl_manager;
-
-	return priv;
-err:
-	wpas_hidl_deinit(priv);
-	return NULL;
-}
-
-void wpas_hidl_deinit(struct wpas_hidl_priv *priv)
-{
-	if (!priv)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Deiniting hidl control");
-
-	HidlManager::destroyInstance();
-	eloop_unregister_read_sock(priv->hidl_fd);
-	os_free(priv);
-}
-
-int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s || !wpa_s->global->hidl)
-		return 1;
-
-	wpa_printf(
-	    MSG_DEBUG, "Registering interface to hidl control: %s",
-	    wpa_s->ifname);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return 1;
-
-	return hidl_manager->registerInterface(wpa_s);
-}
-
-int wpas_hidl_unregister_interface(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s || !wpa_s->global->hidl)
-		return 1;
-
-	wpa_printf(
-	    MSG_DEBUG, "Deregistering interface from hidl control: %s",
-	    wpa_s->ifname);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return 1;
-
-	return hidl_manager->unregisterInterface(wpa_s);
-}
-
-int wpas_hidl_register_network(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
-{
-	if (!wpa_s || !wpa_s->global->hidl || !ssid)
-		return 1;
-
-	wpa_printf(
-	    MSG_DEBUG, "Registering network to hidl control: %d", ssid->id);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return 1;
-
-	return hidl_manager->registerNetwork(wpa_s, ssid);
-}
-
-int wpas_hidl_unregister_network(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
-{
-	if (!wpa_s || !wpa_s->global->hidl || !ssid)
-		return 1;
-
-	wpa_printf(
-	    MSG_DEBUG, "Deregistering network from hidl control: %d", ssid->id);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return 1;
-
-	return hidl_manager->unregisterNetwork(wpa_s, ssid);
-}
-
-int wpas_hidl_notify_state_changed(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s || !wpa_s->global->hidl)
-		return 1;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying state change event to hidl control: %d",
-	    wpa_s->wpa_state);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return 1;
-
-	return hidl_manager->notifyStateChange(wpa_s);
-}
-
-int wpas_hidl_notify_network_request(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
-    enum wpa_ctrl_req_type rtype, const char *default_txt)
-{
-	if (!wpa_s || !wpa_s->global->hidl || !ssid)
-		return 1;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying network request to hidl control: %d",
-	    ssid->id);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return 1;
-
-	return hidl_manager->notifyNetworkRequest(
-	    wpa_s, ssid, rtype, default_txt);
-}
-
-void wpas_hidl_notify_anqp_query_done(
-    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
-    const struct wpa_bss_anqp *anqp)
-{
-	if (!wpa_s || !wpa_s->global->hidl || !bssid || !result || !anqp)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying ANQP query done to hidl control: " MACSTR "result: %s",
-	    MAC2STR(bssid), result);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyAnqpQueryDone(wpa_s, bssid, result, anqp);
-}
-
-void wpas_hidl_notify_hs20_icon_query_done(
-    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
-    const u8 *image, u32 image_length)
-{
-	if (!wpa_s || !wpa_s->global->hidl || !bssid || !file_name || !image)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying HS20 icon query done to hidl control: " MACSTR
-	    "file_name: %s",
-	    MAC2STR(bssid), file_name);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyHs20IconQueryDone(
-	    wpa_s, bssid, file_name, image, image_length);
-}
-
-void wpas_hidl_notify_hs20_rx_subscription_remediation(
-    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
-{
-	if (!wpa_s || !wpa_s->global->hidl || !url)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying HS20 subscription remediation rx to hidl control: %s",
-	    url);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyHs20RxSubscriptionRemediation(
-	    wpa_s, url, osu_method);
-}
-
-void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
-    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
-{
-	if (!wpa_s || !wpa_s->global->hidl)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying HS20 deauth imminent notice rx to hidl control: %s",
-	    url ? url : "<no URL>");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyHs20RxDeauthImminentNotice(
-	    wpa_s, code, reauth_delay, url);
-}
-
-void wpas_hidl_notify_hs20_rx_terms_and_conditions_acceptance(
-		struct wpa_supplicant *wpa_s, const char *url)
-{
-	if (!wpa_s || !wpa_s->global->hidl || !url)
-		return;
-
-	wpa_printf(MSG_DEBUG,
-			"Notifying HS20 terms and conditions acceptance rx to hidl control: %s",
-			url);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyHs20RxTermsAndConditionsAcceptance(wpa_s, url);
-}
-
-void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying disconnect reason to hidl control: %d",
-	    wpa_s->disconnect_reason);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyDisconnectReason(wpa_s);
-}
-
-void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s,
-    const u8 *bssid, u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying assoc reject to hidl control: %d",
-	    wpa_s->assoc_status_code);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyAssocReject(wpa_s, bssid, timed_out, assoc_resp_ie, assoc_resp_ie_len);
-}
-
-void wpas_hidl_notify_auth_timeout(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Notifying auth timeout to hidl control");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyAuthTimeout(wpa_s);
-}
-
-void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Notifying bssid changed to hidl control");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyBssidChanged(wpa_s);
-}
-
-void wpas_hidl_notify_wps_event_fail(
-    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
-    uint16_t error_indication)
-{
-	if (!wpa_s || !peer_macaddr)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying Wps event fail to hidl control: %d, %d",
-	    config_error, error_indication);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyWpsEventFail(
-	    wpa_s, peer_macaddr, config_error, error_indication);
-}
-
-void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Notifying Wps event success to hidl control");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyWpsEventSuccess(wpa_s);
-}
-
-void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying Wps event PBC overlap to hidl control");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyWpsEventPbcOverlap(wpa_s);
-}
-
-void wpas_hidl_notify_p2p_device_found(
-    struct wpa_supplicant *wpa_s, const u8 *addr,
-    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
-    u8 peer_wfd_r2_device_info_len)
-{
-	if (!wpa_s || !addr || !info)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying P2P device found to hidl control " MACSTR,
-	    MAC2STR(info->p2p_device_addr));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pDeviceFound(
-	    wpa_s, addr, info, peer_wfd_device_info,
-	    peer_wfd_device_info_len, peer_wfd_r2_device_info,
-	    peer_wfd_r2_device_info_len);
-}
-
-void wpas_hidl_notify_p2p_device_lost(
-    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
-{
-	if (!wpa_s || !p2p_device_addr)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying P2P device lost to hidl control " MACSTR,
-	    MAC2STR(p2p_device_addr));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pDeviceLost(wpa_s, p2p_device_addr);
-}
-
-void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Notifying P2P find stop to hidl control");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pFindStopped(wpa_s);
-}
-
-void wpas_hidl_notify_p2p_go_neg_req(
-    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
-    u8 go_intent)
-{
-	if (!wpa_s || !src_addr)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P GO negotiation request to hidl control " MACSTR,
-	    MAC2STR(src_addr));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pGoNegReq(
-	    wpa_s, src_addr, dev_passwd_id, go_intent);
-}
-
-void wpas_hidl_notify_p2p_go_neg_completed(
-    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
-{
-	if (!wpa_s || !res)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P GO negotiation completed to hidl control: %d",
-	    res->status);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pGoNegCompleted(wpa_s, res);
-}
-
-void wpas_hidl_notify_p2p_group_formation_failure(
-    struct wpa_supplicant *wpa_s, const char *reason)
-{
-	if (!wpa_s || !reason)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P Group formation failure to hidl control: %s",
-	    reason);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pGroupFormationFailure(wpa_s, reason);
-}
-
-void wpas_hidl_notify_p2p_group_started(
-    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
-    int client)
-{
-	if (!wpa_s || !ssid)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying P2P Group start to hidl control: %d",
-	    ssid->id);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pGroupStarted(wpa_s, ssid, persistent, client);
-}
-
-void wpas_hidl_notify_p2p_group_removed(
-    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
-{
-	if (!wpa_s || !ssid || !role)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG, "Notifying P2P Group removed to hidl control: %d",
-	    ssid->id);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pGroupRemoved(wpa_s, ssid, role);
-}
-
-void wpas_hidl_notify_p2p_invitation_received(
-    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
-    const u8 *bssid, int id, int op_freq)
-{
-	if (!wpa_s || !sa || !go_dev_addr || !bssid)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P invitation received to hidl control: %d " MACSTR, id,
-	    MAC2STR(bssid));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pInvitationReceived(
-	    wpa_s, sa, go_dev_addr, bssid, id, op_freq);
-}
-
-void wpas_hidl_notify_p2p_invitation_result(
-    struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
-{
-	if (!wpa_s)
-		return;
-	if (bssid) {
-		wpa_printf(
-		    MSG_DEBUG,
-		    "Notifying P2P invitation result to hidl control: " MACSTR,
-		    MAC2STR(bssid));
-	} else {
-		wpa_printf(
-		    MSG_DEBUG,
-		    "Notifying P2P invitation result to hidl control: NULL "
-		    "bssid");
-	}
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pInvitationResult(wpa_s, status, bssid);
-}
-
-void wpas_hidl_notify_p2p_provision_discovery(
-    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
-    enum p2p_prov_disc_status status, u16 config_methods,
-    unsigned int generated_pin)
-{
-	if (!wpa_s || !dev_addr)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P provision discovery to hidl control " MACSTR,
-	    MAC2STR(dev_addr));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pProvisionDiscovery(
-	    wpa_s, dev_addr, request, status, config_methods, generated_pin);
-}
-
-void wpas_hidl_notify_p2p_sd_response(
-    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
-    const u8 *tlvs, size_t tlvs_len)
-{
-	if (!wpa_s || !sa || !tlvs)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P service discovery response to hidl control " MACSTR,
-	    MAC2STR(sa));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyP2pSdResponse(
-	    wpa_s, sa, update_indic, tlvs, tlvs_len);
-}
-
-void wpas_hidl_notify_ap_sta_authorized(
-    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
-{
-	if (!wpa_s || !sta)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P AP STA authorized to hidl control " MACSTR,
-	    MAC2STR(sta));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyApStaAuthorized(wpa_s, sta, p2p_dev_addr);
-}
-
-void wpas_hidl_notify_ap_sta_deauthorized(
-    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
-{
-	if (!wpa_s || !sta)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying P2P AP STA deauthorized to hidl control " MACSTR,
-	    MAC2STR(sta));
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyApStaDeauthorized(wpa_s, sta, p2p_dev_addr);
-}
-
-void wpas_hidl_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Notifying EAP Error: %d ", error_code);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyEapError(wpa_s, error_code);
-}
-
-void wpas_hidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
-	    struct wpa_ssid *ssid)
-{
-	if (!wpa_s || !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(wpa_s, ssid);
-}
-
-void wpas_hidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_success(wpa_s, DppSuccessCode::CONFIGURATION_SENT);
-}
-
-/* DPP Progress notifications */
-void wpas_hidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_progress(wpa_s, DppProgressCode::AUTHENTICATION_SUCCESS);
-}
-
-void wpas_hidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_progress(wpa_s, DppProgressCode::RESPONSE_PENDING);
-}
-
-/* DPP Failure notifications */
-void wpas_hidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::NOT_COMPATIBLE);
-}
-
-void wpas_hidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::AUTHENTICATION);
-}
-
-void wpas_hidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::CONFIGURATION);
-}
-
-void wpas_hidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::TIMEOUT);
-}
-
-void wpas_hidl_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::AUTHENTICATION);
-}
-
-void wpas_hidl_notify_dpp_fail(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::FAILURE);
-}
-
-void wpas_hidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_progress(wpa_s, DppProgressCode::CONFIGURATION_SENT_WAITING_RESPONSE);
-}
-
-/* DPP notification helper functions */
-static void wpas_hidl_notify_dpp_failure(struct wpa_supplicant *wpa_s, DppFailureCode code)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying DPP failure event %d", code);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyDppFailure(wpa_s, code);
-}
-
-static void wpas_hidl_notify_dpp_progress(struct wpa_supplicant *wpa_s, DppProgressCode code)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying DPP progress event %d", code);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyDppProgress(wpa_s, code);
-}
-
-void wpas_hidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_progress(wpa_s, DppProgressCode::CONFIGURATION_ACCEPTED);
-}
-
-static void wpas_hidl_notify_dpp_config_applied(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_success(wpa_s, DppSuccessCode::CONFIGURATION_APPLIED);
-}
-
-static void wpas_hidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppSuccessCode code)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying DPP progress event %d", code);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyDppSuccess(wpa_s, code);
-}
-
-void wpas_hidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s)
-{
-	wpas_hidl_notify_dpp_failure(wpa_s, DppFailureCode::CONFIGURATION_REJECTED);
-}
-
-static void wpas_hidl_notify_dpp_no_ap_failure(struct wpa_supplicant *wpa_s,
-		const char *ssid, const char *channel_list, unsigned short band_list[],
-		int size)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(MSG_DEBUG,
-			"Notifying DPP NO AP event for SSID %s\nTried channels: %s",
-			ssid ? ssid : "N/A", channel_list ? channel_list : "N/A");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyDppFailure(wpa_s, DppFailureCode::CANNOT_FIND_NETWORK,
-			ssid, channel_list, band_list, size);
-}
-
-void wpas_hidl_notify_dpp_enrollee_auth_failure(struct wpa_supplicant *wpa_s,
-		const char *ssid, unsigned short band_list[], int size)
-{
-	if (!wpa_s)
-		return;
-
-	wpa_printf(MSG_DEBUG,
-			"Notifying DPP Enrollee authentication failure, SSID %s",
-			ssid ? ssid : "N/A");
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyDppFailure(wpa_s, DppFailureCode::ENROLLEE_AUTHENTICATION,
-			ssid, NULL, band_list, size);
-}
-
-
-void wpas_hidl_notify_dpp_conn_status(struct wpa_supplicant *wpa_s, enum dpp_status_error status,
-		const char *ssid, const char *channel_list, unsigned short band_list[], int size)
-{
-	switch (status)
-	{
-	case DPP_STATUS_OK:
-		wpas_hidl_notify_dpp_config_applied(wpa_s);
-		break;
-
-	case DPP_STATUS_NO_AP:
-		wpas_hidl_notify_dpp_no_ap_failure(wpa_s, ssid, channel_list, band_list, size);
-		break;
-
-	case DPP_STATUS_AUTH_FAILURE:
-		wpas_hidl_notify_dpp_enrollee_auth_failure(wpa_s, ssid, band_list, size);
-		break;
-
-	default:
-		break;
-	}
-}
-
-void wpas_hidl_notify_pmk_cache_added(
-    struct wpa_supplicant *wpa_s,
-    struct rsn_pmksa_cache_entry *pmksa_entry)
-{
-	if (!wpa_s || !pmksa_entry)
-		return;
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	wpa_printf(
-	    MSG_DEBUG,
-	    "Notifying PMK cache added event");
-
-	hidl_manager->notifyPmkCacheAdded(wpa_s, pmksa_entry);
-}
-
-void wpas_hidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Notifying BSS transition status");
-
-	hidl_manager->notifyBssTmStatus(wpa_s);
-}
-
-void wpas_hidl_notify_transition_disable(struct wpa_supplicant *wpa_s,
-					    struct wpa_ssid *ssid,
-					    u8 bitmap)
-{
-	if (!wpa_s || !ssid)
-		return;
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	hidl_manager->notifyTransitionDisable(wpa_s, ssid, bitmap);
-}
-
-void wpas_hidl_notify_network_not_found(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Notify network not found");
-
-	hidl_manager->notifyNetworkNotFound(wpa_s);
-}
diff --git a/wpa_supplicant/hidl/1.4/hidl.h b/wpa_supplicant/hidl/1.4/hidl.h
deleted file mode 100644
index 0974048..0000000
--- a/wpa_supplicant/hidl/1.4/hidl.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_HIDL_H
-#define WPA_SUPPLICANT_HIDL_HIDL_H
-
-#ifdef _cplusplus
-extern "C"
-{
-#endif  // _cplusplus
-
-	/**
-	 * This is the hidl RPC interface entry point to the wpa_supplicant
-	 * core. This initializes the hidl driver & HidlManager instance and
-	 * then forwards all the notifcations from the supplicant core to the
-	 * HidlManager.
-	 */
-	struct wpas_hidl_priv;
-	struct wpa_global;
-
-	struct wpas_hidl_priv *wpas_hidl_init(struct wpa_global *global);
-	void wpas_hidl_deinit(struct wpas_hidl_priv *priv);
-
-#ifdef CONFIG_CTRL_IFACE_HIDL
-	int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s);
-	int wpas_hidl_unregister_interface(struct wpa_supplicant *wpa_s);
-	int wpas_hidl_register_network(
-	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
-	int wpas_hidl_unregister_network(
-	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
-	int wpas_hidl_notify_state_changed(struct wpa_supplicant *wpa_s);
-	int wpas_hidl_notify_network_request(
-	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
-	    enum wpa_ctrl_req_type rtype, const char *default_txt);
-	void wpas_hidl_notify_anqp_query_done(
-	    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
-	    const struct wpa_bss_anqp *anqp);
-	void wpas_hidl_notify_hs20_icon_query_done(
-	    struct wpa_supplicant *wpa_s, const u8 *bssid,
-	    const char *file_name, const u8 *image, u32 image_length);
-	void wpas_hidl_notify_hs20_rx_subscription_remediation(
-	    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
-	void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
-	    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
-	    const char *url);
-	void wpas_hidl_notify_hs20_rx_terms_and_conditions_acceptance(
-			struct wpa_supplicant *wpa_s, const char *url);
-	void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s, const u8 *bssid,
-	    u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len);
-	void wpas_hidl_notify_auth_timeout(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_wps_event_fail(
-	    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
-	    uint16_t config_error, uint16_t error_indication);
-	void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_wps_event_pbc_overlap(
-	    struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_p2p_device_found(
-	    struct wpa_supplicant *wpa_s, const u8 *addr,
-	    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-	    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
-	    u8 peer_wfd_r2_device_info_len);
-	void wpas_hidl_notify_p2p_device_lost(
-	    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
-	void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_p2p_go_neg_req(
-	    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
-	    u8 go_intent);
-	void wpas_hidl_notify_p2p_go_neg_completed(
-	    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
-	void wpas_hidl_notify_p2p_group_formation_failure(
-	    struct wpa_supplicant *wpa_s, const char *reason);
-	void wpas_hidl_notify_p2p_group_started(
-	    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid,
-	    int persistent, int client);
-	void wpas_hidl_notify_p2p_group_removed(
-	    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid,
-	    const char *role);
-	void wpas_hidl_notify_p2p_invitation_received(
-	    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
-	    const u8 *bssid, int id, int op_freq);
-	void wpas_hidl_notify_p2p_invitation_result(
-	    struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
-	void wpas_hidl_notify_p2p_provision_discovery(
-	    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
-	    enum p2p_prov_disc_status status, u16 config_methods,
-	    unsigned int generated_pin);
-	void wpas_hidl_notify_p2p_sd_response(
-	    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
-	    const u8 *tlvs, size_t tlvs_len);
-	void wpas_hidl_notify_ap_sta_authorized(
-	    struct wpa_supplicant *wpa_s, const u8 *sta,
-	    const u8 *p2p_dev_addr);
-	void wpas_hidl_notify_ap_sta_deauthorized(
-	    struct wpa_supplicant *wpa_s, const u8 *sta,
-	    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(struct wpa_supplicant *wpa_s,
-		    struct wpa_ssid *ssid);
-	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);
-	void wpas_hidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_dpp_conn_status(struct wpa_supplicant *wpa_s,
-	    enum dpp_status_error status, const char *ssid,
-	    const char *channel_list, unsigned short band_list[], int size);
-	void wpas_hidl_notify_pmk_cache_added(
-	    struct wpa_supplicant *wpas, struct rsn_pmksa_cache_entry *pmksa_entry);
-	void wpas_hidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s);
-	void wpas_hidl_notify_transition_disable(
-	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, u8 bitmap);
-	void wpas_hidl_notify_network_not_found(struct wpa_supplicant *wpa_s);
-#else   // CONFIG_CTRL_IFACE_HIDL
-static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
-{
-	return 0;
-}
-static inline int wpas_hidl_unregister_interface(struct wpa_supplicant *wpa_s)
-{
-	return 0;
-}
-static inline int wpas_hidl_register_network(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
-{
-	return 0;
-}
-static inline int wpas_hidl_unregister_network(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
-{
-	return 0;
-}
-static inline int wpas_hidl_notify_state_changed(struct wpa_supplicant *wpa_s)
-{
-	return 0;
-}
-static inline int wpas_hidl_notify_network_request(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
-    enum wpa_ctrl_req_type rtype, const char *default_txt)
-{
-	return 0;
-}
-static void wpas_hidl_notify_anqp_query_done(
-    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
-    const struct wpa_bss_anqp *anqp)
-{}
-static void wpas_hidl_notify_hs20_icon_query_done(
-    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
-    const u8 *image, u32 image_length)
-{}
-static void wpas_hidl_notify_hs20_rx_subscription_remediation(
-    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
-{}
-static void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
-    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
-{}
-void wpas_hidl_notify_hs20_rx_terms_and_conditions_acceptance(
-		struct wpa_supplicant *wpa_s, const char *url)
-{}
-static void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s) {}
-static void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s, const u8 *bssid,
-    u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len) {}
-static void wpas_hidl_notify_auth_timeout(struct wpa_supplicant *wpa_s) {}
-static void wpas_hidl_notify_wps_event_fail(
-    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
-    uint16_t error_indication)
-{}
-static void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s) {}
-static void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s) {}
-static void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
-{}
-static void wpas_hidl_notify_p2p_device_found(
-    struct wpa_supplicant *wpa_s, const u8 *addr,
-    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-    u8 peer_wfd_device_info_len);
-{}
-static void wpas_hidl_notify_p2p_device_lost(
-    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
-{}
-static void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s) {}
-static void wpas_hidl_notify_p2p_go_neg_req(
-    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
-    u8 go_intent)
-{}
-static void wpas_hidl_notify_p2p_go_neg_completed(
-    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
-{}
-static void wpas_hidl_notify_p2p_group_formation_failure(
-    struct wpa_supplicant *wpa_s, const char *reason)
-{}
-static void wpas_hidl_notify_p2p_group_started(
-    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
-    int client)
-{}
-static void wpas_hidl_notify_p2p_group_removed(
-    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
-{}
-static void wpas_hidl_notify_p2p_invitation_received(
-    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
-    const u8 *bssid, int id, int op_freq)
-{}
-static void wpas_hidl_notify_p2p_invitation_result(
-    struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
-{}
-static void wpas_hidl_notify_p2p_provision_discovery(
-    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
-    enum p2p_prov_disc_status status, u16 config_methods,
-    unsigned int generated_pin)
-{}
-static void wpas_hidl_notify_p2p_sd_response(
-    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
-    const u8 *tlvs, size_t tlvs_len)
-{}
-static void wpas_hidl_notify_ap_sta_authorized(
-    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
-{}
-static void wpas_hidl_notify_ap_sta_deauthorized(
-    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
-{}
-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)
-{}
-void wpas_hidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s)
-{}
-void wpas_hidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s)
-{}
-void wpas_hidl_notify_dpp_config_applied(struct wpa_supplicant *wpa_s)
-{}
-void wpas_hidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s)
-{}
-static void wpas_hidl_notify_pmk_cache_added(struct wpa_supplicant *wpas,
-					     struct rsn_pmksa_cache_entry *pmksa_entry)
-{}
-void wpas_hidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
-{}
-static void wpas_hidl_notify_transition_disable(struct wpa_supplicant *wpa_s,
-					    struct wpa_ssid *ssid,
-					    u8 bitmap)
-{}
-static void wpas_hidl_notify_network_not_found(struct wpa_supplicant *wpa_s)
-{}
-}
-#endif  // CONFIG_CTRL_IFACE_HIDL
-
-#ifdef _cplusplus
-}
-#endif  // _cplusplus
-
-#endif  // WPA_SUPPLICANT_HIDL_HIDL_H
diff --git a/wpa_supplicant/hidl/1.4/hidl_constants.h b/wpa_supplicant/hidl/1.4/hidl_constants.h
deleted file mode 100644
index 988a590..0000000
--- a/wpa_supplicant/hidl/1.4/hidl_constants.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_HIDL_CONSTANTS_H
-#define WPA_SUPPLICANT_HIDL_HIDL_CONSTANTS_H
-
-namespace wpa_supplicant_hidl {
-namespace hidl_constants {
-
-extern const char kServiceName[];
-
-} /* namespace hidl_constants */
-} /* namespace wpa_supplicant_hidl */
-
-#endif /* WPA_SUPPLICANT_HIDL_HIDL_CONSTANTS_H */
diff --git a/wpa_supplicant/hidl/1.4/hidl_i.h b/wpa_supplicant/hidl/1.4/hidl_i.h
deleted file mode 100644
index 9cff40d..0000000
--- a/wpa_supplicant/hidl/1.4/hidl_i.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 HIDL_I_H
-#define HIDL_I_H
-
-#ifdef _cplusplus
-extern "C"
-{
-#endif  // _cplusplus
-
-	struct wpas_hidl_priv
-	{
-		int hidl_fd;
-		struct wpa_global *global;
-		void *hidl_manager;
-	};
-
-#ifdef _cplusplus
-}
-#endif  // _cplusplus
-
-#endif  // HIDL_I_H
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
deleted file mode 100644
index 0a5fceb..0000000
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ /dev/null
@@ -1,2496 +0,0 @@
-/*
- * 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.
- */
-
-#include <algorithm>
-#include <iostream>
-#include <regex>
-
-#include "hidl_manager.h"
-#include "misc_utils.h"
-
-extern "C" {
-#include "scan.h"
-#include "src/eap_common/eap_sim_common.h"
-#include "list.h"
-}
-
-namespace {
-using android::hardware::hidl_array;
-
-constexpr uint8_t kWfdDeviceInfoLen = 6;
-constexpr uint8_t kWfdR2DeviceInfoLen = 2;
-// GSM-AUTH:<RAND1>:<RAND2>[:<RAND3>]
-constexpr char kGsmAuthRegex2[] = "GSM-AUTH:([0-9a-f]+):([0-9a-f]+)";
-constexpr char kGsmAuthRegex3[] =
-    "GSM-AUTH:([0-9a-f]+):([0-9a-f]+):([0-9a-f]+)";
-// UMTS-AUTH:<RAND>:<AUTN>
-constexpr char kUmtsAuthRegex[] = "UMTS-AUTH:([0-9a-f]+):([0-9a-f]+)";
-constexpr size_t kGsmRandLenBytes = GSM_RAND_LEN;
-constexpr size_t kUmtsRandLenBytes = EAP_AKA_RAND_LEN;
-constexpr size_t kUmtsAutnLenBytes = EAP_AKA_AUTN_LEN;
-constexpr u8 kZeroBssid[6] = {0, 0, 0, 0, 0, 0};
-
-/**
- * Check if the provided |wpa_supplicant| structure represents a P2P iface or
- * not.
- */
-constexpr bool isP2pIface(const struct wpa_supplicant *wpa_s)
-{
-	return (wpa_s->global->p2p_init_wpa_s == wpa_s);
-}
-
-/**
- * Creates a unique key for the network using the provided |ifname| and
- * |network_id| to be used in the internal map of |ISupplicantNetwork| objects.
- * This is of the form |ifname|_|network_id|. For ex: "wlan0_1".
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- */
-const std::string getNetworkObjectMapKey(
-    const std::string &ifname, int network_id)
-{
-	return ifname + "_" + std::to_string(network_id);
-}
-
-/**
- * Add callback to the corresponding list after linking to death on the
- * corresponding hidl object reference.
- */
-template <class CallbackType>
-int registerForDeathAndAddCallbackHidlObjectToList(
-    const android::sp<DeathNotifier> &death_notifier,
-    const android::sp<CallbackType> &callback,
-    std::vector<android::sp<CallbackType>> &callback_list)
-{
-	if (!callback->linkToDeath(death_notifier, 0)) {
-		wpa_printf(
-		    MSG_ERROR,
-		    "Error registering for death notification for "
-		    "supplicant callback object");
-		return 1;
-	}
-	callback_list.push_back(callback);
-	return 0;
-}
-
-template <class ObjectType>
-int addHidlObjectToMap(
-    const std::string &key, const android::sp<ObjectType> object,
-    std::map<const std::string, android::sp<ObjectType>> &object_map)
-{
-	// Return failure if we already have an object for that |key|.
-	if (object_map.find(key) != object_map.end())
-		return 1;
-	object_map[key] = object;
-	if (!object_map[key].get())
-		return 1;
-	return 0;
-}
-
-template <class ObjectType>
-int removeHidlObjectFromMap(
-    const std::string &key,
-    std::map<const std::string, android::sp<ObjectType>> &object_map)
-{
-	// Return failure if we dont have an object for that |key|.
-	const auto &object_iter = object_map.find(key);
-	if (object_iter == object_map.end())
-		return 1;
-	object_iter->second->invalidate();
-	object_map.erase(object_iter);
-	return 0;
-}
-
-template <class CallbackType>
-int addIfaceCallbackHidlObjectToMap(
-    const android::sp<DeathNotifier> &death_notifier,
-    const std::string &ifname, const android::sp<CallbackType> &callback,
-    std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&callbacks_map)
-{
-	if (ifname.empty())
-		return 1;
-
-	auto iface_callback_map_iter = callbacks_map.find(ifname);
-	if (iface_callback_map_iter == callbacks_map.end())
-		return 1;
-	auto &iface_callback_list = iface_callback_map_iter->second;
-
-	// Register for death notification before we add it to our list.
-	return registerForDeathAndAddCallbackHidlObjectToList<CallbackType>(
-	    death_notifier, callback, iface_callback_list);
-}
-
-template <class CallbackType>
-int addNetworkCallbackHidlObjectToMap(
-    const android::sp<DeathNotifier> &death_notifier,
-    const std::string &ifname, int network_id,
-    const android::sp<CallbackType> &callback,
-    std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&callbacks_map)
-{
-	if (ifname.empty() || network_id < 0)
-		return 1;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(ifname, network_id);
-	auto network_callback_map_iter = callbacks_map.find(network_key);
-	if (network_callback_map_iter == callbacks_map.end())
-		return 1;
-	auto &network_callback_list = network_callback_map_iter->second;
-
-	// Register for death notification before we add it to our list.
-	return registerForDeathAndAddCallbackHidlObjectToList<CallbackType>(
-	    death_notifier, callback, network_callback_list);
-}
-
-template <class CallbackType>
-int removeAllIfaceCallbackHidlObjectsFromMap(
-    const android::sp<DeathNotifier> &death_notifier,
-    const std::string &ifname,
-    std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&callbacks_map)
-{
-	auto iface_callback_map_iter = callbacks_map.find(ifname);
-	if (iface_callback_map_iter == callbacks_map.end())
-		return 1;
-	const auto &iface_callback_list = iface_callback_map_iter->second;
-	for (const auto &callback : iface_callback_list) {
-		if (!callback->unlinkToDeath(death_notifier)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Error deregistering for death notification for "
-			    "iface callback object");
-		}
-	}
-	callbacks_map.erase(iface_callback_map_iter);
-	return 0;
-}
-
-template <class CallbackType>
-int removeAllNetworkCallbackHidlObjectsFromMap(
-    const android::sp<DeathNotifier> &death_notifier,
-    const std::string &network_key,
-    std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&callbacks_map)
-{
-	auto network_callback_map_iter = callbacks_map.find(network_key);
-	if (network_callback_map_iter == callbacks_map.end())
-		return 1;
-	const auto &network_callback_list = network_callback_map_iter->second;
-	for (const auto &callback : network_callback_list) {
-		if (!callback->unlinkToDeath(death_notifier)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Error deregistering for death "
-			    "notification for "
-			    "network callback object");
-		}
-	}
-	callbacks_map.erase(network_callback_map_iter);
-	return 0;
-}
-
-template <class CallbackType>
-void removeIfaceCallbackHidlObjectFromMap(
-    const std::string &ifname, const android::sp<CallbackType> &callback,
-    std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&callbacks_map)
-{
-	if (ifname.empty())
-		return;
-
-	auto iface_callback_map_iter = callbacks_map.find(ifname);
-	if (iface_callback_map_iter == callbacks_map.end())
-		return;
-
-	auto &iface_callback_list = iface_callback_map_iter->second;
-	iface_callback_list.erase(
-	    std::remove(
-		iface_callback_list.begin(), iface_callback_list.end(),
-		callback),
-	    iface_callback_list.end());
-}
-
-template <class CallbackType>
-void removeNetworkCallbackHidlObjectFromMap(
-    const std::string &ifname, int network_id,
-    const android::sp<CallbackType> &callback,
-    std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&callbacks_map)
-{
-	if (ifname.empty() || network_id < 0)
-		return;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(ifname, network_id);
-
-	auto network_callback_map_iter = callbacks_map.find(network_key);
-	if (network_callback_map_iter == callbacks_map.end())
-		return;
-
-	auto &network_callback_list = network_callback_map_iter->second;
-	network_callback_list.erase(
-	    std::remove(
-		network_callback_list.begin(), network_callback_list.end(),
-		callback),
-	    network_callback_list.end());
-}
-
-template <class CallbackType>
-void callWithEachIfaceCallback(
-    const std::string &ifname,
-    const std::function<
-	android::hardware::Return<void>(android::sp<CallbackType>)> &method,
-    const std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&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) {
-		if (!method(callback).isOk()) {
-			wpa_printf(
-			    MSG_ERROR, "Failed to invoke HIDL iface callback");
-		}
-	}
-}
-
-template <class CallbackTypeBase, class CallbackTypeDerived>
-void callWithEachIfaceCallbackDerived(
-    const std::string &ifname,
-    const std::function<
-	android::hardware::Return<void>(android::sp<CallbackTypeDerived>)> &method,
-    const std::map<
-	const std::string, std::vector<android::sp<CallbackTypeBase>>>
-	&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<CallbackTypeDerived> callback_derived =
-		    CallbackTypeDerived::castFrom(callback);
-		if (callback_derived == nullptr)
-			continue;
-
-		if (!method(callback_derived).isOk()) {
-			wpa_printf(
-			    MSG_ERROR, "Failed to invoke HIDL iface callback");
-		}
-	}
-}
-
-template <class CallbackType>
-void callWithEachNetworkCallback(
-    const std::string &ifname, int network_id,
-    const std::function<
-	android::hardware::Return<void>(android::sp<CallbackType>)> &method,
-    const std::map<const std::string, std::vector<android::sp<CallbackType>>>
-	&callbacks_map)
-{
-	if (ifname.empty() || network_id < 0)
-		return;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(ifname, network_id);
-	auto network_callback_map_iter = callbacks_map.find(network_key);
-	if (network_callback_map_iter == callbacks_map.end())
-		return;
-	const auto &network_callback_list = network_callback_map_iter->second;
-	for (const auto &callback : network_callback_list) {
-		if (!method(callback).isOk()) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to invoke HIDL network callback");
-		}
-	}
-}
-
-template <class CallbackTypeBase, class CallbackTypeDerived>
-void callWithEachNetworkCallbackDerived(
-    const std::string &ifname, int network_id,
-    const std::function<
-	android::hardware::Return<void>(android::sp<CallbackTypeDerived>)> &method,
-    const std::map<
-	const std::string, std::vector<android::sp<CallbackTypeBase>>>
-	&callbacks_map)
-{
-	if (ifname.empty())
-		return;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(ifname, network_id);
-	auto network_callback_map_iter = callbacks_map.find(network_key);
-	if (network_callback_map_iter == callbacks_map.end())
-		return;
-	const auto &network_callback_list = network_callback_map_iter->second;
-	for (const auto &callback : network_callback_list) {
-		android::sp<CallbackTypeDerived> callback_derived =
-		    CallbackTypeDerived::castFrom(callback);
-		if (callback_derived == nullptr)
-			continue;
-		if (!method(callback_derived).isOk()) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to invoke HIDL network callback");
-		}
-	}
-}
-
-int parseGsmAuthNetworkRequest(
-    const std::string &params_str,
-    std::vector<hidl_array<uint8_t, kGsmRandLenBytes>> *out_rands)
-{
-	std::smatch matches;
-	std::regex params_gsm_regex2(kGsmAuthRegex2);
-	std::regex params_gsm_regex3(kGsmAuthRegex3);
-	if (!std::regex_match(params_str, matches, params_gsm_regex3) &&
-	    !std::regex_match(params_str, matches, params_gsm_regex2)) {
-		return 1;
-	}
-	for (uint32_t i = 1; i < matches.size(); i++) {
-		hidl_array<uint8_t, kGsmRandLenBytes> rand;
-		const auto &match = matches[i];
-		WPA_ASSERT(match.size() >= 2 * rand.size());
-		if (hexstr2bin(match.str().c_str(), rand.data(), rand.size())) {
-			wpa_printf(
-			    MSG_ERROR, "Failed to parse GSM auth params");
-			return 1;
-		}
-		out_rands->push_back(rand);
-	}
-	return 0;
-}
-
-int parseUmtsAuthNetworkRequest(
-    const std::string &params_str,
-    hidl_array<uint8_t, kUmtsRandLenBytes> *out_rand,
-    hidl_array<uint8_t, kUmtsAutnLenBytes> *out_autn)
-{
-	std::smatch matches;
-	std::regex params_umts_regex(kUmtsAuthRegex);
-	if (!std::regex_match(params_str, matches, params_umts_regex)) {
-		return 1;
-	}
-	WPA_ASSERT(matches[1].size() >= 2 * out_rand->size());
-	if (hexstr2bin(
-		matches[1].str().c_str(), out_rand->data(), out_rand->size())) {
-		wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
-		return 1;
-	}
-	WPA_ASSERT(matches[2].size() >= 2 * out_autn->size());
-	if (hexstr2bin(
-		matches[2].str().c_str(), out_autn->data(), out_autn->size())) {
-		wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
-		return 1;
-	}
-	return 0;
-}
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using V1_0::ISupplicantStaIfaceCallback;
-using V1_0::ISupplicantP2pIfaceCallback;
-using ISupplicantP2pIfaceCallbackV1_4 = V1_4::ISupplicantP2pIfaceCallback;
-
-HidlManager *HidlManager::instance_ = NULL;
-
-HidlManager *HidlManager::getInstance()
-{
-	if (!instance_)
-		instance_ = new HidlManager();
-	return instance_;
-}
-
-void HidlManager::destroyInstance()
-{
-	if (instance_)
-		delete instance_;
-	instance_ = NULL;
-}
-
-int HidlManager::registerHidlService(struct wpa_global *global)
-{
-	// Create the main hidl service object and register it.
-	supplicant_object_ = new Supplicant(global);
-	wpa_global_ = global;
-	death_notifier_ = sp<DeathNotifier>::make(global);
-	if (supplicant_object_->registerAsService() != android::NO_ERROR) {
-		return 1;
-	}
-	return 0;
-}
-
-/**
- * Register an interface to hidl manager.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::registerInterface(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return 1;
-
-	if (isP2pIface(wpa_s)) {
-		if (addHidlObjectToMap<P2pIface>(
-			wpa_s->ifname,
-			new P2pIface(wpa_s->global, wpa_s->ifname),
-			p2p_iface_object_map_)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to register P2P interface with HIDL "
-			    "control: %s",
-			    wpa_s->ifname);
-			return 1;
-		}
-		p2p_iface_callbacks_map_[wpa_s->ifname] =
-		    std::vector<android::sp<ISupplicantP2pIfaceCallback>>();
-	} else {
-		if (addHidlObjectToMap<StaIface>(
-			wpa_s->ifname,
-			new StaIface(wpa_s->global, wpa_s->ifname),
-			sta_iface_object_map_)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to register STA interface with HIDL "
-			    "control: %s",
-			    wpa_s->ifname);
-			return 1;
-		}
-		sta_iface_callbacks_map_[wpa_s->ifname] =
-		    std::vector<android::sp<ISupplicantStaIfaceCallback>>();
-		// Turn on Android specific customizations for STA interfaces
-		// here!
-		//
-		// Turn on scan mac randomization only if driver supports.
-		if (wpa_s->mac_addr_rand_supported & MAC_ADDR_RAND_SCAN) {
-			if (wpas_mac_addr_rand_scan_set(
-				wpa_s, MAC_ADDR_RAND_SCAN, nullptr, nullptr)) {
-				wpa_printf(
-				    MSG_ERROR,
-				    "Failed to enable scan mac randomization");
-			}
-		}
-
-		// Enable randomized source MAC address for GAS/ANQP
-		// Set the lifetime to 0, guarantees a unique address for each GAS
-		// session
-		wpa_s->conf->gas_rand_mac_addr = 1;
-		wpa_s->conf->gas_rand_addr_lifetime = 0;
-	}
-
-	// Invoke the |onInterfaceCreated| method on all registered callbacks.
-	callWithEachSupplicantCallback(std::bind(
-	    &ISupplicantCallback::onInterfaceCreated, std::placeholders::_1,
-	    wpa_s->ifname));
-	return 0;
-}
-
-/**
- * Unregister an interface from hidl manager.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::unregisterInterface(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return 1;
-
-	// Check if this interface is present in P2P map first, else check in
-	// STA map.
-	// Note: We can't use isP2pIface() here because interface
-	// pointers (wpa_s->global->p2p_init_wpa_s == wpa_s) used by the helper
-	// function is cleared by the core before notifying the HIDL interface.
-	bool success =
-	    !removeHidlObjectFromMap(wpa_s->ifname, p2p_iface_object_map_);
-	if (success) {  // assumed to be P2P
-		success = !removeAllIfaceCallbackHidlObjectsFromMap(
-		    death_notifier_, wpa_s->ifname, p2p_iface_callbacks_map_);
-	} else {  // assumed to be STA
-		success = !removeHidlObjectFromMap(
-		    wpa_s->ifname, sta_iface_object_map_);
-		if (success) {
-			success = !removeAllIfaceCallbackHidlObjectsFromMap(
-			    death_notifier_, wpa_s->ifname, sta_iface_callbacks_map_);
-		}
-	}
-	if (!success) {
-		wpa_printf(
-		    MSG_ERROR,
-		    "Failed to unregister interface with HIDL "
-		    "control: %s",
-		    wpa_s->ifname);
-		return 1;
-	}
-
-	// Invoke the |onInterfaceRemoved| method on all registered callbacks.
-	callWithEachSupplicantCallback(std::bind(
-	    &ISupplicantCallback::onInterfaceRemoved, std::placeholders::_1,
-	    wpa_s->ifname));
-	return 0;
-}
-
-/**
- * Register a network to hidl manager.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the network is added.
- * @param ssid |wpa_ssid| struct corresponding to the network being added.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::registerNetwork(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
-{
-	if (!wpa_s || !ssid)
-		return 1;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
-
-	if (isP2pIface(wpa_s)) {
-		if (addHidlObjectToMap<P2pNetwork>(
-			network_key,
-			new P2pNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
-			p2p_network_object_map_)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to register P2P network with HIDL "
-			    "control: %d",
-			    ssid->id);
-			return 1;
-		}
-		p2p_network_callbacks_map_[network_key] =
-		    std::vector<android::sp<ISupplicantP2pNetworkCallback>>();
-		// Invoke the |onNetworkAdded| method on all registered
-		// callbacks.
-		callWithEachP2pIfaceCallback(
-		    wpa_s->ifname,
-		    std::bind(
-			&ISupplicantP2pIfaceCallback::onNetworkAdded,
-			std::placeholders::_1, ssid->id));
-	} else {
-		if (addHidlObjectToMap<StaNetwork>(
-			network_key,
-			new StaNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
-			sta_network_object_map_)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to register STA network with HIDL "
-			    "control: %d",
-			    ssid->id);
-			return 1;
-		}
-		sta_network_callbacks_map_[network_key] =
-		    std::vector<android::sp<ISupplicantStaNetworkCallback>>();
-		// Invoke the |onNetworkAdded| method on all registered
-		// callbacks.
-		callWithEachStaIfaceCallback(
-		    wpa_s->ifname,
-		    std::bind(
-			&ISupplicantStaIfaceCallback::onNetworkAdded,
-			std::placeholders::_1, ssid->id));
-	}
-	return 0;
-}
-
-/**
- * Unregister a network from hidl manager.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the network is added.
- * @param ssid |wpa_ssid| struct corresponding to the network being added.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::unregisterNetwork(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
-{
-	if (!wpa_s || !ssid)
-		return 1;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
-
-	if (isP2pIface(wpa_s)) {
-		if (removeHidlObjectFromMap(
-			network_key, p2p_network_object_map_)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to unregister P2P network with HIDL "
-			    "control: %d",
-			    ssid->id);
-			return 1;
-		}
-		if (removeAllNetworkCallbackHidlObjectsFromMap(
-			death_notifier_, network_key, p2p_network_callbacks_map_))
-			return 1;
-
-		// Invoke the |onNetworkRemoved| method on all registered
-		// callbacks.
-		callWithEachP2pIfaceCallback(
-		    wpa_s->ifname,
-		    std::bind(
-			&ISupplicantP2pIfaceCallback::onNetworkRemoved,
-			std::placeholders::_1, ssid->id));
-	} else {
-		if (removeHidlObjectFromMap(
-			network_key, sta_network_object_map_)) {
-			wpa_printf(
-			    MSG_ERROR,
-			    "Failed to unregister STA network with HIDL "
-			    "control: %d",
-			    ssid->id);
-			return 1;
-		}
-		if (removeAllNetworkCallbackHidlObjectsFromMap(
-			death_notifier_, network_key, sta_network_callbacks_map_))
-			return 1;
-
-		// Invoke the |onNetworkRemoved| method on all registered
-		// callbacks.
-		callWithEachStaIfaceCallback(
-		    wpa_s->ifname,
-		    std::bind(
-			&ISupplicantStaIfaceCallback::onNetworkRemoved,
-			std::placeholders::_1, ssid->id));
-	}
-	return 0;
-}
-
-/**
- * Notify all listeners about any state changes on a particular interface.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the state change event occured.
- */
-int HidlManager::notifyStateChange(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return 1;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return 1;
-
-	// Invoke the |onStateChanged| method on all registered callbacks.
-	uint32_t hidl_network_id = UINT32_MAX;
-	std::vector<uint8_t> hidl_ssid;
-	if (wpa_s->current_ssid) {
-		hidl_network_id = wpa_s->current_ssid->id;
-		hidl_ssid.assign(
-		    wpa_s->current_ssid->ssid,
-		    wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
-	}
-	uint8_t *bssid;
-	// wpa_supplicant sets the |pending_bssid| field when it starts a
-	// connection. Only after association state does it update the |bssid|
-	// field. So, in the HIDL callback send the appropriate bssid.
-	if (wpa_s->wpa_state <= WPA_ASSOCIATED) {
-		bssid = wpa_s->pending_bssid;
-	} else {
-		bssid = wpa_s->bssid;
-	}
-	bool fils_hlp_sent =
-		(wpa_auth_alg_fils(wpa_s->auth_alg) &&
-		 !dl_list_empty(&wpa_s->fils_hlp_req) &&
-		 (wpa_s->wpa_state == WPA_COMPLETED)) ? true : false;
-
-	// Invoke the |onStateChanged_1_3| method on all registered callbacks.
-	const std::function<
-		Return<void>(android::sp<V1_3::ISupplicantStaIfaceCallback>)>
-		func = std::bind(
-			&V1_3::ISupplicantStaIfaceCallback::onStateChanged_1_3,
-			std::placeholders::_1,
-			static_cast<ISupplicantStaIfaceCallback::State>(
-				wpa_s->wpa_state),
-				bssid, hidl_network_id, hidl_ssid,
-				fils_hlp_sent);
-	callWithEachStaIfaceCallbackDerived(wpa_s->ifname, func);
-	return 0;
-}
-
-/**
- * Notify all listeners about a request on a particular network.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the network is present.
- * @param ssid |wpa_ssid| struct corresponding to the network.
- * @param type type of request.
- * @param param addition params associated with the request.
- */
-int HidlManager::notifyNetworkRequest(
-    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
-    const char *param)
-{
-	if (!wpa_s || !ssid)
-		return 1;
-
-	const std::string network_key =
-	    getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
-	if (sta_network_object_map_.find(network_key) ==
-	    sta_network_object_map_.end())
-		return 1;
-
-	if (type == WPA_CTRL_REQ_EAP_IDENTITY) {
-		callWithEachStaNetworkCallback(
-		    wpa_s->ifname, ssid->id,
-		    std::bind(
-			&ISupplicantStaNetworkCallback::
-			    onNetworkEapIdentityRequest,
-			std::placeholders::_1));
-		return 0;
-	}
-	if (type == WPA_CTRL_REQ_SIM) {
-		std::vector<hidl_array<uint8_t, 16>> gsm_rands;
-		hidl_array<uint8_t, 16> umts_rand;
-		hidl_array<uint8_t, 16> umts_autn;
-		if (!parseGsmAuthNetworkRequest(param, &gsm_rands)) {
-			ISupplicantStaNetworkCallback::
-			    NetworkRequestEapSimGsmAuthParams hidl_params;
-			hidl_params.rands = gsm_rands;
-			callWithEachStaNetworkCallback(
-			    wpa_s->ifname, ssid->id,
-			    std::bind(
-				&ISupplicantStaNetworkCallback::
-				    onNetworkEapSimGsmAuthRequest,
-				std::placeholders::_1, hidl_params));
-			return 0;
-		}
-		if (!parseUmtsAuthNetworkRequest(
-			param, &umts_rand, &umts_autn)) {
-			ISupplicantStaNetworkCallback::
-			    NetworkRequestEapSimUmtsAuthParams hidl_params;
-			hidl_params.rand = umts_rand;
-			hidl_params.autn = umts_autn;
-			callWithEachStaNetworkCallback(
-			    wpa_s->ifname, ssid->id,
-			    std::bind(
-				&ISupplicantStaNetworkCallback::
-				    onNetworkEapSimUmtsAuthRequest,
-				std::placeholders::_1, hidl_params));
-			return 0;
-		}
-	}
-	return 1;
-}
-
-/**
- * Notify all listeners about the end of an ANQP query.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
- * @param bssid BSSID of the access point.
- * @param result Result of the operation ("SUCCESS" or "FAILURE").
- * @param anqp |wpa_bss_anqp| ANQP data fetched.
- */
-void HidlManager::notifyAnqpQueryDone(
-    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
-    const struct wpa_bss_anqp *anqp)
-{
-	if (!wpa_s || !bssid || !result || !anqp)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	V1_4::ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
-	ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data;
-	if (std::string(result) == "SUCCESS") {
-		hidl_anqp_data.V1_0.venueName =
-		    misc_utils::convertWpaBufToVector(anqp->venue_name);
-		hidl_anqp_data.V1_0.roamingConsortium =
-		    misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
-		hidl_anqp_data.V1_0.ipAddrTypeAvailability =
-		    misc_utils::convertWpaBufToVector(
-			anqp->ip_addr_type_availability);
-		hidl_anqp_data.V1_0.naiRealm =
-		    misc_utils::convertWpaBufToVector(anqp->nai_realm);
-		hidl_anqp_data.V1_0.anqp3gppCellularNetwork =
-		    misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
-		hidl_anqp_data.V1_0.domainName =
-		    misc_utils::convertWpaBufToVector(anqp->domain_name);
-
-		struct wpa_bss_anqp_elem *elem;
-		dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
-				 list) {
-			if (elem->infoid == ANQP_VENUE_URL && elem->protected_response) {
-				hidl_anqp_data.venueUrl =
-						    misc_utils::convertWpaBufToVector(elem->payload);
-				break;
-			}
-		}
-
-		hidl_hs20_anqp_data.operatorFriendlyName =
-		    misc_utils::convertWpaBufToVector(
-			anqp->hs20_operator_friendly_name);
-		hidl_hs20_anqp_data.wanMetrics =
-		    misc_utils::convertWpaBufToVector(anqp->hs20_wan_metrics);
-		hidl_hs20_anqp_data.connectionCapability =
-		    misc_utils::convertWpaBufToVector(
-			anqp->hs20_connection_capability);
-		hidl_hs20_anqp_data.osuProvidersList =
-		    misc_utils::convertWpaBufToVector(
-			anqp->hs20_osu_providers_list);
-	}
-
-	callWithEachStaIfaceCallback_1_4(
-	    wpa_s->ifname, std::bind(
-			       &V1_4::ISupplicantStaIfaceCallback::onAnqpQueryDone_1_4,
-			       std::placeholders::_1, bssid, hidl_anqp_data,
-			       hidl_hs20_anqp_data));
-}
-
-/**
- * Notify all listeners about the end of an HS20 icon query.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
- * @param bssid BSSID of the access point.
- * @param file_name Name of the icon file.
- * @param image Raw bytes of the icon file.
- * @param image_length Size of the the icon file.
- */
-void HidlManager::notifyHs20IconQueryDone(
-    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
-    const u8 *image, u32 image_length)
-{
-	if (!wpa_s || !bssid || !file_name || !image)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onHs20IconQueryDone,
-		std::placeholders::_1, bssid, file_name,
-		std::vector<uint8_t>(image, image + image_length)));
-}
-
-/**
- * Notify all listeners about the reception of HS20 subscription
- * remediation notification from the server.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
- * @param url URL of the server.
- * @param osu_method OSU method (OMA_DM or SOAP_XML_SPP).
- */
-void HidlManager::notifyHs20RxSubscriptionRemediation(
-    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
-{
-	if (!wpa_s || !url)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	ISupplicantStaIfaceCallback::OsuMethod hidl_osu_method = {};
-	if (osu_method & 0x1) {
-		hidl_osu_method =
-		    ISupplicantStaIfaceCallback::OsuMethod::OMA_DM;
-	} else if (osu_method & 0x2) {
-		hidl_osu_method =
-		    ISupplicantStaIfaceCallback::OsuMethod::SOAP_XML_SPP;
-	}
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onHs20SubscriptionRemediation,
-		std::placeholders::_1, wpa_s->bssid, hidl_osu_method, url));
-}
-
-/**
- * Notify all listeners about the reception of HS20 imminent deauth
- * notification from the server.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
- * @param code Deauth reason code sent from server.
- * @param reauth_delay Reauthentication delay in seconds sent from server.
- * @param url URL of the server containing the reason text.
- */
-void HidlManager::notifyHs20RxDeauthImminentNotice(
-    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
-{
-	if (!wpa_s)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onHs20DeauthImminentNotice,
-		std::placeholders::_1, wpa_s->bssid, code, reauth_delay, url));
-}
-
-/**
- * Notify all listeners about the reception of HS20 terms and conditions
- * acceptance notification from the server.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
- * @param url URL of the T&C server.
- */
-void HidlManager::notifyHs20RxTermsAndConditionsAcceptance(
-    struct wpa_supplicant *wpa_s, const char *url)
-{
-	if (!wpa_s || !url)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname)
-			== sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback_1_4(wpa_s->ifname,
-			std::bind(
-					&V1_4::ISupplicantStaIfaceCallback
-					::onHs20TermsAndConditionsAcceptanceRequestedNotification,
-					std::placeholders::_1, wpa_s->bssid, url));
-}
-
-/**
- * Notify all listeners about the reason code for disconnection from the
- * currently connected network.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the network is present.
- */
-void HidlManager::notifyDisconnectReason(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	const u8 *bssid = wpa_s->bssid;
-	if (is_zero_ether_addr(bssid)) {
-		bssid = wpa_s->pending_bssid;
-	}
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onDisconnected,
-		std::placeholders::_1, bssid, wpa_s->disconnect_reason < 0,
-		static_cast<ISupplicantStaIfaceCallback::ReasonCode>(
-		    abs(wpa_s->disconnect_reason))));
-}
-
-/**
- * Notify all listeners about association reject from the access point to which
- * we are attempting to connect.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the network is present.
- * @param bssid bssid of AP that rejected the association.
- * @param timed_out flag to indicate failure is due to timeout
- * (auth, assoc, ...) rather than explicit rejection response from the AP.
- * @param assoc_resp_ie Association response IE.
- * @param assoc_resp_ie_len Association response IE length.
- */
-void HidlManager::notifyAssocReject(struct wpa_supplicant *wpa_s,
-    const u8 *bssid, u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len)
-{
-	std::string hidl_ifname = wpa_s->ifname;
-#ifdef CONFIG_MBO
-	struct wpa_bss *reject_bss;
-#endif /* CONFIG_MBO */
-	V1_4::ISupplicantStaIfaceCallback::AssociationRejectionData hidl_assoc_reject_data = {};
-
-	if (!wpa_s)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-	if (wpa_s->current_ssid) {
-		std::vector < uint8_t > hidl_ssid;
-		hidl_ssid.assign(
-		    wpa_s->current_ssid->ssid,
-		    wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
-		hidl_assoc_reject_data.ssid = hidl_ssid;
-	}
-	hidl_assoc_reject_data.bssid = bssid;
-	hidl_assoc_reject_data.statusCode = static_cast<ISupplicantStaIfaceCallback::StatusCode>(
-					    wpa_s->assoc_status_code);
-	if (timed_out) {
-		hidl_assoc_reject_data.timedOut = true;
-	}
-#ifdef CONFIG_MBO
-	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
-		reject_bss = wpa_s->current_bss;
-	} else {
-		reject_bss = wpa_bss_get_bssid(wpa_s, bssid);
-	}
-	if (reject_bss && assoc_resp_ie && assoc_resp_ie_len > 0) {
-		if (wpa_s->assoc_status_code ==
-		    WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS) {
-			const u8 *rssi_rej;
-			rssi_rej = mbo_get_attr_from_ies(
-				    assoc_resp_ie,
-				    assoc_resp_ie_len,
-				    OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT);
-			if (rssi_rej && rssi_rej[1] == 2) {
-				wpa_printf(MSG_INFO,
-					   "OCE: RSSI-based association rejection from "
-					   MACSTR " Delta RSSI: %u, Retry Delay: %u bss rssi: %d",
-					   MAC2STR(reject_bss->bssid),
-					   rssi_rej[2], rssi_rej[3], reject_bss->level);
-				hidl_assoc_reject_data.isOceRssiBasedAssocRejectAttrPresent = true;
-				hidl_assoc_reject_data.oceRssiBasedAssocRejectData.deltaRssi
-					    = rssi_rej[2];
-				hidl_assoc_reject_data.oceRssiBasedAssocRejectData.retryDelayS
-					    = rssi_rej[3];
-			}
-		} else if (wpa_s->assoc_status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY
-			  || wpa_s->assoc_status_code == WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA) {
-			const u8 *assoc_disallowed;
-			assoc_disallowed = mbo_get_attr_from_ies(
-						    assoc_resp_ie,
-						    assoc_resp_ie_len,
-						    MBO_ATTR_ID_ASSOC_DISALLOW);
-			if (assoc_disallowed && assoc_disallowed[1] == 1) {
-				wpa_printf(MSG_INFO,
-				    "MBO: association disallowed indication from "
-				    MACSTR " Reason: %d",
-				    MAC2STR(reject_bss->bssid),
-				    assoc_disallowed[2]);
-				hidl_assoc_reject_data.isMboAssocDisallowedReasonCodePresent = true;
-				hidl_assoc_reject_data.mboAssocDisallowedReason
-				    = static_cast<V1_4::ISupplicantStaIfaceCallback
-					    ::MboAssocDisallowedReasonCode>(assoc_disallowed[2]);
-			}
-		}
-	}
-#endif /* CONFIG_MBO */
-
-	const std::function<
-		    Return<void>(android::sp<V1_4::ISupplicantStaIfaceCallback>)>
-		    func = std::bind(
-		    &V1_4::ISupplicantStaIfaceCallback::onAssociationRejected_1_4,
-		    std::placeholders::_1, hidl_assoc_reject_data);
-	callWithEachStaIfaceCallbackDerived(hidl_ifname, func);
-}
-
-void HidlManager::notifyAuthTimeout(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	const std::string ifname(wpa_s->ifname);
-	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
-		return;
-
-	const u8 *bssid = wpa_s->bssid;
-	if (is_zero_ether_addr(bssid)) {
-		bssid = wpa_s->pending_bssid;
-	}
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onAuthenticationTimeout,
-		std::placeholders::_1, bssid));
-}
-
-void HidlManager::notifyBssidChanged(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	const std::string ifname(wpa_s->ifname);
-	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
-		return;
-
-	// wpa_supplicant does not explicitly give us the reason for bssid
-	// change, but we figure that out from what is set out of |wpa_s->bssid|
-	// & |wpa_s->pending_bssid|.
-	const u8 *bssid;
-	ISupplicantStaIfaceCallback::BssidChangeReason reason;
-	if (is_zero_ether_addr(wpa_s->bssid) &&
-	    !is_zero_ether_addr(wpa_s->pending_bssid)) {
-		bssid = wpa_s->pending_bssid;
-		reason =
-		    ISupplicantStaIfaceCallback::BssidChangeReason::ASSOC_START;
-	} else if (
-	    !is_zero_ether_addr(wpa_s->bssid) &&
-	    is_zero_ether_addr(wpa_s->pending_bssid)) {
-		bssid = wpa_s->bssid;
-		reason = ISupplicantStaIfaceCallback::BssidChangeReason::
-		    ASSOC_COMPLETE;
-	} else if (
-	    is_zero_ether_addr(wpa_s->bssid) &&
-	    is_zero_ether_addr(wpa_s->pending_bssid)) {
-		bssid = wpa_s->pending_bssid;
-		reason =
-		    ISupplicantStaIfaceCallback::BssidChangeReason::DISASSOC;
-	} else {
-		wpa_printf(MSG_ERROR, "Unknown bssid change reason");
-		return;
-	}
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname, std::bind(
-			       &ISupplicantStaIfaceCallback::onBssidChanged,
-			       std::placeholders::_1, reason, bssid));
-}
-
-void HidlManager::notifyWpsEventFail(
-    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
-    uint16_t error_indication)
-{
-	if (!wpa_s || !peer_macaddr)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onWpsEventFail,
-		std::placeholders::_1, peer_macaddr,
-		static_cast<ISupplicantStaIfaceCallback::WpsConfigError>(
-		    config_error),
-		static_cast<ISupplicantStaIfaceCallback::WpsErrorIndication>(
-		    error_indication)));
-}
-
-void HidlManager::notifyWpsEventSuccess(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname, std::bind(
-			       &ISupplicantStaIfaceCallback::onWpsEventSuccess,
-			       std::placeholders::_1));
-}
-
-void HidlManager::notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onWpsEventPbcOverlap,
-		std::placeholders::_1));
-}
-
-void HidlManager::notifyP2pDeviceFound(
-    struct wpa_supplicant *wpa_s, const u8 *addr,
-    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
-    u8 peer_wfd_r2_device_info_len)
-{
-	if (!wpa_s || !addr || !info)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	std::array<uint8_t, kWfdDeviceInfoLen> hidl_peer_wfd_device_info{};
-	if (peer_wfd_device_info) {
-		if (peer_wfd_device_info_len != kWfdDeviceInfoLen) {
-			wpa_printf(
-			    MSG_ERROR, "Unexpected WFD device info len: %d",
-			    peer_wfd_device_info_len);
-		} else {
-			os_memcpy(
-			    hidl_peer_wfd_device_info.data(),
-			    peer_wfd_device_info, kWfdDeviceInfoLen);
-		}
-	}
-
-	std::array<uint8_t, kWfdR2DeviceInfoLen> hidl_peer_wfd_r2_device_info{};
-	if (peer_wfd_r2_device_info) {
-		if (peer_wfd_r2_device_info_len != kWfdR2DeviceInfoLen) {
-			wpa_printf(
-			    MSG_ERROR, "Unexpected WFD R2 device info len: %d",
-			    peer_wfd_r2_device_info_len);
-			return;
-		} else {
-			os_memcpy(
-			    hidl_peer_wfd_r2_device_info.data(),
-			    peer_wfd_r2_device_info, kWfdR2DeviceInfoLen);
-		}
-	}
-
-	if (peer_wfd_r2_device_info_len == kWfdR2DeviceInfoLen) {
-		const std::function<
-		    Return<void>(android::sp<V1_4::ISupplicantP2pIfaceCallback>)>
-		    func = std::bind(
-			&ISupplicantP2pIfaceCallbackV1_4::onR2DeviceFound,
-			std::placeholders::_1, addr, info->p2p_device_addr,
-			info->pri_dev_type, info->device_name, info->config_methods,
-			info->dev_capab, info->group_capab, hidl_peer_wfd_device_info,
-			hidl_peer_wfd_r2_device_info);
-		callWithEachP2pIfaceCallbackDerived(wpa_s->ifname, func);
-	} else {
-		callWithEachP2pIfaceCallback(
-		    wpa_s->ifname,
-		    std::bind(
-			&ISupplicantP2pIfaceCallback::onDeviceFound,
-			std::placeholders::_1, addr, info->p2p_device_addr,
-			info->pri_dev_type, info->device_name, info->config_methods,
-			info->dev_capab, info->group_capab, hidl_peer_wfd_device_info));
-	}
-}
-
-void HidlManager::notifyP2pDeviceLost(
-    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
-{
-	if (!wpa_s || !p2p_device_addr)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname, std::bind(
-			       &ISupplicantP2pIfaceCallback::onDeviceLost,
-			       std::placeholders::_1, p2p_device_addr));
-}
-
-void HidlManager::notifyP2pFindStopped(struct wpa_supplicant *wpa_s)
-{
-	if (!wpa_s)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname, std::bind(
-			       &ISupplicantP2pIfaceCallback::onFindStopped,
-			       std::placeholders::_1));
-}
-
-void HidlManager::notifyP2pGoNegReq(
-    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
-    u8 /* go_intent */)
-{
-	if (!wpa_s || !src_addr)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onGoNegotiationRequest,
-		std::placeholders::_1, src_addr,
-		static_cast<ISupplicantP2pIfaceCallback::WpsDevPasswordId>(
-		    dev_passwd_id)));
-}
-
-void HidlManager::notifyP2pGoNegCompleted(
-    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
-{
-	if (!wpa_s || !res)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onGoNegotiationCompleted,
-		std::placeholders::_1,
-		static_cast<ISupplicantP2pIfaceCallback::P2pStatusCode>(
-		    res->status)));
-}
-
-void HidlManager::notifyP2pGroupFormationFailure(
-    struct wpa_supplicant *wpa_s, const char *reason)
-{
-	if (!wpa_s || !reason)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onGroupFormationFailure,
-		std::placeholders::_1, reason));
-}
-
-void HidlManager::notifyP2pGroupStarted(
-    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
-    int persistent, int client)
-{
-	if (!wpa_group_s || !wpa_group_s->parent || !ssid)
-		return;
-
-	// For group notifications, need to use the parent iface for callbacks.
-	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
-	if (!wpa_s)
-		return;
-
-	uint32_t hidl_freq = wpa_group_s->current_bss
-				 ? wpa_group_s->current_bss->freq
-				 : wpa_group_s->assoc_freq;
-	std::array<uint8_t, 32> hidl_psk;
-	if (ssid->psk_set) {
-		os_memcpy(hidl_psk.data(), ssid->psk, 32);
-	}
-	bool hidl_is_go = (client == 0 ? true : false);
-	bool hidl_is_persistent = (persistent == 1 ? true : false);
-
-	// notify the group device again to ensure the framework knowing this device.
-	struct p2p_data *p2p = wpa_s->global->p2p;
-	struct p2p_device *dev = p2p_get_device(p2p, wpa_group_s->go_dev_addr);
-	if (NULL != dev) {
-		wpa_printf(MSG_DEBUG, "P2P: Update GO device on group started.");
-		p2p->cfg->dev_found(p2p->cfg->cb_ctx, wpa_group_s->go_dev_addr,
-				&dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
-		dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
-	}
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onGroupStarted,
-		std::placeholders::_1, wpa_group_s->ifname, hidl_is_go,
-		std::vector<uint8_t>{ssid->ssid, ssid->ssid + ssid->ssid_len},
-		hidl_freq, hidl_psk, ssid->passphrase, wpa_group_s->go_dev_addr,
-		hidl_is_persistent));
-}
-
-void HidlManager::notifyP2pGroupRemoved(
-    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
-    const char *role)
-{
-	if (!wpa_group_s || !wpa_group_s->parent || !ssid || !role)
-		return;
-
-	// For group notifications, need to use the parent iface for callbacks.
-	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
-	if (!wpa_s)
-		return;
-
-	bool hidl_is_go = (std::string(role) == "GO");
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onGroupRemoved,
-		std::placeholders::_1, wpa_group_s->ifname, hidl_is_go));
-}
-
-void HidlManager::notifyP2pInvitationReceived(
-    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
-    const u8 *bssid, int id, int op_freq)
-{
-	if (!wpa_s || !sa || !go_dev_addr || !bssid)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	SupplicantNetworkId hidl_network_id;
-	if (id < 0) {
-		hidl_network_id = UINT32_MAX;
-	}
-	hidl_network_id = id;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onInvitationReceived,
-		std::placeholders::_1, sa, go_dev_addr, bssid, hidl_network_id,
-		op_freq));
-}
-
-void HidlManager::notifyP2pInvitationResult(
-    struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
-{
-	if (!wpa_s)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onInvitationResult,
-		std::placeholders::_1, bssid ? bssid : kZeroBssid,
-		static_cast<ISupplicantP2pIfaceCallback::P2pStatusCode>(
-		    status)));
-}
-
-void HidlManager::notifyP2pProvisionDiscovery(
-    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
-    enum p2p_prov_disc_status status, u16 config_methods,
-    unsigned int generated_pin)
-{
-	if (!wpa_s || !dev_addr)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	std::string hidl_generated_pin;
-	if (generated_pin > 0) {
-		hidl_generated_pin =
-		    misc_utils::convertWpsPinToString(generated_pin);
-	}
-	bool hidl_is_request = (request == 1 ? true : false);
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onProvisionDiscoveryCompleted,
-		std::placeholders::_1, dev_addr, hidl_is_request,
-		static_cast<ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode>(
-		    status),
-		config_methods, hidl_generated_pin));
-}
-
-void HidlManager::notifyP2pSdResponse(
-    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
-    const u8 *tlvs, size_t tlvs_len)
-{
-	if (!wpa_s || !sa || !tlvs)
-		return;
-
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onServiceDiscoveryResponse,
-		std::placeholders::_1, sa, update_indic,
-		std::vector<uint8_t>{tlvs, tlvs + tlvs_len}));
-}
-
-void HidlManager::notifyApStaAuthorized(
-    struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
-{
-	if (!wpa_group_s || !wpa_group_s->parent || !sta)
-		return;
-	wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
-	if (!wpa_s)
-		return;
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onStaAuthorized,
-		std::placeholders::_1, sta,
-		p2p_dev_addr ? p2p_dev_addr : kZeroBssid));
-}
-
-void HidlManager::notifyApStaDeauthorized(
-    struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
-{
-	if (!wpa_group_s || !wpa_group_s->parent || !sta)
-		return;
-	wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
-	if (!wpa_s)
-		return;
-
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onStaDeauthorized,
-		std::placeholders::_1, sta,
-		p2p_dev_addr ? p2p_dev_addr : kZeroBssid));
-}
-
-void HidlManager::notifyExtRadioWorkStart(
-    struct wpa_supplicant *wpa_s, uint32_t id)
-{
-	if (!wpa_s)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onExtRadioWorkStart,
-		std::placeholders::_1, id));
-}
-
-void HidlManager::notifyExtRadioWorkTimeout(
-    struct wpa_supplicant *wpa_s, uint32_t id)
-{
-	if (!wpa_s)
-		return;
-
-	if (sta_iface_object_map_.find(wpa_s->ifname) ==
-	    sta_iface_object_map_.end())
-		return;
-
-	callWithEachStaIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantStaIfaceCallback::onExtRadioWorkTimeout,
-		std::placeholders::_1, id));
-}
-
-void HidlManager::notifyEapError(struct wpa_supplicant *wpa_s, int error_code)
-{
-	if (!wpa_s)
-		return;
-
-	callWithEachStaIfaceCallback_1_3(
-	    wpa_s->ifname,
-	    std::bind(
-		&V1_3::ISupplicantStaIfaceCallback::onEapFailure_1_3,
-		std::placeholders::_1, error_code));
-}
-
-/**
- * Notify listener about a new DPP configuration received success event
- *
- * @param ifname Interface name
- * @param config Configuration object
- */
-void HidlManager::notifyDppConfigReceived(struct wpa_supplicant *wpa_s,
-		struct wpa_ssid *config)
-{
-	DppAkm securityAkm;
-	char *password;
-	std::string hidl_ifname = wpa_s->ifname;
-
-	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 */
-		wpa_printf(MSG_ERROR, "DPP: Error: Unsupported AKM 0x%X",
-				config->key_mgmt);
-		notifyDppFailure(wpa_s,
-				android::hardware::wifi::supplicant::V1_3::DppFailureCode
-				::NOT_SUPPORTED);
-		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 configuration sent success event
- *
- * @param ifname Interface name
- */
-void HidlManager::notifyDppConfigSent(struct wpa_supplicant *wpa_s)
-{
-	std::string hidl_ifname = wpa_s->ifname;
-
-	callWithEachStaIfaceCallback_1_2(hidl_ifname,
-			std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppSuccessConfigSent,
-					std::placeholders::_1));
-}
-
-/**
- * Notify listener about a DPP failure event
- *
- * @param ifname Interface name
- * @param code Status code
- */
-void HidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
-		android::hardware::wifi::supplicant::V1_3::DppFailureCode code) {
-	std::string hidl_ifname = wpa_s->ifname;
-
-	notifyDppFailure(wpa_s, code, NULL, NULL, NULL, 0);
-}
-
-/**
- * Notify listener about a DPP failure event
- *
- * @param ifname Interface name
- * @param code Status code
- */
-void HidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
-		android::hardware::wifi::supplicant::V1_3::DppFailureCode code,
-		const char *ssid, const char *channel_list, unsigned short band_list[],
-		int size) {
-	std::string hidl_ifname = wpa_s->ifname;
-	std::vector<uint16_t> band_list_vec(band_list, band_list + size);
-
-	callWithEachStaIfaceCallback_1_3(hidl_ifname,
-			std::bind(&V1_3::ISupplicantStaIfaceCallback::onDppFailure_1_3,
-					std::placeholders::_1, code, ssid, channel_list, band_list_vec));
-}
-
-/**
- * Notify listener about a DPP progress event
- *
- * @param ifname Interface name
- * @param code Status code
- */
-void HidlManager::notifyDppProgress(struct wpa_supplicant *wpa_s,
-		android::hardware::wifi::supplicant::V1_3::DppProgressCode code) {
-	std::string hidl_ifname = wpa_s->ifname;
-
-	callWithEachStaIfaceCallback_1_3(hidl_ifname,
-			std::bind(&V1_3::ISupplicantStaIfaceCallback::onDppProgress_1_3,
-					std::placeholders::_1, code));
-}
-
-/**
- * Notify listener about a DPP success event
- *
- * @param ifname Interface name
- * @param code Status code
- */
-void HidlManager::notifyDppSuccess(struct wpa_supplicant *wpa_s, V1_3::DppSuccessCode code)
-{
-	std::string hidl_ifname = wpa_s->ifname;
-
-	callWithEachStaIfaceCallback_1_3(hidl_ifname,
-			std::bind(&V1_3::ISupplicantStaIfaceCallback::onDppSuccess,
-					std::placeholders::_1, code));
-}
-
-/**
- * Notify listener about a PMK cache added event
- *
- * @param ifname Interface name
- * @param entry PMK cache entry
- */
-void HidlManager::notifyPmkCacheAdded(
-    struct wpa_supplicant *wpa_s, struct rsn_pmksa_cache_entry *pmksa_entry)
-{
-	std::string hidl_ifname = wpa_s->ifname;
-
-	// Serialize PmkCacheEntry into blob.
-	std::stringstream ss(
-	    std::stringstream::in | std::stringstream::out | std::stringstream::binary);
-	misc_utils::serializePmkCacheEntry(ss, pmksa_entry);
-	std::vector<uint8_t> serializedEntry(
-		std::istreambuf_iterator<char>(ss), {});
-
-	const std::function<
-	    Return<void>(android::sp<V1_3::ISupplicantStaIfaceCallback>)>
-	    func = std::bind(
-		&V1_3::ISupplicantStaIfaceCallback::onPmkCacheAdded,
-		std::placeholders::_1, pmksa_entry->expiration, serializedEntry);
-	callWithEachStaIfaceCallbackDerived(hidl_ifname, func);
-}
-
-#ifdef CONFIG_WNM
-V1_3::ISupplicantStaIfaceCallback::BssTmStatusCode convertSupplicantBssTmStatusToHidl(
-    enum bss_trans_mgmt_status_code bss_tm_status)
-{
-	switch (bss_tm_status) {
-		case WNM_BSS_TM_ACCEPT:
-			return V1_3::ISupplicantStaIfaceCallback::BssTmStatusCode::ACCEPT;
-		case WNM_BSS_TM_REJECT_UNSPECIFIED:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_UNSPECIFIED;
-		case WNM_BSS_TM_REJECT_INSUFFICIENT_BEACON:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_INSUFFICIENT_BEACON;
-		case WNM_BSS_TM_REJECT_INSUFFICIENT_CAPABITY:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_INSUFFICIENT_CAPABITY;
-		case WNM_BSS_TM_REJECT_UNDESIRED:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_BSS_TERMINATION_UNDESIRED;
-		case WNM_BSS_TM_REJECT_DELAY_REQUEST:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_BSS_TERMINATION_DELAY_REQUEST;
-		case WNM_BSS_TM_REJECT_STA_CANDIDATE_LIST_PROVIDED:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_STA_CANDIDATE_LIST_PROVIDED;
-		case WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_NO_SUITABLE_CANDIDATES;
-		case WNM_BSS_TM_REJECT_LEAVING_ESS:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_LEAVING_ESS;
-		default:
-			return V1_3::ISupplicantStaIfaceCallback::
-			    BssTmStatusCode::REJECT_UNSPECIFIED;
-	}
-}
-
-uint32_t setBssTmDataFlagsMask(struct wpa_supplicant *wpa_s)
-{
-	uint32_t flags = 0;
-
-	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::WNM_MODE_BSS_TERMINATION_INCLUDED;
-	}
-	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::WNM_MODE_ESS_DISASSOCIATION_IMMINENT;
-	}
-	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::WNM_MODE_DISASSOCIATION_IMMINENT;
-	}
-	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ABRIDGED) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::WNM_MODE_ABRIDGED;
-	}
-	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED;
-	}
-#ifdef CONFIG_MBO
-	if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::MBO_ASSOC_RETRY_DELAY_INCLUDED;
-	}
-	if (wpa_s->wnm_mbo_trans_reason_present) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::MBO_TRANSITION_REASON_CODE_INCLUDED;
-	}
-	if (wpa_s->wnm_mbo_cell_pref_present) {
-		flags |= V1_3::ISupplicantStaIfaceCallback::
-		    BssTmDataFlagsMask::MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED;
-	}
-#endif
-	return flags;
-}
-
-uint32_t getBssTmDataAssocRetryDelayMs(struct wpa_supplicant *wpa_s)
-{
-	uint32_t beacon_int;
-	uint32_t duration_ms = 0;
-
-	if (wpa_s->current_bss)
-		beacon_int = wpa_s->current_bss->beacon_int;
-	else
-		beacon_int = 100; /* best guess */
-
-	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
-		// number of tbtts to milliseconds
-		duration_ms = wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125;
-	}
-	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
-		//wnm_bss_termination_duration contains 12 bytes of BSS
-		//termination duration subelement. Format of IE is
-		// Sub eid | Length | BSS termination TSF | Duration
-		//    1	 1	     8		2
-		// Duration indicates number of minutes for which BSS is not
-		// present.
-		duration_ms = WPA_GET_LE16(wpa_s->wnm_bss_termination_duration + 10);
-		// minutes to milliseconds
-		duration_ms = duration_ms * 60 * 1000;
-	}
-#ifdef CONFIG_MBO
-	if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
-		// number of seconds to milliseconds
-		duration_ms = wpa_s->wnm_mbo_assoc_retry_delay_sec * 1000;
-	}
-#endif
-
-	return duration_ms;
-}
-#endif
-
-/**
- * Notify listener about the status of BSS transition management
- * request frame handling.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the network is present.
- */
-void HidlManager::notifyBssTmStatus(struct wpa_supplicant *wpa_s)
-{
-#ifdef CONFIG_WNM
-	std::string hidl_ifname = wpa_s->ifname;
-	V1_3::ISupplicantStaIfaceCallback::BssTmData hidl_bsstm_data = {};
-
-	hidl_bsstm_data.status = convertSupplicantBssTmStatusToHidl(wpa_s->bss_tm_status);
-	hidl_bsstm_data.flags = setBssTmDataFlagsMask(wpa_s);
-	hidl_bsstm_data.assocRetryDelayMs = getBssTmDataAssocRetryDelayMs(wpa_s);
-#ifdef CONFIG_MBO
-	if (wpa_s->wnm_mbo_cell_pref_present) {
-		hidl_bsstm_data.mboCellPreference = static_cast
-		    <V1_3::ISupplicantStaIfaceCallback::MboCellularDataConnectionPrefValue>
-		    (wpa_s->wnm_mbo_cell_preference);
-	}
-	if (wpa_s->wnm_mbo_trans_reason_present) {
-		hidl_bsstm_data.mboTransitionReason =
-		    static_cast<V1_3::ISupplicantStaIfaceCallback::MboTransitionReasonCode>
-		    (wpa_s->wnm_mbo_transition_reason);
-	}
-#endif
-
-	const std::function<
-	    Return<void>(android::sp<V1_3::ISupplicantStaIfaceCallback>)>
-	    func = std::bind(
-		&V1_3::ISupplicantStaIfaceCallback::onBssTmHandlingDone,
-		std::placeholders::_1, hidl_bsstm_data);
-	callWithEachStaIfaceCallbackDerived(hidl_ifname, func);
-#endif
-}
-
-uint32_t setTransitionDisableFlagsMask(u8 bitmap)
-{
-	uint32_t flags = 0;
-
-	if (bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) {
-		flags |= V1_4::ISupplicantStaNetworkCallback::
-			TransitionDisableIndication::
-			USE_WPA3_PERSONAL;
-		bitmap &= ~TRANSITION_DISABLE_WPA3_PERSONAL;
-	}
-	if (bitmap & TRANSITION_DISABLE_SAE_PK) {
-		flags |= V1_4::ISupplicantStaNetworkCallback::
-			TransitionDisableIndication::
-			USE_SAE_PK;
-		bitmap &= ~TRANSITION_DISABLE_SAE_PK;
-	}
-	if (bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) {
-		flags |= V1_4::ISupplicantStaNetworkCallback::
-			TransitionDisableIndication::
-			USE_WPA3_ENTERPRISE;
-		bitmap &= ~TRANSITION_DISABLE_WPA3_ENTERPRISE;
-	}
-	if (bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) {
-		flags |= V1_4::ISupplicantStaNetworkCallback::
-			TransitionDisableIndication::
-			USE_ENHANCED_OPEN;
-		bitmap &= ~TRANSITION_DISABLE_ENHANCED_OPEN;
-	}
-
-	if (bitmap != 0) {
-		wpa_printf(MSG_WARNING, "Unhandled transition disable bit: 0x%x", bitmap);
-	}
-
-	return flags;
-}
-
-void HidlManager::notifyTransitionDisable(struct wpa_supplicant *wpa_s,
-    struct wpa_ssid *ssid, u8 bitmap)
-{
-	uint32_t flag = setTransitionDisableFlagsMask(bitmap);
-	const std::function<
-	    Return<void>(android::sp<V1_4::ISupplicantStaNetworkCallback>)>
-	    func = std::bind(
-		&V1_4::ISupplicantStaNetworkCallback::onTransitionDisable,
-		std::placeholders::_1, flag);
-
-	callWithEachStaNetworkCallbackDerived(wpa_s->ifname, ssid->id, func);
-}
-
-void HidlManager::notifyNetworkNotFound(struct wpa_supplicant *wpa_s)
-{
-	std::vector<uint8_t> hidl_ssid;
-
-	if (!wpa_s->current_ssid) {
-		wpa_printf(MSG_ERROR, "Current network NULL. Drop WPA_EVENT_NETWORK_NOT_FOUND!");
-		return;
-	}
-
-	hidl_ssid.assign(
-		    wpa_s->current_ssid->ssid,
-		    wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
-
-	const std::function<
-	    Return<void>(android::sp<V1_4::ISupplicantStaIfaceCallback>)>
-	    func = std::bind(
-		&V1_4::ISupplicantStaIfaceCallback::onNetworkNotFound,
-		std::placeholders::_1, hidl_ssid);
-	callWithEachStaIfaceCallbackDerived(wpa_s->ifname, func);
-}
-
-/**
- * Retrieve the |ISupplicantP2pIface| hidl object reference using the provided
- * ifname.
- *
- * @param ifname Name of the corresponding interface.
- * @param iface_object Hidl reference corresponding to the iface.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::getP2pIfaceHidlObjectByIfname(
-    const std::string &ifname, android::sp<ISupplicantP2pIface> *iface_object)
-{
-	if (ifname.empty() || !iface_object)
-		return 1;
-
-	auto iface_object_iter = p2p_iface_object_map_.find(ifname);
-	if (iface_object_iter == p2p_iface_object_map_.end())
-		return 1;
-
-	*iface_object = iface_object_iter->second;
-	return 0;
-}
-
-/**
- * Retrieve the |ISupplicantStaIface| hidl object reference using the provided
- * ifname.
- *
- * @param ifname Name of the corresponding interface.
- * @param iface_object Hidl reference corresponding to the iface.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::getStaIfaceHidlObjectByIfname(
-    const std::string &ifname, android::sp<V1_1::ISupplicantStaIface> *iface_object)
-{
-	if (ifname.empty() || !iface_object)
-		return 1;
-
-	auto iface_object_iter = sta_iface_object_map_.find(ifname);
-	if (iface_object_iter == sta_iface_object_map_.end())
-		return 1;
-
-	*iface_object = iface_object_iter->second;
-	return 0;
-}
-
-/**
- * Retrieve the |ISupplicantP2pNetwork| hidl object reference using the provided
- * ifname and network_id.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param network_object Hidl reference corresponding to the network.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::getP2pNetworkHidlObjectByIfnameAndNetworkId(
-    const std::string &ifname, int network_id,
-    android::sp<ISupplicantP2pNetwork> *network_object)
-{
-	if (ifname.empty() || network_id < 0 || !network_object)
-		return 1;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(ifname, network_id);
-
-	auto network_object_iter = p2p_network_object_map_.find(network_key);
-	if (network_object_iter == p2p_network_object_map_.end())
-		return 1;
-
-	*network_object = network_object_iter->second;
-	return 0;
-}
-
-/**
- * Retrieve the |ISupplicantStaNetwork| hidl object reference using the provided
- * ifname and network_id.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param network_object Hidl reference corresponding to the network.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::getStaNetworkHidlObjectByIfnameAndNetworkId(
-    const std::string &ifname, int network_id,
-    android::sp<V1_3::ISupplicantStaNetwork> *network_object)
-{
-	if (ifname.empty() || network_id < 0 || !network_object)
-		return 1;
-
-	// Generate the key to be used to lookup the network.
-	const std::string network_key =
-	    getNetworkObjectMapKey(ifname, network_id);
-
-	auto network_object_iter = sta_network_object_map_.find(network_key);
-	if (network_object_iter == sta_network_object_map_.end())
-		return 1;
-
-	*network_object = network_object_iter->second;
-	return 0;
-}
-
-/**
- * Add a new |ISupplicantCallback| hidl object reference to our
- * global callback list.
- *
- * @param callback Hidl reference of the |ISupplicantCallback| object.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::addSupplicantCallbackHidlObject(
-    const android::sp<ISupplicantCallback> &callback)
-{
-	return registerForDeathAndAddCallbackHidlObjectToList<
-	    ISupplicantCallback>(
-	    death_notifier_, callback, supplicant_callbacks_);
-}
-
-/**
- * Add a new iface callback hidl object reference to our
- * interface callback list.
- *
- * @param ifname Name of the corresponding interface.
- * @param callback Hidl reference of the callback object.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::addP2pIfaceCallbackHidlObject(
-    const std::string &ifname,
-    const android::sp<ISupplicantP2pIfaceCallback> &callback)
-{
-	return addIfaceCallbackHidlObjectToMap(
-	    death_notifier_, ifname, callback, p2p_iface_callbacks_map_);
-}
-
-/**
- * Add a new iface callback hidl object reference to our
- * interface callback list.
- *
- * @param ifname Name of the corresponding interface.
- * @param callback Hidl reference of the callback object.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::addStaIfaceCallbackHidlObject(
-    const std::string &ifname,
-    const android::sp<ISupplicantStaIfaceCallback> &callback)
-{
-	return addIfaceCallbackHidlObjectToMap(
-	    death_notifier_, ifname, callback, sta_iface_callbacks_map_);
-}
-
-/**
- * Add a new network callback hidl object reference to our network callback
- * list.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param callback Hidl reference of the callback object.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::addP2pNetworkCallbackHidlObject(
-    const std::string &ifname, int network_id,
-    const android::sp<ISupplicantP2pNetworkCallback> &callback)
-{
-	return addNetworkCallbackHidlObjectToMap(
-	    death_notifier_, ifname, network_id, callback,
-	    p2p_network_callbacks_map_);
-}
-
-/**
- * Add a new network callback hidl object reference to our network callback
- * list.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param callback Hidl reference of the callback object.
- *
- * @return 0 on success, 1 on failure.
- */
-int HidlManager::addStaNetworkCallbackHidlObject(
-    const std::string &ifname, int network_id,
-    const android::sp<ISupplicantStaNetworkCallback> &callback)
-{
-	return addNetworkCallbackHidlObjectToMap(
-	    death_notifier_, ifname, network_id, callback,
-	    sta_network_callbacks_map_);
-}
-
-/**
- * Finds the correct |wpa_supplicant| object for P2P notifications
- *
- * @param wpa_s the |wpa_supplicant| that triggered the P2P event.
- * @return appropriate |wpa_supplicant| object or NULL if not found.
- */
-struct wpa_supplicant *HidlManager::getTargetP2pIfaceForGroup(
-	    struct wpa_supplicant *wpa_group_s)
-{
-	if (!wpa_group_s || !wpa_group_s->parent)
-		return NULL;
-
-	struct wpa_supplicant *target_wpa_s = wpa_group_s->parent;
-
-	// check wpa_supplicant object is a p2p device interface
-	if ((wpa_group_s == wpa_group_s->p2pdev) && wpa_group_s->p2p_mgmt) {
-		if (p2p_iface_object_map_.find(wpa_group_s->ifname) !=
-		    p2p_iface_object_map_.end())
-			return wpa_group_s;
-	}
-
-	if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
-	    p2p_iface_object_map_.end())
-		return target_wpa_s;
-
-	// try P2P device if available
-	if (!target_wpa_s->p2pdev || !target_wpa_s->p2pdev->p2p_mgmt)
-		return NULL;
-
-	target_wpa_s = target_wpa_s->p2pdev;
-	if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
-	    p2p_iface_object_map_.end())
-		return target_wpa_s;
-
-	return NULL;
-}
-
-/**
- * Removes the provided |ISupplicantCallback| hidl object reference
- * from our global callback list.
- *
- * @param callback Hidl reference of the |ISupplicantCallback| object.
- */
-void HidlManager::removeSupplicantCallbackHidlObject(
-    const android::sp<ISupplicantCallback> &callback)
-{
-	supplicant_callbacks_.erase(
-	    std::remove(
-		supplicant_callbacks_.begin(), supplicant_callbacks_.end(),
-		callback),
-	    supplicant_callbacks_.end());
-}
-
-/**
- * Removes the provided iface callback hidl object reference from
- * our interface callback list.
- *
- * @param ifname Name of the corresponding interface.
- * @param callback Hidl reference of the callback object.
- */
-void HidlManager::removeP2pIfaceCallbackHidlObject(
-    const std::string &ifname,
-    const android::sp<ISupplicantP2pIfaceCallback> &callback)
-{
-	return removeIfaceCallbackHidlObjectFromMap(
-	    ifname, callback, p2p_iface_callbacks_map_);
-}
-
-/**
- * Removes the provided iface callback hidl object reference from
- * our interface callback list.
- *
- * @param ifname Name of the corresponding interface.
- * @param callback Hidl reference of the callback object.
- */
-void HidlManager::removeStaIfaceCallbackHidlObject(
-    const std::string &ifname,
-    const android::sp<ISupplicantStaIfaceCallback> &callback)
-{
-	return removeIfaceCallbackHidlObjectFromMap(
-	    ifname, callback, sta_iface_callbacks_map_);
-}
-
-/**
- * Removes the provided network callback hidl object reference from
- * our network callback list.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param callback Hidl reference of the callback object.
- */
-void HidlManager::removeP2pNetworkCallbackHidlObject(
-    const std::string &ifname, int network_id,
-    const android::sp<ISupplicantP2pNetworkCallback> &callback)
-{
-	return removeNetworkCallbackHidlObjectFromMap(
-	    ifname, network_id, callback, p2p_network_callbacks_map_);
-}
-
-/**
- * Removes the provided network callback hidl object reference from
- * our network callback list.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param callback Hidl reference of the callback object.
- */
-void HidlManager::removeStaNetworkCallbackHidlObject(
-    const std::string &ifname, int network_id,
-    const android::sp<ISupplicantStaNetworkCallback> &callback)
-{
-	return removeNetworkCallbackHidlObjectFromMap(
-	    ifname, network_id, callback, sta_network_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered |ISupplicantCallback| callback hidl objects.
- *
- * @param method Pointer to the required hidl method from
- * |ISupplicantCallback|.
- */
-void HidlManager::callWithEachSupplicantCallback(
-    const std::function<Return<void>(android::sp<ISupplicantCallback>)> &method)
-{
-	for (const auto &callback : supplicant_callbacks_) {
-		if (!method(callback).isOk()) {
-			wpa_printf(MSG_ERROR, "Failed to invoke HIDL callback");
-		}
-	}
-}
-
-/**
- * Helper fucntion to invoke the provided callback method on all the
- * registered iface callback hidl objects for the specified
- * |ifname|.
- *
- * @param ifname Name of the corresponding interface.
- * @param method Pointer to the required hidl method from
- * |ISupplicantIfaceCallback|.
- */
-void HidlManager::callWithEachP2pIfaceCallback(
-    const std::string &ifname,
-    const std::function<Return<void>(android::sp<ISupplicantP2pIfaceCallback>)>
-	&method)
-{
-	callWithEachIfaceCallback(ifname, method, p2p_iface_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered derived interface callback hidl objects for the specified
- * |ifname|.
- *
- * @param ifname Name of the corresponding interface.
- * @param method Pointer to the required hidl method from
- * derived |V1_x::ISupplicantIfaceCallback|.
- */
-template <class CallbackTypeDerived>
-void HidlManager::callWithEachP2pIfaceCallbackDerived(
-    const std::string &ifname,
-    const std::function<
-	Return<void>(android::sp<CallbackTypeDerived>)> &method)
-{
-	callWithEachIfaceCallbackDerived(ifname, method, p2p_iface_callbacks_map_);
-}
-
-/**
- * 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.
- * @param method Pointer to the required hidl method from
- * |V1_1::ISupplicantIfaceCallback|.
- */
-void HidlManager::callWithEachStaIfaceCallback_1_1(
-    const std::string &ifname,
-    const std::function<
-	Return<void>(android::sp<V1_1::ISupplicantStaIfaceCallback>)> &method)
-{
-	callWithEachIfaceCallbackDerived(ifname, method, sta_iface_callbacks_map_);
-}
-
-/**
- * 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)
-{
-	callWithEachIfaceCallbackDerived(ifname, method, sta_iface_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered V1.3 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_3::ISupplicantIfaceCallback|.
- */
-void HidlManager::callWithEachStaIfaceCallback_1_3(
-    const std::string &ifname,
-    const std::function<
-	Return<void>(android::sp<V1_3::ISupplicantStaIfaceCallback>)> &method)
-{
-	callWithEachIfaceCallbackDerived(ifname, method, sta_iface_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered V1.4 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_4::ISupplicantIfaceCallback|.
- */
-void HidlManager::callWithEachStaIfaceCallback_1_4(
-    const std::string &ifname,
-    const std::function<
-	Return<void>(android::sp<V1_4::ISupplicantStaIfaceCallback>)> &method)
-{
-	callWithEachIfaceCallbackDerived(ifname, method, sta_iface_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered derived interface callback hidl objects for the specified
- * |ifname|.
- *
- * @param ifname Name of the corresponding interface.
- * @param method Pointer to the required hidl method from
- * derived |V1_x::ISupplicantIfaceCallback|.
- */
-template <class CallbackTypeDerived>
-void HidlManager::callWithEachStaIfaceCallbackDerived(
-    const std::string &ifname,
-    const std::function<
-	Return<void>(android::sp<CallbackTypeDerived>)> &method)
-{
-	callWithEachIfaceCallbackDerived(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.
- * @param method Pointer to the required hidl method from
- * |ISupplicantIfaceCallback|.
- */
-void HidlManager::callWithEachStaIfaceCallback(
-    const std::string &ifname,
-    const std::function<Return<void>(android::sp<ISupplicantStaIfaceCallback>)>
-	&method)
-{
-	callWithEachIfaceCallback(ifname, method, sta_iface_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered network callback hidl objects for the specified
- * |ifname| & |network_id|.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param method Pointer to the required hidl method from
- * |ISupplicantP2pNetworkCallback| or |ISupplicantStaNetworkCallback| .
- */
-void HidlManager::callWithEachP2pNetworkCallback(
-    const std::string &ifname, int network_id,
-    const std::function<
-	Return<void>(android::sp<ISupplicantP2pNetworkCallback>)> &method)
-{
-	callWithEachNetworkCallback(
-	    ifname, network_id, method, p2p_network_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered network callback hidl objects for the specified
- * |ifname| & |network_id|.
- *
- * @param ifname Name of the corresponding interface.
- * @param network_id ID of the corresponding network.
- * @param method Pointer to the required hidl method from
- * |ISupplicantP2pNetworkCallback| or |ISupplicantStaNetworkCallback| .
- */
-void HidlManager::callWithEachStaNetworkCallback(
-    const std::string &ifname, int network_id,
-    const std::function<
-	Return<void>(android::sp<ISupplicantStaNetworkCallback>)> &method)
-{
-	callWithEachNetworkCallback(
-	    ifname, network_id, method, sta_network_callbacks_map_);
-}
-
-/**
- * Helper function to invoke the provided callback method on all the
- * registered derived interface callback hidl objects for the specified
- * |ifname|.
- *
- * @param ifname Name of the corresponding interface.
- * @param method Pointer to the required hidl method from
- * derived |V1_x::ISupplicantIfaceCallback|.
- */
-template <class CallbackTypeDerived>
-void HidlManager::callWithEachStaNetworkCallbackDerived(
-    const std::string &ifname, int network_id,
-    const std::function<
-	Return<void>(android::sp<CallbackTypeDerived>)> &method)
-{
-	callWithEachNetworkCallbackDerived(ifname, network_id, method, sta_network_callbacks_map_);
-}
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.h b/wpa_supplicant/hidl/1.4/hidl_manager.h
deleted file mode 100644
index ccde11c..0000000
--- a/wpa_supplicant/hidl/1.4/hidl_manager.h
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_HIDL_MANAGER_H
-#define WPA_SUPPLICANT_HIDL_HIDL_MANAGER_H
-
-#include <map>
-#include <string>
-
-#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.4/ISupplicantStaIfaceCallback.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
-#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaNetworkCallback.h>
-
-#include "p2p_iface.h"
-#include "p2p_network.h"
-#include "rsn_supp/pmksa_cache.h"
-#include "sta_iface.h"
-#include "sta_network.h"
-#include "supplicant.h"
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/includes.h"
-#include "wpa_supplicant_i.h"
-#include "driver_i.h"
-}
-
-class DeathNotifier : public android::hardware::hidl_death_recipient
-{
-public:
-	DeathNotifier(struct wpa_global *wpa_global)
-	    : wpa_global_(wpa_global)
-	{}
-
-	void serviceDied(
-	    uint64_t /*cookie*/,
-	    const android::wp<android::hidl::base::V1_0::IBase>
-		& /* who */) override
-	{
-		wpa_printf(MSG_ERROR, "Client died. Terminating...");
-		wpa_supplicant_terminate_proc(wpa_global_);
-	}
-
-private:
-	struct wpa_global *wpa_global_;
-};
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using V1_0::ISupplicant;
-using V1_0::ISupplicantP2pIface;
-using V1_0::ISupplicantStaIface;
-using V1_0::ISupplicantStaIfaceCallback;
-using V1_0::P2pGroupCapabilityMask;
-using V1_0::WpsConfigMethods;
-
-/**
- * HidlManager is responsible for managing the lifetime of all
- * hidl objects created by wpa_supplicant. This is a singleton
- * class which is created by the supplicant core and can be used
- * to get references to the hidl objects.
- */
-class HidlManager
-{
-public:
-	static HidlManager *getInstance();
-	static void destroyInstance();
-
-	// Methods called from wpa_supplicant core.
-	int registerHidlService(struct wpa_global *global);
-	int registerInterface(struct wpa_supplicant *wpa_s);
-	int unregisterInterface(struct wpa_supplicant *wpa_s);
-	int registerNetwork(
-	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
-	int unregisterNetwork(
-	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
-	int notifyStateChange(struct wpa_supplicant *wpa_s);
-	int notifyNetworkRequest(
-	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
-	    const char *param);
-	void notifyAnqpQueryDone(
-	    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
-	    const struct wpa_bss_anqp *anqp);
-	void notifyHs20IconQueryDone(
-	    struct wpa_supplicant *wpa_s, const u8 *bssid,
-	    const char *file_name, const u8 *image, u32 image_length);
-	void notifyHs20RxSubscriptionRemediation(
-	    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
-	void notifyHs20RxDeauthImminentNotice(
-	    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
-		const char *url);
-	void notifyHs20RxTermsAndConditionsAcceptance(
-			struct wpa_supplicant *wpa_s, const char *url);
-	void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
-	void notifyAssocReject(struct wpa_supplicant *wpa_s, const u8 *bssid,
-	    u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len);
-	void notifyAuthTimeout(struct wpa_supplicant *wpa_s);
-	void notifyBssidChanged(struct wpa_supplicant *wpa_s);
-	void notifyWpsEventFail(
-	    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
-	    uint16_t config_error, uint16_t error_indication);
-	void notifyWpsEventSuccess(struct wpa_supplicant *wpa_s);
-	void notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s);
-	void notifyP2pDeviceFound(
-	    struct wpa_supplicant *wpa_s, const u8 *addr,
-	    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-	    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
-	    u8 peer_wfd_r2_device_info_len);
-	void notifyP2pDeviceLost(
-	    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
-	void notifyP2pFindStopped(struct wpa_supplicant *wpa_s);
-	void notifyP2pGoNegReq(
-	    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
-	    u8 go_intent);
-	void notifyP2pGoNegCompleted(
-	    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
-	void notifyP2pGroupFormationFailure(
-	    struct wpa_supplicant *wpa_s, const char *reason);
-	void notifyP2pGroupStarted(
-	    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
-	    int persistent, int client);
-	void notifyP2pGroupRemoved(
-	    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
-	    const char *role);
-	void notifyP2pInvitationReceived(
-	    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
-	    const u8 *bssid, int id, int op_freq);
-	void notifyP2pInvitationResult(
-	    struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
-	void notifyP2pProvisionDiscovery(
-	    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
-	    enum p2p_prov_disc_status status, u16 config_methods,
-	    unsigned int generated_pin);
-	void notifyP2pSdResponse(
-	    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
-	    const u8 *tlvs, size_t tlvs_len);
-	void notifyApStaAuthorized(
-	    struct wpa_supplicant *wpa_s, const u8 *sta,
-	    const u8 *p2p_dev_addr);
-	void notifyApStaDeauthorized(
-	    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(struct wpa_supplicant *wpa_s,
-			struct wpa_ssid *config);
-	void notifyDppConfigSent(struct wpa_supplicant *wpa_s);
-	void notifyDppSuccess(struct wpa_supplicant *wpa_s, V1_3::DppSuccessCode code);
-	void notifyDppFailure(struct wpa_supplicant *wpa_s,
-			android::hardware::wifi::supplicant::V1_3::DppFailureCode code);
-	void notifyDppFailure(struct wpa_supplicant *wpa_s,
-			android::hardware::wifi::supplicant::V1_3::DppFailureCode code,
-			const char *ssid, const char *channel_list, unsigned short band_list[],
-			int size);
-	void notifyDppProgress(struct wpa_supplicant *wpa_s,
-			android::hardware::wifi::supplicant::V1_3::DppProgressCode code);
-	void notifyPmkCacheAdded(struct wpa_supplicant *wpa_s,
-			struct rsn_pmksa_cache_entry *pmksa_entry);
-	void notifyBssTmStatus(struct wpa_supplicant *wpa_s);
-	void notifyTransitionDisable(struct wpa_supplicant *wpa_s,
-			struct wpa_ssid *ssid,
-			u8 bitmap);
-	void notifyNetworkNotFound(struct wpa_supplicant *wpa_s);
-
-	// Methods called from hidl objects.
-	void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
-	void notifyExtRadioWorkTimeout(
-	    struct wpa_supplicant *wpa_s, uint32_t id);
-
-	int getP2pIfaceHidlObjectByIfname(
-	    const std::string &ifname,
-	    android::sp<ISupplicantP2pIface> *iface_object);
-	int getStaIfaceHidlObjectByIfname(
-	    const std::string &ifname,
-	    android::sp<V1_1::ISupplicantStaIface> *iface_object);
-	int getP2pNetworkHidlObjectByIfnameAndNetworkId(
-	    const std::string &ifname, int network_id,
-	    android::sp<ISupplicantP2pNetwork> *network_object);
-	int getStaNetworkHidlObjectByIfnameAndNetworkId(
-	    const std::string &ifname, int network_id,
-	    android::sp<V1_3::ISupplicantStaNetwork> *network_object);
-	int addSupplicantCallbackHidlObject(
-	    const android::sp<ISupplicantCallback> &callback);
-	int addP2pIfaceCallbackHidlObject(
-	    const std::string &ifname,
-	    const android::sp<ISupplicantP2pIfaceCallback> &callback);
-	int addStaIfaceCallbackHidlObject(
-	    const std::string &ifname,
-	    const android::sp<ISupplicantStaIfaceCallback> &callback);
-	int addP2pNetworkCallbackHidlObject(
-	    const std::string &ifname, int network_id,
-	    const android::sp<ISupplicantP2pNetworkCallback> &callback);
-	int addStaNetworkCallbackHidlObject(
-	    const std::string &ifname, int network_id,
-	    const android::sp<ISupplicantStaNetworkCallback> &callback);
-
-private:
-	HidlManager() = default;
-	~HidlManager() = default;
-	HidlManager(const HidlManager &) = default;
-	HidlManager &operator=(const HidlManager &) = default;
-
-	struct wpa_supplicant *getTargetP2pIfaceForGroup(
-	    struct wpa_supplicant *wpa_s);
-	void removeSupplicantCallbackHidlObject(
-	    const android::sp<ISupplicantCallback> &callback);
-	void removeP2pIfaceCallbackHidlObject(
-	    const std::string &ifname,
-	    const android::sp<ISupplicantP2pIfaceCallback> &callback);
-	void removeStaIfaceCallbackHidlObject(
-	    const std::string &ifname,
-	    const android::sp<ISupplicantStaIfaceCallback> &callback);
-	void removeP2pNetworkCallbackHidlObject(
-	    const std::string &ifname, int network_id,
-	    const android::sp<ISupplicantP2pNetworkCallback> &callback);
-	void removeStaNetworkCallbackHidlObject(
-	    const std::string &ifname, int network_id,
-	    const android::sp<ISupplicantStaNetworkCallback> &callback);
-
-	void callWithEachSupplicantCallback(
-	    const std::function<android::hardware::Return<void>(
-		android::sp<ISupplicantCallback>)> &method);
-	void callWithEachP2pIfaceCallback(
-	    const std::string &ifname,
-	    const std::function<android::hardware::Return<void>(
-		android::sp<ISupplicantP2pIfaceCallback>)> &method);
-	template <class CallbackTypeDerived>
-	void callWithEachP2pIfaceCallbackDerived(
-	    const std::string &ifname,
-	    const std::function<
-		Return<void>(android::sp<CallbackTypeDerived>)> &method);
-	void callWithEachStaIfaceCallback(
-	    const std::string &ifname,
-	    const std::function<android::hardware::Return<void>(
-		android::sp<ISupplicantStaIfaceCallback>)> &method);
-	void callWithEachStaIfaceCallback_1_1(
-	    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 callWithEachStaIfaceCallback_1_3(
-	    const std::string &ifname,
-	    const std::function<android::hardware::Return<void>(
-	    android::sp<V1_3::ISupplicantStaIfaceCallback>)> &method);
-	void callWithEachStaIfaceCallback_1_4(
-	    const std::string &ifname,
-	    const std::function<android::hardware::Return<void>(
-	    android::sp<V1_4::ISupplicantStaIfaceCallback>)> &method);
-	template <class CallbackTypeDerived>
-	void callWithEachStaIfaceCallbackDerived(
-	    const std::string &ifname,
-	    const std::function<
-		Return<void>(android::sp<CallbackTypeDerived>)> &method);
-	void callWithEachP2pNetworkCallback(
-	    const std::string &ifname, int network_id,
-	    const std::function<android::hardware::Return<void>(
-		android::sp<ISupplicantP2pNetworkCallback>)> &method);
-	void callWithEachStaNetworkCallback(
-	    const std::string &ifname, int network_id,
-	    const std::function<android::hardware::Return<void>(
-		android::sp<ISupplicantStaNetworkCallback>)> &method);
-	template <class CallbackTypeDerived>
-	void callWithEachStaNetworkCallbackDerived(
-	    const std::string &ifname, int network_id,
-	    const std::function<
-		Return<void>(android::sp<CallbackTypeDerived>)> &method);
-
-	// Singleton instance of this class.
-	static HidlManager *instance_;
-	// Raw pointer to the global structure maintained by the core.
-	struct wpa_global *wpa_global_;
-	// Death notifier.
-	android::sp<DeathNotifier> death_notifier_;
-	// The main hidl service object.
-	android::sp<Supplicant> supplicant_object_;
-	// Map of all the P2P interface specific hidl objects controlled by
-	// wpa_supplicant. This map is keyed in by the corresponding
-	// |ifname|.
-	std::map<const std::string, android::sp<P2pIface>>
-	    p2p_iface_object_map_;
-	// Map of all the STA interface specific hidl objects controlled by
-	// wpa_supplicant. This map is keyed in by the corresponding
-	// |ifname|.
-	std::map<const std::string, android::sp<StaIface>>
-	    sta_iface_object_map_;
-	// Map of all the P2P network specific hidl objects controlled by
-	// wpa_supplicant. This map is keyed in by the corresponding
-	// |ifname| & |network_id|.
-	std::map<const std::string, android::sp<P2pNetwork>>
-	    p2p_network_object_map_;
-	// Map of all the STA network specific hidl objects controlled by
-	// wpa_supplicant. This map is keyed in by the corresponding
-	// |ifname| & |network_id|.
-	std::map<const std::string, android::sp<StaNetwork>>
-	    sta_network_object_map_;
-
-	// Callback registered for the main hidl service object.
-	std::vector<android::sp<ISupplicantCallback>> supplicant_callbacks_;
-	// Map of all the callbacks registered for P2P interface specific
-	// hidl objects controlled by wpa_supplicant.  This map is keyed in by
-	// the corresponding |ifname|.
-	std::map<
-	    const std::string,
-	    std::vector<android::sp<ISupplicantP2pIfaceCallback>>>
-	    p2p_iface_callbacks_map_;
-	// Map of all the callbacks registered for STA interface specific
-	// hidl objects controlled by wpa_supplicant.  This map is keyed in by
-	// the corresponding |ifname|.
-	std::map<
-	    const std::string,
-	    std::vector<android::sp<ISupplicantStaIfaceCallback>>>
-	    sta_iface_callbacks_map_;
-	// Map of all the callbacks registered for P2P network specific
-	// hidl objects controlled by wpa_supplicant.  This map is keyed in by
-	// the corresponding |ifname| & |network_id|.
-	std::map<
-	    const std::string,
-	    std::vector<android::sp<ISupplicantP2pNetworkCallback>>>
-	    p2p_network_callbacks_map_;
-	// Map of all the callbacks registered for STA network specific
-	// hidl objects controlled by wpa_supplicant.  This map is keyed in by
-	// the corresponding |ifname| & |network_id|.
-	std::map<
-	    const std::string,
-	    std::vector<android::sp<ISupplicantStaNetworkCallback>>>
-	    sta_network_callbacks_map_;
-};
-
-// The hidl interface uses some values which are the same as internal ones to
-// avoid nasty runtime conversion functions. So, adding compile time asserts
-// to guard against any internal changes breaking the hidl interface.
-static_assert(
-    static_cast<uint32_t>(ISupplicant::DebugLevel::EXCESSIVE) == MSG_EXCESSIVE,
-    "Debug level value mismatch");
-static_assert(
-    static_cast<uint32_t>(ISupplicant::DebugLevel::ERROR) == MSG_ERROR,
-    "Debug level value mismatch");
-
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::KeyMgmtMask::NONE) ==
-	WPA_KEY_MGMT_NONE,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK) ==
-	WPA_KEY_MGMT_PSK,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP) ==
-	WPA_KEY_MGMT_IEEE8021X,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X) ==
-	WPA_KEY_MGMT_IEEE8021X_NO_WPA,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::KeyMgmtMask::FT_EAP) ==
-	WPA_KEY_MGMT_FT_IEEE8021X,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::KeyMgmtMask::FT_PSK) ==
-	WPA_KEY_MGMT_FT_PSK,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::KeyMgmtMask::OSEN) ==
-	WPA_KEY_MGMT_OSEN,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_2::ISupplicantStaNetwork::KeyMgmtMask::SAE) ==
-	WPA_KEY_MGMT_SAE,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_2::ISupplicantStaNetwork::KeyMgmtMask::SUITE_B_192) ==
-	WPA_KEY_MGMT_IEEE8021X_SUITE_B_192,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_2::ISupplicantStaNetwork::KeyMgmtMask::OWE) ==
-	WPA_KEY_MGMT_OWE,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_2::ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK_SHA256) ==
-	WPA_KEY_MGMT_PSK_SHA256,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_2::ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP_SHA256) ==
-	WPA_KEY_MGMT_IEEE8021X_SHA256,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_3::ISupplicantStaNetwork::KeyMgmtMask::WAPI_PSK) ==
-	WPA_KEY_MGMT_WAPI_PSK,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_3::ISupplicantStaNetwork::KeyMgmtMask::WAPI_CERT) ==
-	WPA_KEY_MGMT_WAPI_CERT,
-    "KeyMgmt value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::ProtoMask::WPA) ==
-	WPA_PROTO_WPA,
-    "Proto value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::ProtoMask::RSN) ==
-	WPA_PROTO_RSN,
-    "Proto value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::ProtoMask::OSEN) ==
-	WPA_PROTO_OSEN,
-    "Proto value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_3::ISupplicantStaNetwork::ProtoMask::WAPI) ==
-	WPA_PROTO_WAPI,
-    "Proto value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::AuthAlgMask::OPEN) ==
-	WPA_AUTH_ALG_OPEN,
-    "AuthAlg value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::AuthAlgMask::SHARED) ==
-	WPA_AUTH_ALG_SHARED,
-    "AuthAlg value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::AuthAlgMask::LEAP) ==
-	WPA_AUTH_ALG_LEAP,
-    "AuthAlg value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::GroupCipherMask::WEP40) ==
-	WPA_CIPHER_WEP40,
-    "GroupCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::GroupCipherMask::WEP104) ==
-	WPA_CIPHER_WEP104,
-    "GroupCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::GroupCipherMask::TKIP) ==
-	WPA_CIPHER_TKIP,
-    "GroupCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::GroupCipherMask::CCMP) ==
-	WPA_CIPHER_CCMP,
-    "GroupCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_2::ISupplicantStaNetwork::GroupCipherMask::GCMP_256) ==
-	WPA_CIPHER_GCMP_256,
-    "GroupCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_3::ISupplicantStaNetwork::GroupCipherMask::SMS4) ==
-	WPA_CIPHER_SMS4,
-    "GroupCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	V1_0::ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED) ==
-	WPA_CIPHER_GTK_NOT_USED,
-    "GroupCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::PairwiseCipherMask::NONE) ==
-	WPA_CIPHER_NONE,
-    "PairwiseCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::PairwiseCipherMask::TKIP) ==
-	WPA_CIPHER_TKIP,
-    "PairwiseCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(V1_0::ISupplicantStaNetwork::PairwiseCipherMask::CCMP) ==
-	WPA_CIPHER_CCMP,
-    "PairwiseCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	V1_2::ISupplicantStaNetwork::PairwiseCipherMask::GCMP_256) ==
-	WPA_CIPHER_GCMP_256,
-    "PairwiseCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	V1_3::ISupplicantStaNetwork::PairwiseCipherMask::SMS4) ==
-	WPA_CIPHER_SMS4,
-    "PairwiseCipher value mismatch");
-static_assert(
-    static_cast<uint32_t>(ISupplicantStaIfaceCallback::State::DISCONNECTED) ==
-	WPA_DISCONNECTED,
-    "State value mismatch");
-static_assert(
-    static_cast<uint32_t>(ISupplicantStaIfaceCallback::State::COMPLETED) ==
-	WPA_COMPLETED,
-    "State value mismatch");
-
-static_assert(
-    static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::VENUE_NAME) ==
-	ANQP_VENUE_NAME,
-    "ANQP ID value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	ISupplicantStaIface::AnqpInfoId::ROAMING_CONSORTIUM) ==
-	ANQP_ROAMING_CONSORTIUM,
-    "ANQP ID value mismatch");
-static_assert(
-    static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::NAI_REALM) ==
-	ANQP_NAI_REALM,
-    "ANQP ID value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	ISupplicantStaIface::AnqpInfoId::IP_ADDR_TYPE_AVAILABILITY) ==
-	ANQP_IP_ADDR_TYPE_AVAILABILITY,
-    "ANQP ID value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	ISupplicantStaIface::AnqpInfoId::ANQP_3GPP_CELLULAR_NETWORK) ==
-	ANQP_3GPP_CELLULAR_NETWORK,
-    "ANQP ID value mismatch");
-static_assert(
-    static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::DOMAIN_NAME) ==
-	ANQP_DOMAIN_NAME,
-    "ANQP ID value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	ISupplicantStaIface::Hs20AnqpSubtypes::OPERATOR_FRIENDLY_NAME) ==
-	HS20_STYPE_OPERATOR_FRIENDLY_NAME,
-    "HS Subtype value mismatch");
-static_assert(
-    static_cast<uint32_t>(ISupplicantStaIface::Hs20AnqpSubtypes::WAN_METRICS) ==
-	HS20_STYPE_WAN_METRICS,
-    "HS Subtype value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	ISupplicantStaIface::Hs20AnqpSubtypes::CONNECTION_CAPABILITY) ==
-	HS20_STYPE_CONNECTION_CAPABILITY,
-    "HS Subtype value mismatch");
-static_assert(
-    static_cast<uint32_t>(
-	ISupplicantStaIface::Hs20AnqpSubtypes::OSU_PROVIDERS_LIST) ==
-	HS20_STYPE_OSU_PROVIDERS_LIST,
-    "HS Subtype value mismatch");
-
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantStaIfaceCallback::WpsConfigError::NO_ERROR) ==
-	WPS_CFG_NO_ERROR,
-    "Wps config error value mismatch");
-static_assert(
-    static_cast<uint16_t>(ISupplicantStaIfaceCallback::WpsConfigError::
-			      PUBLIC_KEY_HASH_MISMATCH) ==
-	WPS_CFG_PUBLIC_KEY_HASH_MISMATCH,
-    "Wps config error value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantStaIfaceCallback::WpsErrorIndication::NO_ERROR) ==
-	WPS_EI_NO_ERROR,
-    "Wps error indication value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantStaIfaceCallback::WpsErrorIndication::AUTH_FAILURE) ==
-	WPS_EI_AUTH_FAILURE,
-    "Wps error indication value mismatch");
-
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::USBA) == WPS_CONFIG_USBA,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::ETHERNET) == WPS_CONFIG_ETHERNET,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::LABEL) == WPS_CONFIG_LABEL,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::DISPLAY) == WPS_CONFIG_DISPLAY,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::INT_NFC_TOKEN) ==
-	WPS_CONFIG_INT_NFC_TOKEN,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::EXT_NFC_TOKEN) ==
-	WPS_CONFIG_EXT_NFC_TOKEN,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::NFC_INTERFACE) ==
-	WPS_CONFIG_NFC_INTERFACE,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::PUSHBUTTON) ==
-	WPS_CONFIG_PUSHBUTTON,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::KEYPAD) == WPS_CONFIG_KEYPAD,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::VIRT_PUSHBUTTON) ==
-	WPS_CONFIG_VIRT_PUSHBUTTON,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::PHY_PUSHBUTTON) ==
-	WPS_CONFIG_PHY_PUSHBUTTON,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::P2PS) == WPS_CONFIG_P2PS,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::VIRT_DISPLAY) ==
-	WPS_CONFIG_VIRT_DISPLAY,
-    "Wps config value mismatch");
-static_assert(
-    static_cast<uint32_t>(WpsConfigMethods::PHY_DISPLAY) ==
-	WPS_CONFIG_PHY_DISPLAY,
-    "Wps config value mismatch");
-
-static_assert(
-    static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_OWNER) ==
-	P2P_GROUP_CAPAB_GROUP_OWNER,
-    "P2P capability value mismatch");
-static_assert(
-    static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_GROUP) ==
-	P2P_GROUP_CAPAB_PERSISTENT_GROUP,
-    "P2P capability value mismatch");
-static_assert(
-    static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_LIMIT) ==
-	P2P_GROUP_CAPAB_GROUP_LIMIT,
-    "P2P capability value mismatch");
-static_assert(
-    static_cast<uint32_t>(P2pGroupCapabilityMask::INTRA_BSS_DIST) ==
-	P2P_GROUP_CAPAB_INTRA_BSS_DIST,
-    "P2P capability value mismatch");
-static_assert(
-    static_cast<uint32_t>(P2pGroupCapabilityMask::CROSS_CONN) ==
-	P2P_GROUP_CAPAB_CROSS_CONN,
-    "P2P capability value mismatch");
-static_assert(
-    static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_RECONN) ==
-	P2P_GROUP_CAPAB_PERSISTENT_RECONN,
-    "P2P capability value mismatch");
-static_assert(
-    static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_FORMATION) ==
-	P2P_GROUP_CAPAB_GROUP_FORMATION,
-    "P2P capability value mismatch");
-
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::WpsDevPasswordId::DEFAULT) ==
-	DEV_PW_DEFAULT,
-    "Wps dev password id value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::WpsDevPasswordId::USER_SPECIFIED) ==
-	DEV_PW_USER_SPECIFIED,
-    "Wps dev password id value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::WpsDevPasswordId::MACHINE_SPECIFIED) ==
-	DEV_PW_MACHINE_SPECIFIED,
-    "Wps dev password id value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::WpsDevPasswordId::REKEY) == DEV_PW_REKEY,
-    "Wps dev password id value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::WpsDevPasswordId::PUSHBUTTON) ==
-	DEV_PW_PUSHBUTTON,
-    "Wps dev password id value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::WpsDevPasswordId::REGISTRAR_SPECIFIED) ==
-	DEV_PW_REGISTRAR_SPECIFIED,
-    "Wps dev password id value mismatch");
-static_assert(
-    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::WpsDevPasswordId::
-			      NFC_CONNECTION_HANDOVER) ==
-	DEV_PW_NFC_CONNECTION_HANDOVER,
-    "Wps dev password id value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::WpsDevPasswordId::P2PS_DEFAULT) ==
-	DEV_PW_P2PS_DEFAULT,
-    "Wps dev password id value mismatch");
-
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::SUCCESS) == P2P_SC_SUCCESS,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::P2pStatusCode::
-			      FAIL_INFO_CURRENTLY_UNAVAILABLE) ==
-	P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_INCOMPATIBLE_PARAMS) ==
-	P2P_SC_FAIL_INCOMPATIBLE_PARAMS,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_LIMIT_REACHED) ==
-	P2P_SC_FAIL_LIMIT_REACHED,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_INVALID_PARAMS) ==
-	P2P_SC_FAIL_INVALID_PARAMS,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::P2pStatusCode::
-			      FAIL_UNABLE_TO_ACCOMMODATE) ==
-	P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_PREV_PROTOCOL_ERROR) ==
-	P2P_SC_FAIL_PREV_PROTOCOL_ERROR,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_NO_COMMON_CHANNELS) ==
-	P2P_SC_FAIL_NO_COMMON_CHANNELS,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_UNKNOWN_GROUP) ==
-	P2P_SC_FAIL_UNKNOWN_GROUP,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_BOTH_GO_INTENT_15) ==
-	P2P_SC_FAIL_BOTH_GO_INTENT_15,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::P2pStatusCode::
-			      FAIL_INCOMPATIBLE_PROV_METHOD) ==
-	P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_REJECTED_BY_USER) ==
-	P2P_SC_FAIL_REJECTED_BY_USER,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pStatusCode::SUCCESS_DEFERRED) ==
-	P2P_SC_SUCCESS_DEFERRED,
-    "P2P status code value mismatch");
-
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::SUCCESS) ==
-	P2P_PROV_DISC_SUCCESS,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::TIMEOUT) ==
-	P2P_PROV_DISC_TIMEOUT,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::REJECTED) ==
-	P2P_PROV_DISC_REJECTED,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::TIMEOUT_JOIN) ==
-	P2P_PROV_DISC_TIMEOUT_JOIN,
-    "P2P status code value mismatch");
-static_assert(
-    static_cast<uint16_t>(
-	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::INFO_UNAVAILABLE) ==
-	P2P_PROV_DISC_INFO_UNAVAILABLE,
-    "P2P status code value mismatch");
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-#endif  // WPA_SUPPLICANT_HIDL_HIDL_MANAGER_H
diff --git a/wpa_supplicant/hidl/1.4/hidl_return_util.h b/wpa_supplicant/hidl/1.4/hidl_return_util.h
deleted file mode 100644
index 217f215..0000000
--- a/wpa_supplicant/hidl/1.4/hidl_return_util.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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 HIDL_RETURN_UTIL_H_
-#define HIDL_RETURN_UTIL_H_
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-namespace hidl_return_util {
-
-/**
- * These utility functions are used to invoke a method on the provided
- * HIDL interface object.
- * These functions checks if the provided HIDL interface object is valid.
- * a) if valid, Invokes the corresponding internal implementation function of
- * the HIDL method. It then invokes the HIDL continuation callback with
- * the status and any returned values.
- * b) if invalid, invokes the HIDL continuation callback with the
- * provided error status and default values.
- */
-// Use for HIDL methods which return only an instance of SupplicantStatus.
-template <typename ObjT, typename SupplicantStatusCodeT, typename WorkFuncT,
-    typename SupplicantStatusT, typename... Args>
-Return<void> validateAndCall(
-    ObjT* obj, SupplicantStatusCodeT status_code_if_invalid, WorkFuncT&& work,
-    const std::function<void(const SupplicantStatusT&)>& hidl_cb, Args&&... args)
-{
-	if (obj->isValid()) {
-		hidl_cb((obj->*work)(std::forward<Args>(args)...));
-	} else {
-		hidl_cb({status_code_if_invalid, ""});
-	}
-	return Void();
-}
-
-// Use for HIDL methods which return instance of SupplicantStatus and a single
-// return value.
-template <typename ObjT, typename SupplicantStatusCodeT, typename WorkFuncT,
-    typename SupplicantStatusT, typename ReturnT, typename... Args>
-Return<void> validateAndCall(
-    ObjT* obj, SupplicantStatusCodeT status_code_if_invalid, WorkFuncT&& work,
-    const std::function<void(const SupplicantStatusT&, ReturnT)>& hidl_cb,
-    Args&&... args)
-{
-	if (obj->isValid()) {
-		const auto& ret_pair =
-		    (obj->*work)(std::forward<Args>(args)...);
-		const SupplicantStatusT& status = std::get<0>(ret_pair);
-		const auto& ret_value = std::get<1>(ret_pair);
-		hidl_cb(status, ret_value);
-	} else {
-		hidl_cb(
-		    {status_code_if_invalid, ""},
-		    typename std::remove_reference<ReturnT>::type());
-	}
-	return Void();
-}
-
-// Use for HIDL methods which return instance of SupplicantStatus and 2 return
-// values.
-template <
-    typename ObjT, typename SupplicantStatusCodeT, typename WorkFuncT,
-    typename SupplicantStatusT, typename ReturnT1, typename ReturnT2, typename... Args>
-Return<void> validateAndCall(
-    ObjT* obj, SupplicantStatusCodeT status_code_if_invalid, WorkFuncT&& work,
-    const std::function<void(const SupplicantStatusT&, ReturnT1, ReturnT2)>&
-	hidl_cb,
-    Args&&... args)
-{
-	if (obj->isValid()) {
-		const auto& ret_tuple =
-		    (obj->*work)(std::forward<Args>(args)...);
-		const SupplicantStatusT& status = std::get<0>(ret_tuple);
-		const auto& ret_value1 = std::get<1>(ret_tuple);
-		const auto& ret_value2 = std::get<2>(ret_tuple);
-		hidl_cb(status, ret_value1, ret_value2);
-	} else {
-		hidl_cb(
-		    {status_code_if_invalid, ""},
-		    typename std::remove_reference<ReturnT1>::type(),
-		    typename std::remove_reference<ReturnT2>::type());
-	}
-	return Void();
-}
-
-}  // namespace hidl_return_util
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-#endif  // HIDL_RETURN_UTIL_H_
diff --git a/wpa_supplicant/hidl/1.4/iface_config_utils.cpp b/wpa_supplicant/hidl/1.4/iface_config_utils.cpp
deleted file mode 100644
index 9af3ea9..0000000
--- a/wpa_supplicant/hidl/1.4/iface_config_utils.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (struct wpa_supplicant* wpa_s, c) 2004-2016, Jouni Malinen
- * <j@w1.fi>
- * Copyright (struct wpa_supplicant* wpa_s, 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.
- */
-
-#include "hidl_manager.h"
-#include "hidl_return_util.h"
-#include "iface_config_utils.h"
-
-namespace {
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
-
-constexpr uint32_t kMaxWpsDeviceNameSize = WPS_DEV_NAME_MAX_LEN;
-constexpr uint32_t kMaxWpsManufacturerSize = WPS_MANUFACTURER_MAX_LEN;
-constexpr uint32_t kMaxWpsModelNameSize = WPS_MODEL_NAME_MAX_LEN;
-constexpr uint32_t kMaxWpsModelNumberSize = WPS_MODEL_NUMBER_MAX_LEN;
-constexpr uint32_t kMaxWpsSerialNumberSize = WPS_SERIAL_NUMBER_MAX_LEN;
-
-void processConfigUpdate(struct wpa_supplicant* wpa_s, uint32_t changed_param)
-{
-	wpa_s->conf->changed_parameters |= changed_param;
-	wpa_supplicant_update_config(wpa_s);
-}
-
-// Free any existing pointer stored in |dst| and store the provided string value
-// there.
-int freeAndSetStringConfigParam(
-    struct wpa_supplicant* wpa_s, const std::string& value, uint32_t max_size,
-    uint32_t changed_param, char** dst)
-{
-	if (value.size() > max_size) {
-		return -1;
-	}
-	WPA_ASSERT(dst);
-	os_free(static_cast<void*>(*dst));
-	*dst = os_strdup(value.c_str());
-	processConfigUpdate(wpa_s, changed_param);
-	return 0;
-}
-
-std::string convertWpsConfigMethodsMaskToString(uint16_t config_methods)
-{
-	using WpsConfigMethods =
-	    android::hardware::wifi::supplicant::V1_0::WpsConfigMethods;
-	std::string config_methods_str;
-	for (const auto& flag_and_name :
-	     {std::make_pair(WpsConfigMethods::USBA, "usba"),
-	      {WpsConfigMethods::ETHERNET, "ethernet"},
-	      {WpsConfigMethods::LABEL, "label"},
-	      {WpsConfigMethods::DISPLAY, "display"},
-	      {WpsConfigMethods::INT_NFC_TOKEN, "int_nfc_token"},
-	      {WpsConfigMethods::EXT_NFC_TOKEN, "ext_nfc_token"},
-	      {WpsConfigMethods::NFC_INTERFACE, "nfc_interface"},
-	      {WpsConfigMethods::PUSHBUTTON, "push_button"},
-	      {WpsConfigMethods::KEYPAD, "keypad"},
-	      {WpsConfigMethods::VIRT_PUSHBUTTON, "virtual_push_button"},
-	      {WpsConfigMethods::PHY_PUSHBUTTON, "physical_push_button"},
-	      {WpsConfigMethods::P2PS, "p2ps"},
-	      {WpsConfigMethods::VIRT_DISPLAY, "virtual_display"},
-	      {WpsConfigMethods::PHY_DISPLAY, "physical_display"}}) {
-		const auto flag =
-		    static_cast<std::underlying_type<WpsConfigMethods>::type>(
-			flag_and_name.first);
-		if ((config_methods & flag) == flag) {
-			config_methods_str += flag_and_name.second;
-			config_methods_str += " ";
-		}
-	}
-	return config_methods_str;
-}
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-namespace iface_config_utils {
-using V1_0::SupplicantStatusCode;
-
-SupplicantStatus setWpsDeviceName(
-    struct wpa_supplicant* wpa_s, const std::string& name)
-{
-	WPA_ASSERT(wpa_s);
-	if (freeAndSetStringConfigParam(
-		wpa_s, name, kMaxWpsDeviceNameSize, CFG_CHANGED_DEVICE_NAME,
-		&wpa_s->conf->device_name)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus setWpsDeviceType(
-    struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type)
-{
-	WPA_ASSERT(wpa_s);
-	WPA_ASSERT(type.size() == WPS_DEV_TYPE_LEN);
-	os_memcpy(wpa_s->conf->device_type, type.data(), WPS_DEV_TYPE_LEN);
-	processConfigUpdate(wpa_s, CFG_CHANGED_DEVICE_TYPE);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus setWpsManufacturer(
-    struct wpa_supplicant* wpa_s, const std::string& manufacturer)
-{
-	WPA_ASSERT(wpa_s);
-	if (freeAndSetStringConfigParam(
-		wpa_s, manufacturer, kMaxWpsManufacturerSize,
-		CFG_CHANGED_WPS_STRING, &wpa_s->conf->manufacturer)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus setWpsModelName(
-    struct wpa_supplicant* wpa_s, const std::string& model_name)
-{
-	WPA_ASSERT(wpa_s);
-	if (freeAndSetStringConfigParam(
-		wpa_s, model_name, kMaxWpsModelNameSize, CFG_CHANGED_WPS_STRING,
-		&wpa_s->conf->model_name)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus setWpsModelNumber(
-    struct wpa_supplicant* wpa_s, const std::string& model_number)
-{
-	WPA_ASSERT(wpa_s);
-	if (freeAndSetStringConfigParam(
-		wpa_s, model_number, kMaxWpsModelNumberSize,
-		CFG_CHANGED_WPS_STRING, &wpa_s->conf->model_number)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus setWpsSerialNumber(
-    struct wpa_supplicant* wpa_s, const std::string& serial_number)
-{
-	WPA_ASSERT(wpa_s);
-	if (freeAndSetStringConfigParam(
-		wpa_s, serial_number, kMaxWpsSerialNumberSize,
-		CFG_CHANGED_WPS_STRING, &wpa_s->conf->serial_number)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus setWpsConfigMethods(
-    struct wpa_supplicant* wpa_s, uint16_t config_methods)
-{
-	WPA_ASSERT(wpa_s);
-	if (freeAndSetStringConfigParam(
-		wpa_s, convertWpsConfigMethodsMaskToString(config_methods),
-		UINT32_MAX, CFG_CHANGED_CONFIG_METHODS,
-		&wpa_s->conf->config_methods)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus setExternalSim(
-    struct wpa_supplicant* wpa_s, bool useExternalSim)
-{
-	WPA_ASSERT(wpa_s);
-	wpa_s->conf->external_sim = useExternalSim ? 1 : 0;
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-}  // namespace iface_config_utils
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wpa_supplicant/hidl/1.4/iface_config_utils.h b/wpa_supplicant/hidl/1.4/iface_config_utils.h
deleted file mode 100644
index a94feb5..0000000
--- a/wpa_supplicant/hidl/1.4/iface_config_utils.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (struct wpa_supplicant* wpa_s, c) 2004-2016, Jouni Malinen
- * <j@w1.fi>
- * Copyright (struct wpa_supplicant* wpa_s, 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 WPA_SUPPLICANT_HIDL_IFACE_CONFIG_UTILS_H
-#define WPA_SUPPLICANT_HIDL_IFACE_CONFIG_UTILS_H
-
-#include <android-base/macros.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/includes.h"
-#include "wpa_supplicant_i.h"
-#include "config.h"
-}
-
-/**
- * Utility functions to set various config parameters of an iface via HIDL
- * methods.
- */
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-namespace iface_config_utils {
-SupplicantStatus setWpsDeviceName(
-    struct wpa_supplicant* wpa_s, const std::string& name);
-SupplicantStatus setWpsDeviceType(
-    struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type);
-SupplicantStatus setWpsManufacturer(
-    struct wpa_supplicant* wpa_s, const std::string& manufacturer);
-SupplicantStatus setWpsModelName(
-    struct wpa_supplicant* wpa_s, const std::string& model_name);
-SupplicantStatus setWpsModelNumber(
-    struct wpa_supplicant* wpa_s, const std::string& model_number);
-SupplicantStatus setWpsSerialNumber(
-    struct wpa_supplicant* wpa_s, const std::string& serial_number);
-SupplicantStatus setWpsConfigMethods(
-    struct wpa_supplicant* wpa_s, uint16_t config_methods);
-SupplicantStatus setExternalSim(
-    struct wpa_supplicant* wpa_s, bool useExternalSim);
-}  // namespace iface_config_utils
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WPA_SUPPLICANT_HIDL_IFACE_CONFIG_UTILS_H
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.cpp b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
deleted file mode 100644
index cabcccb..0000000
--- a/wpa_supplicant/hidl/1.4/p2p_iface.cpp
+++ /dev/null
@@ -1,1985 +0,0 @@
-/*
- * hidl interface for wpa_supplicant daemon
- * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
- * Copyright (C) 2017 Sony Mobile Communications Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "hidl_manager.h"
-#include "hidl_return_util.h"
-#include "iface_config_utils.h"
-#include "misc_utils.h"
-#include "p2p_iface.h"
-#include "sta_network.h"
-
-extern "C"
-{
-#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 3
-// Wait time before triggering the single channel scan to discover Auto GO.
-// Use a shorter wait time when the given frequency is GO operating frequency.
-// The idea is to quickly finish scans and return the status to application.
-#define P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS 200000
-// Wait time before triggering the multiple channel scan to discover Auto GO.
-#define P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS 1000000
-
-namespace {
-const char kConfigMethodStrPbc[] = "pbc";
-const char kConfigMethodStrDisplay[] = "display";
-const char kConfigMethodStrKeypad[] = "keypad";
-constexpr char kSetMiracastMode[] = "MIRACAST ";
-constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
-constexpr uint8_t kWfdR2DeviceInfoSubelemId = 11;
-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(
-    ISupplicantP2pIface::MiracastMode mode)
-{
-	switch (mode) {
-	case ISupplicantP2pIface::MiracastMode::DISABLED:
-		return 0;
-	case ISupplicantP2pIface::MiracastMode::SOURCE:
-		return 1;
-	case ISupplicantP2pIface::MiracastMode::SINK:
-		return 2;
-	};
-	WPA_ASSERT(false);
-}
-
-/**
- * Check if the provided ssid is valid or not.
- *
- * Returns 1 if valid, 0 otherwise.
- */
-int isSsidValid(const std::vector<uint8_t>& ssid)
-{
-	if (ssid.size() == 0 ||
-	    ssid.size() >
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  SSID_MAX_LEN_IN_BYTES)) {
-		return 0;
-	}
-	return 1;
-}
-
-/**
- * Check if the provided psk passhrase is valid or not.
- *
- * Returns 1 if valid, 0 otherwise.
- */
-int isPskPassphraseValid(const std::string &psk)
-{
-	if (psk.size() <
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
-	    psk.size() >
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
-		return 0;
-	}
-	if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
-		return 0;
-	}
-	return 1;
-}
-
-static int setBandScanFreqsList(
-    struct wpa_supplicant *wpa_s,
-    enum hostapd_hw_mode hw_mode,
-    bool exclude_dfs,
-    struct wpa_driver_scan_params *params)
-{
-	struct hostapd_hw_modes *mode;
-	int count, i;
-
-	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
-	if (mode == NULL || !mode->num_channels) {
-		wpa_printf(MSG_ERROR,
-		    "P2P: No channels supported in this hw_mode: %d", hw_mode);
-		return -1;
-	}
-
-	/*
-	 * Allocate memory for frequency array, allocate one extra
-	 * slot for the zero-terminator.
-	 */
-	params->freqs = (int *) os_calloc(mode->num_channels + 1, sizeof(int));
-	if (params->freqs == NULL) {
-		return -ENOMEM;
-	}
-	for (count = 0, i = 0; i < mode->num_channels; i++) {
-		if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) {
-			continue;
-		}
-		if (exclude_dfs && (mode->channels[i].flag & HOSTAPD_CHAN_RADAR)) {
-			continue;
-		}
-		params->freqs[count++] = mode->channels[i].freq;
-	}
-	if (!count && params->freqs) {
-		wpa_printf(MSG_ERROR,
-		    "P2P: All channels(exclude_dfs: %d) are disabled in this hw_mode: %d",
-		    exclude_dfs, hw_mode);
-		os_free(params->freqs);
-		return -1;
-	}
-	return 0;
-}
-
-static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
-    struct wpa_driver_scan_params *params, int freq)
-{
-	if (freq == 2 || freq == 5) {
-		enum hostapd_hw_mode mode;
-		int ret;
-		if (wpa_s->hw.modes == NULL) {
-			wpa_printf(MSG_DEBUG,
-				   "P2P: Unknown what %dG channels the driver supports.", freq);
-			return 0;
-		}
-		mode = freq == 5 ? HOSTAPD_MODE_IEEE80211A : HOSTAPD_MODE_IEEE80211G;
-		if (wpa_s->p2p_join_scan_count < 2) {
-			// scan all non DFS channels in the first two attempts
-			ret = setBandScanFreqsList(wpa_s, mode, true, params);
-			if (ret < 0 && (-ENOMEM != ret)) {
-				// try to scan all channels before returning error
-				ret = setBandScanFreqsList(wpa_s, mode, false, params);
-			}
-		} else {
-			// scan all channels
-			ret = setBandScanFreqsList(wpa_s, mode, false, params);
-		}
-		return ret;
-	} else {
-		if (disabled_freq(wpa_s, freq)) {
-			wpa_printf(MSG_ERROR,
-				   "P2P: freq %d is not supported for a client.", freq);
-			return -1;
-		}
-		/*
-		 * Allocate memory for frequency array, allocate one extra
-		 * slot for the zero-terminator.
-		 */
-		params->freqs = (int *) os_calloc(2, sizeof(int));
-		if (params->freqs) {
-			params->freqs[0] = freq;
-		} else {
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-/**
- * getP2pJoinScanInterval - Get the delay in triggering the scan to discover
- * Auto GO.
- */
-static int getP2pJoinScanIntervalUsecs(int freq)
-{
-	if (freq == 5 || freq == 2 || freq == 0) {
-		return P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS;
-	} else {
-		return P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS;
-	}
-}
-
-/*
- * isAnyEtherAddr - match any ether address
- *
- */
-int isAnyEtherAddr(const u8 *a)
-{
-	// 02:00:00:00:00:00
-	return (a[0] == 2) && !(a[1] | a[2] | a[3] | a[4] | a[5]);
-}
-
-/**
- * findBssBySsid - Fetch a BSS table entry based on SSID and optional BSSID.
- * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID, 02:00:00:00:00:00 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 ((isAnyEtherAddr(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 = 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 (wpa_s->p2p_scan_work) {
-		struct wpa_radio_work *work = wpa_s->p2p_scan_work;
-		wpa_s->p2p_scan_work = NULL;
-		radio_work_done(work);
-	}
-
-	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;
-
-	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
-		wpa_printf(MSG_ERROR,
-		    "P2P: P2P interface is gone, cancel join scan");
-		return -ENXIO;
-	}
-
-	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);
-
-	/* Construct an optimized p2p scan channel list */
-	if (freq > 0) {
-		ret = setP2pCliOptimizedScanFreqsList(wpa_s, &params, freq);
-		if (ret < 0) {
-			wpa_printf(MSG_ERROR,
-				   "Failed to set frequency in p2p scan params, error = %d", ret);
-			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);
-		if (wpa_s->scan_res_handler) {
-			wpa_printf(MSG_DEBUG, "Replace current running scan result handler");
-		}
-		wpa_s->p2p_join_scan_count++;
-		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 he = wpa_s->conf->p2p_go_he;
-	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,
-		CHANWIDTH_USE_HT, he, 0, NULL, 0, 0)) {
-		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.");
-
-	if (wpa_s->p2p_scan_work) {
-		struct wpa_radio_work *work = wpa_s->p2p_scan_work;
-		wpa_s->p2p_scan_work = NULL;
-		radio_work_done(work);
-	}
-
-}
-
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using V1_0::SupplicantStatusCode;
-
-P2pIface::P2pIface(struct wpa_global* wpa_global, const char ifname[])
-    : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
-{}
-
-void P2pIface::invalidate() { is_valid_ = false; }
-bool P2pIface::isValid()
-{
-	return (is_valid_ && (retrieveIfacePtr() != nullptr));
-}
-Return<void> P2pIface::getName(getName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::getNameInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::getType(getType_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::getTypeInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::addNetwork(addNetwork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::addNetworkInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::removeNetwork(
-    SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::removeNetworkInternal, _hidl_cb, id);
-}
-
-Return<void> P2pIface::getNetwork(
-    SupplicantNetworkId id, getNetwork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::getNetworkInternal, _hidl_cb, id);
-}
-
-Return<void> P2pIface::listNetworks(listNetworks_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::listNetworksInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::registerCallback(
-    const sp<ISupplicantP2pIfaceCallback>& callback,
-    registerCallback_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::registerCallbackInternal, _hidl_cb, callback);
-}
-
-Return<void> P2pIface::getDeviceAddress(getDeviceAddress_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::getDeviceAddressInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::setSsidPostfix(
-    const hidl_vec<uint8_t>& postfix, setSsidPostfix_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setSsidPostfixInternal, _hidl_cb, postfix);
-}
-
-Return<void> P2pIface::setGroupIdle(
-    const hidl_string& group_ifname, uint32_t timeout_in_sec,
-    setGroupIdle_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setGroupIdleInternal, _hidl_cb, group_ifname,
-	    timeout_in_sec);
-}
-
-Return<void> P2pIface::setPowerSave(
-    const hidl_string& group_ifname, bool enable, setPowerSave_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setPowerSaveInternal, _hidl_cb, group_ifname, enable);
-}
-
-Return<void> P2pIface::find(uint32_t timeout_in_sec, find_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::findInternal, _hidl_cb, timeout_in_sec);
-}
-
-Return<void> P2pIface::stopFind(stopFind_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::stopFindInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::flush(flush_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::flushInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::connect(
-    const hidl_array<uint8_t, 6>& peer_address,
-    ISupplicantP2pIface::WpsProvisionMethod provision_method,
-    const hidl_string& pre_selected_pin, bool join_existing_group,
-    bool persistent, uint32_t go_intent, connect_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::connectInternal, _hidl_cb, peer_address,
-	    provision_method, pre_selected_pin, join_existing_group, persistent,
-	    go_intent);
-}
-
-Return<void> P2pIface::cancelConnect(cancelConnect_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::cancelConnectInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::provisionDiscovery(
-    const hidl_array<uint8_t, 6>& peer_address,
-    ISupplicantP2pIface::WpsProvisionMethod provision_method,
-    provisionDiscovery_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::provisionDiscoveryInternal, _hidl_cb, peer_address,
-	    provision_method);
-}
-
-Return<void> P2pIface::addGroup(
-    bool persistent, SupplicantNetworkId persistent_network_id,
-    addGroup_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::addGroupInternal, _hidl_cb, persistent,
-	    persistent_network_id);
-}
-
-Return<void> P2pIface::removeGroup(
-    const hidl_string& group_ifname, removeGroup_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::removeGroupInternal, _hidl_cb, group_ifname);
-}
-
-Return<void> P2pIface::reject(
-    const hidl_array<uint8_t, 6>& peer_address, reject_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::rejectInternal, _hidl_cb, peer_address);
-}
-
-Return<void> P2pIface::invite(
-    const hidl_string& group_ifname,
-    const hidl_array<uint8_t, 6>& go_device_address,
-    const hidl_array<uint8_t, 6>& peer_address, invite_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::inviteInternal, _hidl_cb, group_ifname,
-	    go_device_address, peer_address);
-}
-
-Return<void> P2pIface::reinvoke(
-    SupplicantNetworkId persistent_network_id,
-    const hidl_array<uint8_t, 6>& peer_address, reinvoke_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::reinvokeInternal, _hidl_cb, persistent_network_id,
-	    peer_address);
-}
-
-Return<void> P2pIface::configureExtListen(
-    uint32_t period_in_millis, uint32_t interval_in_millis,
-    configureExtListen_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::configureExtListenInternal, _hidl_cb, period_in_millis,
-	    interval_in_millis);
-}
-
-Return<void> P2pIface::setListenChannel(
-    uint32_t channel, uint32_t operating_class, setListenChannel_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setListenChannelInternal, _hidl_cb, channel,
-	    operating_class);
-}
-
-Return<void> P2pIface::setDisallowedFrequencies(
-    const hidl_vec<FreqRange>& ranges, setDisallowedFrequencies_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setDisallowedFrequenciesInternal, _hidl_cb, ranges);
-}
-
-Return<void> P2pIface::getSsid(
-    const hidl_array<uint8_t, 6>& peer_address, getSsid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::getSsidInternal, _hidl_cb, peer_address);
-}
-
-Return<void> P2pIface::getGroupCapability(
-    const hidl_array<uint8_t, 6>& peer_address, getGroupCapability_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::getGroupCapabilityInternal, _hidl_cb, peer_address);
-}
-
-Return<void> P2pIface::addBonjourService(
-    const hidl_vec<uint8_t>& query, const hidl_vec<uint8_t>& response,
-    addBonjourService_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::addBonjourServiceInternal, _hidl_cb, query, response);
-}
-
-Return<void> P2pIface::removeBonjourService(
-    const hidl_vec<uint8_t>& query, removeBonjourService_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::removeBonjourServiceInternal, _hidl_cb, query);
-}
-
-Return<void> P2pIface::addUpnpService(
-    uint32_t version, const hidl_string& service_name,
-    addUpnpService_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::addUpnpServiceInternal, _hidl_cb, version, service_name);
-}
-
-Return<void> P2pIface::removeUpnpService(
-    uint32_t version, const hidl_string& service_name,
-    removeUpnpService_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::removeUpnpServiceInternal, _hidl_cb, version,
-	    service_name);
-}
-
-Return<void> P2pIface::flushServices(flushServices_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::flushServicesInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::requestServiceDiscovery(
-    const hidl_array<uint8_t, 6>& peer_address, const hidl_vec<uint8_t>& query,
-    requestServiceDiscovery_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::requestServiceDiscoveryInternal, _hidl_cb, peer_address,
-	    query);
-}
-
-Return<void> P2pIface::cancelServiceDiscovery(
-    uint64_t identifier, cancelServiceDiscovery_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::cancelServiceDiscoveryInternal, _hidl_cb, identifier);
-}
-
-Return<void> P2pIface::setMiracastMode(
-    ISupplicantP2pIface::MiracastMode mode, setMiracastMode_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setMiracastModeInternal, _hidl_cb, mode);
-}
-
-Return<void> P2pIface::startWpsPbc(
-    const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
-    startWpsPbc_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::startWpsPbcInternal, _hidl_cb, group_ifname, bssid);
-}
-
-Return<void> P2pIface::startWpsPinKeypad(
-    const hidl_string& group_ifname, const hidl_string& pin,
-    startWpsPinKeypad_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::startWpsPinKeypadInternal, _hidl_cb, group_ifname, pin);
-}
-
-Return<void> P2pIface::startWpsPinDisplay(
-    const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
-    startWpsPinDisplay_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::startWpsPinDisplayInternal, _hidl_cb, group_ifname,
-	    bssid);
-}
-
-Return<void> P2pIface::cancelWps(
-    const hidl_string& group_ifname, cancelWps_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::cancelWpsInternal, _hidl_cb, group_ifname);
-}
-
-Return<void> P2pIface::setWpsDeviceName(
-    const hidl_string& name, setWpsDeviceName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWpsDeviceNameInternal, _hidl_cb, name);
-}
-
-Return<void> P2pIface::setWpsDeviceType(
-    const hidl_array<uint8_t, 8>& type, setWpsDeviceType_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWpsDeviceTypeInternal, _hidl_cb, type);
-}
-
-Return<void> P2pIface::setWpsManufacturer(
-    const hidl_string& manufacturer, setWpsManufacturer_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
-}
-
-Return<void> P2pIface::setWpsModelName(
-    const hidl_string& model_name, setWpsModelName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWpsModelNameInternal, _hidl_cb, model_name);
-}
-
-Return<void> P2pIface::setWpsModelNumber(
-    const hidl_string& model_number, setWpsModelNumber_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWpsModelNumberInternal, _hidl_cb, model_number);
-}
-
-Return<void> P2pIface::setWpsSerialNumber(
-    const hidl_string& serial_number, setWpsSerialNumber_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
-}
-
-Return<void> P2pIface::setWpsConfigMethods(
-    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
-}
-
-Return<void> P2pIface::enableWfd(bool enable, enableWfd_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::enableWfdInternal, _hidl_cb, enable);
-}
-
-Return<void> P2pIface::setWfdDeviceInfo(
-    const hidl_array<uint8_t, 6>& info, setWfdDeviceInfo_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &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);
-}
-
-Return<void> P2pIface::saveConfig(saveConfig_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::saveConfigInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::addGroup_1_2(
-    const hidl_vec<uint8_t>& ssid, const hidl_string& passphrase,
-    bool persistent, uint32_t freq, const hidl_array<uint8_t, 6>& peer_address,
-    bool join, addGroup_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::addGroup_1_2Internal, _hidl_cb,
-	    ssid, passphrase, persistent, freq, peer_address, join);
-}
-
-Return<void> P2pIface::setMacRandomization(bool enable, setMacRandomization_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setMacRandomizationInternal, _hidl_cb, enable);
-}
-
-Return<void> P2pIface::setEdmg(bool enable, setEdmg_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pIface::setEdmgInternal, _hidl_cb, enable);
-}
-
-Return<void> P2pIface::getEdmg(getEdmg_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pIface::getEdmgInternal, _hidl_cb);
-}
-
-Return<void> P2pIface::registerCallback_1_4(
-    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback,
-    registerCallback_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::registerCallback_1_4Internal, _hidl_cb, callback);
-}
-
-Return<void> P2pIface::setWfdR2DeviceInfo(
-    const hidl_array<uint8_t, 4>& info, setWfdR2DeviceInfo_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &P2pIface::setWfdR2DeviceInfoInternal, _hidl_cb, info);
-}
-
-std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
-}
-
-std::pair<SupplicantStatus, IfaceType> P2pIface::getTypeInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
-}
-
-std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
-P2pIface::addNetworkInternal()
-{
-	android::sp<ISupplicantP2pNetwork> network;
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	struct wpa_ssid* ssid = wpa_supplicant_add_network(wpa_s);
-	if (!ssid) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
-	}
-	HidlManager* hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
-		wpa_s->ifname, ssid->id, &network)) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, network};
-}
-
-SupplicantStatus P2pIface::removeNetworkInternal(SupplicantNetworkId id)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	int result = wpa_supplicant_remove_network(wpa_s, id);
-	if (result == -1) {
-		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
-	}
-	if (result != 0) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
-P2pIface::getNetworkInternal(SupplicantNetworkId id)
-{
-	android::sp<ISupplicantP2pNetwork> network;
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	struct wpa_ssid* ssid = wpa_config_get_network(wpa_s->conf, id);
-	if (!ssid) {
-		return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
-			network};
-	}
-	HidlManager* hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
-		wpa_s->ifname, ssid->id, &network)) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, network};
-}
-
-std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
-P2pIface::listNetworksInternal()
-{
-	std::vector<SupplicantNetworkId> network_ids;
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	for (struct wpa_ssid* wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
-	     wpa_ssid = wpa_ssid->next) {
-		network_ids.emplace_back(wpa_ssid->id);
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
-}
-
-SupplicantStatus P2pIface::registerCallbackInternal(
-    const sp<ISupplicantP2pIfaceCallback>& callback)
-{
-	HidlManager* hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, std::array<uint8_t, 6>>
-P2pIface::getDeviceAddressInternal()
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	std::array<uint8_t, 6> addr;
-	static_assert(ETH_ALEN == addr.size(), "Size mismatch");
-	os_memcpy(addr.data(), wpa_s->global->p2p_dev_addr, ETH_ALEN);
-	return {{SupplicantStatusCode::SUCCESS, ""}, addr};
-}
-
-SupplicantStatus P2pIface::setSsidPostfixInternal(
-    const std::vector<uint8_t>& postfix)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (p2p_set_ssid_postfix(
-		wpa_s->global->p2p, postfix.data(), postfix.size())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setGroupIdleInternal(
-    const std::string& group_ifname, uint32_t timeout_in_sec)
-{
-	struct wpa_supplicant* wpa_group_s =
-	    retrieveGroupIfacePtr(group_ifname);
-	if (!wpa_group_s) {
-		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-	wpa_group_s->conf->p2p_group_idle = timeout_in_sec;
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setPowerSaveInternal(
-    const std::string& group_ifname, bool enable)
-{
-	struct wpa_supplicant* wpa_group_s =
-	    retrieveGroupIfacePtr(group_ifname);
-	if (!wpa_group_s) {
-		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-	if (wpa_drv_set_p2p_powersave(wpa_group_s, enable, -1, -1)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::findInternal(uint32_t timeout_in_sec)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
-		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-	}
-	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
-	if (wpas_p2p_find(
-		wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
-		nullptr, search_delay, 0, nullptr, 0)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::stopFindInternal()
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	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, ""};
-}
-
-SupplicantStatus P2pIface::flushInternal()
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
-	wpa_s->force_long_sd = 0;
-	wpas_p2p_stop_find(wpa_s);
-	wpa_s->parent->p2ps_method_config_any = 0;
-	if (wpa_s->global->p2p)
-		p2p_flush(wpa_s->global->p2p);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-// This method only implements support for subset (needed by Android framework)
-// of parameters that can be specified for connect.
-std::pair<SupplicantStatus, std::string> P2pIface::connectInternal(
-    const std::array<uint8_t, 6>& peer_address,
-    ISupplicantP2pIface::WpsProvisionMethod provision_method,
-    const std::string& pre_selected_pin, bool join_existing_group,
-    bool persistent, uint32_t go_intent)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (go_intent > 15) {
-		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
-	}
-	int go_intent_signed = join_existing_group ? -1 : go_intent;
-	p2p_wps_method wps_method = {};
-	switch (provision_method) {
-	case WpsProvisionMethod::PBC:
-		wps_method = WPS_PBC;
-		break;
-	case WpsProvisionMethod::DISPLAY:
-		wps_method = WPS_PIN_DISPLAY;
-		break;
-	case WpsProvisionMethod::KEYPAD:
-		wps_method = WPS_PIN_KEYPAD;
-		break;
-	}
-	int he = wpa_s->conf->p2p_go_he;
-	int vht = wpa_s->conf->p2p_go_vht;
-	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
-	const char* pin =
-	    pre_selected_pin.length() > 0 ? pre_selected_pin.data() : nullptr;
-	bool auto_join = !join_existing_group;
-	int new_pin = wpas_p2p_connect(
-	    wpa_s, peer_address.data(), pin, wps_method, persistent, auto_join,
-	    join_existing_group, false, go_intent_signed, 0, 0, -1, false, ht40,
-	    vht, CHANWIDTH_USE_HT, he, 0, nullptr, 0);
-	if (new_pin < 0) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	std::string pin_ret;
-	if (provision_method == WpsProvisionMethod::DISPLAY &&
-	    pre_selected_pin.empty()) {
-		pin_ret = misc_utils::convertWpsPinToString(new_pin);
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, pin_ret};
-}
-
-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, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::provisionDiscoveryInternal(
-    const std::array<uint8_t, 6>& peer_address,
-    ISupplicantP2pIface::WpsProvisionMethod provision_method)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	p2ps_provision* prov_param;
-	const char* config_method_str = nullptr;
-	switch (provision_method) {
-	case WpsProvisionMethod::PBC:
-		config_method_str = kConfigMethodStrPbc;
-		break;
-	case WpsProvisionMethod::DISPLAY:
-		config_method_str = kConfigMethodStrDisplay;
-		break;
-	case WpsProvisionMethod::KEYPAD:
-		config_method_str = kConfigMethodStrKeypad;
-		break;
-	}
-	if (wpas_p2p_prov_disc(
-		wpa_s, peer_address.data(), config_method_str,
-		WPAS_P2P_PD_FOR_GO_NEG, nullptr)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::addGroupInternal(
-    bool persistent, SupplicantNetworkId persistent_network_id)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	int he = wpa_s->conf->p2p_go_he;
-	int vht = wpa_s->conf->p2p_go_vht;
-	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
-	struct wpa_ssid* ssid =
-	    wpa_config_get_network(wpa_s->conf, persistent_network_id);
-	if (ssid == NULL) {
-		if (wpas_p2p_group_add(
-			wpa_s, persistent, 0, 0, ht40, vht,
-			CHANWIDTH_USE_HT, he, 0)) {
-			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-		} else {
-			return {SupplicantStatusCode::SUCCESS, ""};
-		}
-	} else if (ssid->disabled == 2) {
-		if (wpas_p2p_group_add_persistent(
-			wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
-			CHANWIDTH_USE_HT, he, 0, NULL, 0, 0)) {
-			return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
-				""};
-		} else {
-			return {SupplicantStatusCode::SUCCESS, ""};
-		}
-	}
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-SupplicantStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
-{
-	struct wpa_supplicant* wpa_group_s =
-	    retrieveGroupIfacePtr(group_ifname);
-	if (!wpa_group_s) {
-		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-	wpa_group_s->global->p2p_go_found_external_scan = 0;
-	if (wpas_p2p_group_remove(wpa_group_s, group_ifname.c_str())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::rejectInternal(
-    const std::array<uint8_t, 6>& peer_address)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
-		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-	}
-	if (wpas_p2p_reject(wpa_s, peer_address.data())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::inviteInternal(
-    const std::string& group_ifname,
-    const std::array<uint8_t, 6>& go_device_address,
-    const std::array<uint8_t, 6>& peer_address)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (wpas_p2p_invite_group(
-		wpa_s, group_ifname.c_str(), peer_address.data(),
-		go_device_address.data())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::reinvokeInternal(
-    SupplicantNetworkId persistent_network_id,
-    const std::array<uint8_t, 6>& peer_address)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	int he = wpa_s->conf->p2p_go_he;
-	int vht = wpa_s->conf->p2p_go_vht;
-	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
-	struct wpa_ssid* ssid =
-	    wpa_config_get_network(wpa_s->conf, persistent_network_id);
-	if (ssid == NULL || ssid->disabled != 2) {
-		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
-	}
-	if (wpas_p2p_invite(
-		wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
-		CHANWIDTH_USE_HT, 0, he, 0)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::configureExtListenInternal(
-    uint32_t period_in_millis, uint32_t interval_in_millis)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (wpas_p2p_ext_listen(wpa_s, period_in_millis, interval_in_millis)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setListenChannelInternal(
-    uint32_t channel, uint32_t operating_class)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (p2p_set_listen_channel(
-		wpa_s->global->p2p, operating_class, channel, 1)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setDisallowedFrequenciesInternal(
-    const std::vector<FreqRange>& ranges)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	using DestT = struct wpa_freq_range_list::wpa_freq_range;
-	DestT* freq_ranges = nullptr;
-	// Empty ranges is used to enable all frequencies.
-	if (ranges.size() != 0) {
-		freq_ranges = static_cast<DestT*>(
-		    os_malloc(sizeof(DestT) * ranges.size()));
-		if (!freq_ranges) {
-			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-		}
-		uint32_t i = 0;
-		for (const auto& range : ranges) {
-			freq_ranges[i].min = range.min;
-			freq_ranges[i].max = range.max;
-			i++;
-		}
-	}
-
-	os_free(wpa_s->global->p2p_disallow_freq.range);
-	wpa_s->global->p2p_disallow_freq.range = freq_ranges;
-	wpa_s->global->p2p_disallow_freq.num = ranges.size();
-	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>> P2pIface::getSsidInternal(
-    const std::array<uint8_t, 6>& peer_address)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	const struct p2p_peer_info* info =
-	    p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
-	if (!info) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	const struct p2p_device* dev =
-	    reinterpret_cast<const struct p2p_device*>(
-		(reinterpret_cast<const uint8_t*>(info)) -
-		offsetof(struct p2p_device, info));
-	std::vector<uint8_t> ssid;
-	if (dev && dev->oper_ssid_len) {
-		ssid.assign(
-		    dev->oper_ssid, dev->oper_ssid + dev->oper_ssid_len);
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, ssid};
-}
-
-std::pair<SupplicantStatus, uint32_t> P2pIface::getGroupCapabilityInternal(
-    const std::array<uint8_t, 6>& peer_address)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	const struct p2p_peer_info* info =
-	    p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
-	if (!info) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, info->group_capab};
-}
-
-SupplicantStatus P2pIface::addBonjourServiceInternal(
-    const std::vector<uint8_t>& query, const std::vector<uint8_t>& response)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
-	auto response_buf = misc_utils::convertVectorToWpaBuf(response);
-	if (!query_buf || !response_buf) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	if (wpas_p2p_service_add_bonjour(
-		wpa_s, query_buf.get(), response_buf.get())) {
-		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, ""};
-}
-
-SupplicantStatus P2pIface::removeBonjourServiceInternal(
-    const std::vector<uint8_t>& query)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
-	if (!query_buf) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	if (wpas_p2p_service_del_bonjour(wpa_s, query_buf.get())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::addUpnpServiceInternal(
-    uint32_t version, const std::string& service_name)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (wpas_p2p_service_add_upnp(wpa_s, version, service_name.c_str())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::removeUpnpServiceInternal(
-    uint32_t version, const std::string& service_name)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (wpas_p2p_service_del_upnp(wpa_s, version, service_name.c_str())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::flushServicesInternal()
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	wpas_p2p_service_flush(wpa_s);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, uint64_t> P2pIface::requestServiceDiscoveryInternal(
-    const std::array<uint8_t, 6>& peer_address,
-    const std::vector<uint8_t>& query)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
-	if (!query_buf) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	const uint8_t* dst_addr = is_zero_ether_addr(peer_address.data())
-				      ? nullptr
-				      : peer_address.data();
-	uint64_t identifier =
-	    wpas_p2p_sd_request(wpa_s, dst_addr, query_buf.get());
-	if (identifier == 0) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, identifier};
-}
-
-SupplicantStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setMiracastModeInternal(
-    ISupplicantP2pIface::MiracastMode mode)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	uint8_t mode_internal = convertHidlMiracastModeToInternal(mode);
-	const std::string cmd_str =
-	    kSetMiracastMode + std::to_string(mode_internal);
-	std::vector<char> cmd(
-	    cmd_str.c_str(), cmd_str.c_str() + cmd_str.size() + 1);
-	char driver_cmd_reply_buf[4096] = {};
-	if (wpa_drv_driver_cmd(
-		wpa_s, cmd.data(), driver_cmd_reply_buf,
-		sizeof(driver_cmd_reply_buf))) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::startWpsPbcInternal(
-    const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
-{
-	struct wpa_supplicant* wpa_group_s =
-	    retrieveGroupIfacePtr(group_ifname);
-	if (!wpa_group_s) {
-		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-	const uint8_t* bssid_addr =
-	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
-#ifdef CONFIG_AP
-	if (wpa_group_s->ap_iface) {
-		if (wpa_supplicant_ap_wps_pbc(wpa_group_s, bssid_addr, NULL)) {
-			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-		}
-		return {SupplicantStatusCode::SUCCESS, ""};
-	}
-#endif /* CONFIG_AP */
-	if (wpas_wps_start_pbc(wpa_group_s, bssid_addr, 0, 0)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::startWpsPinKeypadInternal(
-    const std::string& group_ifname, const std::string& pin)
-{
-	struct wpa_supplicant* wpa_group_s =
-	    retrieveGroupIfacePtr(group_ifname);
-	if (!wpa_group_s) {
-		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-#ifdef CONFIG_AP
-	if (wpa_group_s->ap_iface) {
-		if (wpa_supplicant_ap_wps_pin(
-			wpa_group_s, nullptr, pin.c_str(), nullptr, 0, 0) < 0) {
-			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-		}
-		return {SupplicantStatusCode::SUCCESS, ""};
-	}
-#endif /* CONFIG_AP */
-	if (wpas_wps_start_pin(
-		wpa_group_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, std::string> P2pIface::startWpsPinDisplayInternal(
-    const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
-{
-	struct wpa_supplicant* wpa_group_s =
-	    retrieveGroupIfacePtr(group_ifname);
-	if (!wpa_group_s) {
-		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""}, ""};
-	}
-	const uint8_t* bssid_addr =
-	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
-	int pin = wpas_wps_start_pin(
-	    wpa_group_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
-	if (pin < 0) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		misc_utils::convertWpsPinToString(pin)};
-}
-
-SupplicantStatus P2pIface::cancelWpsInternal(const std::string& group_ifname)
-{
-	struct wpa_supplicant* wpa_group_s =
-	    retrieveGroupIfacePtr(group_ifname);
-	if (!wpa_group_s) {
-		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-	if (wpas_wps_cancel(wpa_group_s)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setWpsDeviceNameInternal(const std::string& name)
-{
-	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
-}
-
-SupplicantStatus P2pIface::setWpsDeviceTypeInternal(
-    const std::array<uint8_t, 8>& type)
-{
-	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
-}
-
-SupplicantStatus P2pIface::setWpsManufacturerInternal(
-    const std::string& manufacturer)
-{
-	return iface_config_utils::setWpsManufacturer(
-	    retrieveIfacePtr(), manufacturer);
-}
-
-SupplicantStatus P2pIface::setWpsModelNameInternal(
-    const std::string& model_name)
-{
-	return iface_config_utils::setWpsModelName(
-	    retrieveIfacePtr(), model_name);
-}
-
-SupplicantStatus P2pIface::setWpsModelNumberInternal(
-    const std::string& model_number)
-{
-	return iface_config_utils::setWpsModelNumber(
-	    retrieveIfacePtr(), model_number);
-}
-
-SupplicantStatus P2pIface::setWpsSerialNumberInternal(
-    const std::string& serial_number)
-{
-	return iface_config_utils::setWpsSerialNumber(
-	    retrieveIfacePtr(), serial_number);
-}
-
-SupplicantStatus P2pIface::setWpsConfigMethodsInternal(uint16_t config_methods)
-{
-	return iface_config_utils::setWpsConfigMethods(
-	    retrieveIfacePtr(), config_methods);
-}
-
-SupplicantStatus P2pIface::enableWfdInternal(bool enable)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	wifi_display_enable(wpa_s->global, enable);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setWfdDeviceInfoInternal(
-    const std::array<uint8_t, 6>& info)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	std::vector<char> wfd_device_info_hex(info.size() * 2 + 1);
-	wpa_snprintf_hex(
-	    wfd_device_info_hex.data(), wfd_device_info_hex.size(), info.data(),
-	    info.size());
-	// |wifi_display_subelem_set| expects the first 2 bytes
-	// to hold the lenght of the subelement. In this case it's
-	// fixed to 6, so prepend that.
-	std::string wfd_device_info_set_cmd_str =
-	    std::to_string(kWfdDeviceInfoSubelemId) + " " +
-	    kWfdDeviceInfoSubelemLenHexStr + wfd_device_info_hex.data();
-	std::vector<char> wfd_device_info_set_cmd(
-	    wfd_device_info_set_cmd_str.c_str(),
-	    wfd_device_info_set_cmd_str.c_str() +
-		wfd_device_info_set_cmd_str.size() + 1);
-	if (wifi_display_subelem_set(
-		wpa_s->global, wfd_device_info_set_cmd.data())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	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, ""};
-}
-
-SupplicantStatus P2pIface::saveConfigInternal()
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	if (!wpa_s->conf->update_config) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::addGroup_1_2Internal(
-    const std::vector<uint8_t>& ssid, const std::string& passphrase,
-    bool persistent, uint32_t freq, const std::array<uint8_t, 6>& peer_address,
-    bool joinExistingGroup)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	int he = wpa_s->conf->p2p_go_he;
-	int vht = wpa_s->conf->p2p_go_vht;
-	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
-
-	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
-		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-	}
-
-	if (!isSsidValid(ssid)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, "SSID is invalid."};
-	}
-
-	if (!isPskPassphraseValid(passphrase)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, "passphrase is invalid."};
-	}
-
-	if (!joinExistingGroup) {
-		struct p2p_data *p2p = wpa_s->global->p2p;
-		os_memcpy(p2p->ssid, ssid.data(), ssid.size());
-		p2p->ssid_len = ssid.size();
-		p2p->ssid_set = 1;
-
-		os_memset(p2p->passphrase, 0, sizeof(p2p->passphrase));
-		os_memcpy(p2p->passphrase, passphrase.c_str(), passphrase.length());
-		p2p->passphrase_set = 1;
-
-		if (wpas_p2p_group_add(
-		    wpa_s, persistent, freq, 0, ht40, vht,
-		    CHANWIDTH_USE_HT, he, 0)) {
-			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 (pending_scan_res_join_callback != NULL) {
-		wpa_printf(MSG_WARNING, "P2P: Renew scan result callback with new request.");
-	}
-
-	pending_join_scan_callback =
-	    [wpa_s, ssid, freq]() {
-		if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
-			return;
-		}
-		int ret = joinScanReq(wpa_s, ssid, freq);
-		// for BUSY case, the scan might be occupied by WiFi.
-		// Do not give up immediately, but try again later.
-		if (-EBUSY == ret) {
-			// re-schedule this join scan and don't consume retry count.
-			if (pending_scan_res_join_callback) {
-				pending_scan_res_join_callback();
-			}
-		} else if (0 != ret) {
-			notifyGroupJoinFailure(wpa_s);
-			pending_scan_res_join_callback = NULL;
-		}
-	};
-
-	pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, freq, this]() {
-		if (wpa_s->global->p2p == NULL || 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) {
-			wpa_s->global->p2p_go_found_external_scan = 1;
-			if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
-				wpa_printf(MSG_ERROR, "P2P: Failed to join a group.");
-				wpa_s->global->p2p_go_found_external_scan = 0;
-			}
-			// 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_printf(MSG_DEBUG, "P2P: Join scan count %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(0, getP2pJoinScanIntervalUsecs(freq),
-			    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;
-	pending_join_scan_callback();
-	if (pending_scan_res_join_callback == NULL) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, "Failed to start scan."};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus P2pIface::setMacRandomizationInternal(bool enable)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	bool currentEnabledState = !!wpa_s->conf->p2p_device_random_mac_addr;
-	u8 *addr = NULL;
-
-	// The same state, no change is needed.
-	if (currentEnabledState == enable) {
-		wpa_printf(MSG_DEBUG, "The random MAC is %s already.",
-		    (enable) ? "enabled" : "disabled");
-		return {SupplicantStatusCode::SUCCESS, ""};
-	}
-
-	if (enable) {
-		wpa_s->conf->p2p_device_random_mac_addr = 1;
-		wpa_s->conf->p2p_interface_random_mac_addr = 1;
-
-		// restore config if it failed to set up MAC address.
-		if (wpas_p2p_mac_setup(wpa_s) < 0) {
-			wpa_s->conf->p2p_device_random_mac_addr = 0;
-			wpa_s->conf->p2p_interface_random_mac_addr = 0;
-			return {SupplicantStatusCode::FAILURE_UNKNOWN,
-			    "Failed to set up MAC address."};
-		}
-	} else {
-		// disable random MAC will use original MAC address
-		// regardless of any saved persistent groups.
-		if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
-			wpa_printf(MSG_ERROR, "Failed to restore MAC address");
-			return {SupplicantStatusCode::FAILURE_UNKNOWN,
-			    "Failed to restore MAC address."};
-		}
-
-		if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
-			wpa_printf(MSG_INFO, "Could not update MAC address information");
-			return {SupplicantStatusCode::FAILURE_UNKNOWN,
-			    "Failed to update MAC address."};
-		}
-		wpa_s->conf->p2p_device_random_mac_addr = 0;
-		wpa_s->conf->p2p_interface_random_mac_addr = 0;
-	}
-
-	// update internal data to send out correct device address in action frame.
-	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
-	os_memcpy(wpa_s->global->p2p->cfg->dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
-
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-V1_4::SupplicantStatus P2pIface::setEdmgInternal(bool enable)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	wpa_printf(MSG_DEBUG, "set p2p_go_edmg to %d", enable);
-	wpa_s->conf->p2p_go_edmg = enable ? 1 : 0;
-	wpa_s->p2p_go_edmg = enable ? 1 : 0;
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<V1_4::SupplicantStatus, bool> P2pIface::getEdmgInternal()
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	return {{V1_4::SupplicantStatusCode::SUCCESS, ""},
-		(wpa_s->p2p_go_edmg == 1)};
-}
-
-V1_4::SupplicantStatus P2pIface::registerCallback_1_4Internal(
-    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback)
-{
-	HidlManager* hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
-		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-V1_4::SupplicantStatus P2pIface::setWfdR2DeviceInfoInternal(
-    const std::array<uint8_t, 4>& info)
-{
-	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
-	uint32_t wfd_r2_device_info_hex_len = info.size() * 2 + 1;
-	std::vector<char> wfd_r2_device_info_hex(wfd_r2_device_info_hex_len);
-	wpa_snprintf_hex(
-	    wfd_r2_device_info_hex.data(), wfd_r2_device_info_hex.size(),
-	    info.data(),info.size());
-	std::string wfd_r2_device_info_set_cmd_str =
-	     std::to_string(kWfdR2DeviceInfoSubelemId) + " " +
-	     wfd_r2_device_info_hex.data();
-	std::vector<char> wfd_r2_device_info_set_cmd(
-	     wfd_r2_device_info_set_cmd_str.c_str(),
-	     wfd_r2_device_info_set_cmd_str.c_str() +
-	     wfd_r2_device_info_set_cmd_str.size() + 1);
-	if (wifi_display_subelem_set(
-		wpa_s->global, wfd_r2_device_info_set_cmd.data())) {
-		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-/**
- * Retrieve the underlying |wpa_supplicant| struct
- * pointer for this iface.
- * If the underlying iface is removed, then all RPC method calls on this object
- * will return failure.
- */
-wpa_supplicant* P2pIface::retrieveIfacePtr()
-{
-	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
-}
-
-/**
- * Retrieve the underlying |wpa_supplicant| struct
- * pointer for this group iface.
- */
-wpa_supplicant* P2pIface::retrieveGroupIfacePtr(const std::string& group_ifname)
-{
-	return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
-}
-
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.h b/wpa_supplicant/hidl/1.4/p2p_iface.h
deleted file mode 100644
index c8ddc01..0000000
--- a/wpa_supplicant/hidl/1.4/p2p_iface.h
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_P2P_IFACE_H
-#define WPA_SUPPLICANT_HIDL_P2P_IFACE_H
-
-#include <array>
-#include <vector>
-
-#include <android-base/macros.h>
-
-#include <android/hardware/wifi/supplicant/1.4/ISupplicantP2pIface.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetwork.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/includes.h"
-#include "p2p/p2p.h"
-#include "p2p/p2p_i.h"
-#include "p2p_supplicant.h"
-#include "p2p_supplicant.h"
-#include "config.h"
-}
-
-#define P2P_MGMT_DEVICE_PREFIX       "p2p-dev-"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using V1_0::SupplicantNetworkId;
-using V1_0::SupplicantStatus;
-using V1_0::IfaceType;
-using V1_0::ISupplicantP2pIfaceCallback;
-using V1_0::ISupplicantP2pNetwork;
-
-/**
- * Implementation of P2pIface hidl object. Each unique hidl
- * object is used for control operations on a specific interface
- * controlled by wpa_supplicant.
- */
-class P2pIface : public V1_4::ISupplicantP2pIface
-{
-public:
-	P2pIface(struct wpa_global* wpa_global, const char ifname[]);
-	~P2pIface() override = default;
-	// Refer to |StaIface::invalidate()|.
-	void invalidate();
-	bool isValid();
-
-	// Hidl methods exposed.
-	Return<void> getName(getName_cb _hidl_cb) override;
-	Return<void> getType(getType_cb _hidl_cb) override;
-	Return<void> addNetwork(addNetwork_cb _hidl_cb) override;
-	Return<void> removeNetwork(
-	    SupplicantNetworkId id, removeNetwork_cb _hidl_cb) override;
-	Return<void> getNetwork(
-	    SupplicantNetworkId id, getNetwork_cb _hidl_cb) override;
-	Return<void> listNetworks(listNetworks_cb _hidl_cb) override;
-	Return<void> registerCallback(
-	    const sp<ISupplicantP2pIfaceCallback>& callback,
-	    registerCallback_cb _hidl_cb) override;
-	Return<void> getDeviceAddress(getDeviceAddress_cb _hidl_cb) override;
-	Return<void> setSsidPostfix(
-	    const hidl_vec<uint8_t>& postfix,
-	    setSsidPostfix_cb _hidl_cb) override;
-	Return<void> setGroupIdle(
-	    const hidl_string& group_ifname, uint32_t timeout_in_sec,
-	    setGroupIdle_cb _hidl_cb) override;
-	Return<void> setPowerSave(
-	    const hidl_string& group_ifname, bool enable,
-	    setPowerSave_cb _hidl_cb) override;
-	Return<void> find(uint32_t timeout_in_sec, find_cb _hidl_cb) override;
-	Return<void> stopFind(stopFind_cb _hidl_cb) override;
-	Return<void> flush(flush_cb _hidl_cb) override;
-	Return<void> connect(
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
-	    const hidl_string& pre_selected_pin, bool join_existing_group,
-	    bool persistent, uint32_t go_intent, connect_cb _hidl_cb) override;
-	Return<void> cancelConnect(cancelConnect_cb _hidl_cb) override;
-	Return<void> provisionDiscovery(
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
-	    provisionDiscovery_cb _hidl_cb) override;
-	Return<void> addGroup(
-	    bool persistent, SupplicantNetworkId persistent_network_id,
-	    addGroup_cb _hidl_cb) override;
-	Return<void> removeGroup(
-	    const hidl_string& group_ifname, removeGroup_cb _hidl_cb) override;
-	Return<void> reject(
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    reject_cb _hidl_cb) override;
-	Return<void> invite(
-	    const hidl_string& group_ifname,
-	    const hidl_array<uint8_t, 6>& go_device_address,
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    invite_cb _hidl_cb) override;
-	Return<void> reinvoke(
-	    SupplicantNetworkId persistent_network_id,
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    reinvoke_cb _hidl_cb) override;
-	Return<void> configureExtListen(
-	    uint32_t period_in_millis, uint32_t interval_in_millis,
-	    configureExtListen_cb _hidl_cb) override;
-	Return<void> setListenChannel(
-	    uint32_t channel, uint32_t operating_class,
-	    setListenChannel_cb _hidl_cb) override;
-	Return<void> setDisallowedFrequencies(
-	    const hidl_vec<FreqRange>& ranges,
-	    setDisallowedFrequencies_cb _hidl_cb) override;
-	Return<void> getSsid(
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    getSsid_cb _hidl_cb) override;
-	Return<void> getGroupCapability(
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    getGroupCapability_cb _hidl_cb) override;
-	Return<void> addBonjourService(
-	    const hidl_vec<uint8_t>& query, const hidl_vec<uint8_t>& response,
-	    addBonjourService_cb _hidl_cb) override;
-	Return<void> removeBonjourService(
-	    const hidl_vec<uint8_t>& query,
-	    removeBonjourService_cb _hidl_cb) override;
-	Return<void> addUpnpService(
-	    uint32_t version, const hidl_string& service_name,
-	    addUpnpService_cb _hidl_cb) override;
-	Return<void> removeUpnpService(
-	    uint32_t version, const hidl_string& service_name,
-	    removeUpnpService_cb _hidl_cb) override;
-	Return<void> flushServices(flushServices_cb _hidl_cb) override;
-	Return<void> requestServiceDiscovery(
-	    const hidl_array<uint8_t, 6>& peer_address,
-	    const hidl_vec<uint8_t>& query,
-	    requestServiceDiscovery_cb _hidl_cb) override;
-	Return<void> cancelServiceDiscovery(
-	    uint64_t identifier, cancelServiceDiscovery_cb _hidl_cb) override;
-	Return<void> setMiracastMode(
-	    ISupplicantP2pIface::MiracastMode mode,
-	    setMiracastMode_cb _hidl_cb) override;
-	Return<void> startWpsPbc(
-	    const hidl_string& groupIfName, const hidl_array<uint8_t, 6>& bssid,
-	    startWpsPbc_cb _hidl_cb) override;
-	Return<void> startWpsPinKeypad(
-	    const hidl_string& groupIfName, const hidl_string& pin,
-	    startWpsPinKeypad_cb _hidl_cb) override;
-	Return<void> startWpsPinDisplay(
-	    const hidl_string& groupIfName, const hidl_array<uint8_t, 6>& bssid,
-	    startWpsPinDisplay_cb _hidl_cb) override;
-	Return<void> cancelWps(
-	    const hidl_string& groupIfName, cancelWps_cb _hidl_cb) override;
-	Return<void> setWpsDeviceName(
-	    const hidl_string& name, setWpsDeviceName_cb _hidl_cb) override;
-	Return<void> setWpsDeviceType(
-	    const hidl_array<uint8_t, 8>& type,
-	    setWpsDeviceType_cb _hidl_cb) override;
-	Return<void> setWpsManufacturer(
-	    const hidl_string& manufacturer,
-	    setWpsManufacturer_cb _hidl_cb) override;
-	Return<void> setWpsModelName(
-	    const hidl_string& model_name,
-	    setWpsModelName_cb _hidl_cb) override;
-	Return<void> setWpsModelNumber(
-	    const hidl_string& model_number,
-	    setWpsModelNumber_cb _hidl_cb) override;
-	Return<void> setWpsSerialNumber(
-	    const hidl_string& serial_number,
-	    setWpsSerialNumber_cb _hidl_cb) override;
-	Return<void> setWpsConfigMethods(
-	    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb) override;
-	Return<void> enableWfd(bool enable, enableWfd_cb _hidl_cb) override;
-	Return<void> setWfdDeviceInfo(
-	    const hidl_array<uint8_t, 6>& 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;
-	Return<void> saveConfig(saveConfig_cb _hidl_cb) override;
-	Return<void> addGroup_1_2(
-	    const hidl_vec<uint8_t>& ssid, const hidl_string& passphrase,
-	    bool persistent, uint32_t freq, const hidl_array<uint8_t, 6>& peer_address,
-	    bool joinExistingGroup, addGroup_1_2_cb _hidl_cb) override;
-	Return<void> setMacRandomization(
-	    bool enable, setMacRandomization_cb _hidl_cb) override;
-	Return<void> setEdmg(bool enable, setEdmg_cb _hidl_cb) override;
-	Return<void> getEdmg(getEdmg_cb _hidl_cb) override;
-	Return<void> registerCallback_1_4(
-	    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback,
-	    registerCallback_1_4_cb _hidl_cb) override;
-	Return<void> setWfdR2DeviceInfo(
-	    const hidl_array<uint8_t, 4>& info,
-	    setWfdR2DeviceInfo_cb _hidl_cb) override;
-
-private:
-	// Corresponding worker functions for the HIDL methods.
-	std::pair<SupplicantStatus, std::string> getNameInternal();
-	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
-	std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
-	addNetworkInternal();
-	SupplicantStatus removeNetworkInternal(SupplicantNetworkId id);
-	std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
-	getNetworkInternal(SupplicantNetworkId id);
-	std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
-	listNetworksInternal();
-	SupplicantStatus registerCallbackInternal(
-	    const sp<ISupplicantP2pIfaceCallback>& callback);
-	std::pair<SupplicantStatus, std::array<uint8_t, 6>>
-	getDeviceAddressInternal();
-	SupplicantStatus setSsidPostfixInternal(
-	    const std::vector<uint8_t>& postfix);
-	SupplicantStatus setGroupIdleInternal(
-	    const std::string& group_ifname, uint32_t timeout_in_sec);
-	SupplicantStatus setPowerSaveInternal(
-	    const std::string& group_ifname, bool enable);
-	SupplicantStatus findInternal(uint32_t timeout_in_sec);
-	SupplicantStatus stopFindInternal();
-	SupplicantStatus flushInternal();
-	std::pair<SupplicantStatus, std::string> connectInternal(
-	    const std::array<uint8_t, 6>& peer_address,
-	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
-	    const std::string& pre_selected_pin, bool join_existing_group,
-	    bool persistent, uint32_t go_intent);
-	SupplicantStatus cancelConnectInternal();
-	SupplicantStatus provisionDiscoveryInternal(
-	    const std::array<uint8_t, 6>& peer_address,
-	    ISupplicantP2pIface::WpsProvisionMethod provision_method);
-	SupplicantStatus addGroupInternal(
-	    bool persistent, SupplicantNetworkId persistent_network_id);
-	SupplicantStatus removeGroupInternal(const std::string& group_ifname);
-	SupplicantStatus rejectInternal(
-	    const std::array<uint8_t, 6>& peer_address);
-	SupplicantStatus inviteInternal(
-	    const std::string& group_ifname,
-	    const std::array<uint8_t, 6>& go_device_address,
-	    const std::array<uint8_t, 6>& peer_address);
-	SupplicantStatus reinvokeInternal(
-	    SupplicantNetworkId persistent_network_id,
-	    const std::array<uint8_t, 6>& peer_address);
-	SupplicantStatus configureExtListenInternal(
-	    uint32_t period_in_millis, uint32_t interval_in_millis);
-	SupplicantStatus setListenChannelInternal(
-	    uint32_t channel, uint32_t operating_class);
-	SupplicantStatus setDisallowedFrequenciesInternal(
-	    const std::vector<FreqRange>& ranges);
-	std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal(
-	    const std::array<uint8_t, 6>& peer_address);
-	std::pair<SupplicantStatus, uint32_t> getGroupCapabilityInternal(
-	    const std::array<uint8_t, 6>& peer_address);
-	SupplicantStatus addBonjourServiceInternal(
-	    const std::vector<uint8_t>& query,
-	    const std::vector<uint8_t>& response);
-	SupplicantStatus removeBonjourServiceInternal(
-	    const std::vector<uint8_t>& query);
-	SupplicantStatus addUpnpServiceInternal(
-	    uint32_t version, const std::string& service_name);
-	SupplicantStatus removeUpnpServiceInternal(
-	    uint32_t version, const std::string& service_name);
-	SupplicantStatus flushServicesInternal();
-	std::pair<SupplicantStatus, uint64_t> requestServiceDiscoveryInternal(
-	    const std::array<uint8_t, 6>& peer_address,
-	    const std::vector<uint8_t>& query);
-	SupplicantStatus cancelServiceDiscoveryInternal(uint64_t identifier);
-	SupplicantStatus setMiracastModeInternal(
-	    ISupplicantP2pIface::MiracastMode mode);
-	SupplicantStatus startWpsPbcInternal(
-	    const std::string& group_ifname,
-	    const std::array<uint8_t, 6>& bssid);
-	SupplicantStatus startWpsPinKeypadInternal(
-	    const std::string& group_ifname, const std::string& pin);
-	std::pair<SupplicantStatus, std::string> startWpsPinDisplayInternal(
-	    const std::string& group_ifname,
-	    const std::array<uint8_t, 6>& bssid);
-	SupplicantStatus cancelWpsInternal(const std::string& group_ifname);
-	SupplicantStatus setWpsDeviceNameInternal(const std::string& name);
-	SupplicantStatus setWpsDeviceTypeInternal(
-	    const std::array<uint8_t, 8>& type);
-	SupplicantStatus setWpsManufacturerInternal(
-	    const std::string& manufacturer);
-	SupplicantStatus setWpsModelNameInternal(const std::string& model_name);
-	SupplicantStatus setWpsModelNumberInternal(
-	    const std::string& model_number);
-	SupplicantStatus setWpsSerialNumberInternal(
-	    const std::string& serial_number);
-	SupplicantStatus setWpsConfigMethodsInternal(uint16_t config_methods);
-	SupplicantStatus enableWfdInternal(bool enable);
-	SupplicantStatus setWfdDeviceInfoInternal(
-	    const std::array<uint8_t, 6>& 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);
-	SupplicantStatus saveConfigInternal();
-	SupplicantStatus addGroup_1_2Internal(
-	    const std::vector<uint8_t>& ssid, const std::string& passphrase,
-	    bool persistent, uint32_t freq, const std::array<uint8_t, 6>& peer_address,
-	    bool joinExistingGroup);
-	SupplicantStatus setMacRandomizationInternal(bool enable);
-	V1_4::SupplicantStatus setEdmgInternal(bool enable);
-	std::pair<V1_4::SupplicantStatus, bool> getEdmgInternal();
-	V1_4::SupplicantStatus registerCallback_1_4Internal(
-	    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback);
-	V1_4::SupplicantStatus setWfdR2DeviceInfoInternal(
-	    const std::array<uint8_t, 4>& info);
-
-	struct wpa_supplicant* retrieveIfacePtr();
-	struct wpa_supplicant* retrieveGroupIfacePtr(
-	    const std::string& group_ifname);
-
-	// Reference to the global wpa_struct. This is assumed to be valid for
-	// the lifetime of the process.
-	struct wpa_global* wpa_global_;
-	// Name of the iface this hidl object controls
-	const std::string ifname_;
-	bool is_valid_;
-
-	DISALLOW_COPY_AND_ASSIGN(P2pIface);
-};
-
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WPA_SUPPLICANT_HIDL_P2P_IFACE_H
diff --git a/wpa_supplicant/hidl/1.4/p2p_network.cpp b/wpa_supplicant/hidl/1.4/p2p_network.cpp
deleted file mode 100644
index cba2fdd..0000000
--- a/wpa_supplicant/hidl/1.4/p2p_network.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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.
- */
-
-#include "hidl_manager.h"
-#include "hidl_return_util.h"
-#include "p2p_network.h"
-
-extern "C"
-{
-#include "config_ssid.h"
-}
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using V1_0::SupplicantStatusCode;
-
-P2pNetwork::P2pNetwork(
-    struct wpa_global *wpa_global, const char ifname[], int network_id)
-    : wpa_global_(wpa_global),
-      ifname_(ifname),
-      network_id_(network_id),
-      is_valid_(true)
-{}
-
-void P2pNetwork::invalidate() { is_valid_ = false; }
-bool P2pNetwork::isValid()
-{
-	return (is_valid_ && (retrieveNetworkPtr() != nullptr));
-}
-
-Return<void> P2pNetwork::getId(getId_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::getIdInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::getInterfaceNameInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::getType(getType_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::getTypeInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::registerCallback(
-    const sp<ISupplicantP2pNetworkCallback> &callback,
-    registerCallback_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::registerCallbackInternal, _hidl_cb, callback);
-}
-
-Return<void> P2pNetwork::getSsid(getSsid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::getSsidInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::getBssid(getBssid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::getBssidInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::isCurrent(isCurrent_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::isCurrentInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::isPersistent(isPersistent_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::isPersistentInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::isGo(isGo_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::isGoInternal, _hidl_cb);
-}
-
-Return<void> P2pNetwork::setClientList(
-    const hidl_vec<hidl_array<uint8_t, 6>> &clients, setClientList_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::setClientListInternal, _hidl_cb, clients);
-}
-
-Return<void> P2pNetwork::getClientList(getClientList_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &P2pNetwork::getClientListInternal, _hidl_cb);
-}
-
-std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
-}
-
-std::pair<SupplicantStatus, std::string> P2pNetwork::getInterfaceNameInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
-}
-
-std::pair<SupplicantStatus, IfaceType> P2pNetwork::getTypeInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
-}
-
-SupplicantStatus P2pNetwork::registerCallbackInternal(
-    const sp<ISupplicantP2pNetworkCallback> &callback)
-{
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager || hidl_manager->addP2pNetworkCallbackHidlObject(
-				 ifname_, network_id_, callback)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>> P2pNetwork::getSsidInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		{wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len}};
-}
-
-std::pair<SupplicantStatus, std::array<uint8_t, 6>>
-P2pNetwork::getBssidInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	std::array<uint8_t, 6> bssid{};
-	if (wpa_ssid->bssid_set) {
-		os_memcpy(bssid.data(), wpa_ssid->bssid, ETH_ALEN);
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, bssid};
-}
-
-std::pair<SupplicantStatus, bool> P2pNetwork::isCurrentInternal()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		(wpa_s->current_ssid == wpa_ssid)};
-}
-
-std::pair<SupplicantStatus, bool> P2pNetwork::isPersistentInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_ssid->disabled == 2)};
-}
-
-std::pair<SupplicantStatus, bool> P2pNetwork::isGoInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		(wpa_ssid->mode == wpas_mode::WPAS_MODE_P2P_GO)};
-}
-
-SupplicantStatus P2pNetwork::setClientListInternal(
-    const std::vector<hidl_array<uint8_t, 6>> &clients)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	os_free(wpa_ssid->p2p_client_list);
-	// Internal representation uses a generic MAC addr/mask storage format
-	// (even though the mask is always 0xFF'ed for p2p_client_list). So, the
-	// first 6 bytes holds the client MAC address and the next 6 bytes are
-	// OxFF'ed.
-	wpa_ssid->p2p_client_list =
-	    (u8 *)os_malloc(ETH_ALEN * 2 * clients.size());
-	if (!wpa_ssid->p2p_client_list) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	u8 *list = wpa_ssid->p2p_client_list;
-	for (const auto &client : clients) {
-		os_memcpy(list, client.data(), ETH_ALEN);
-		list += ETH_ALEN;
-		os_memset(list, 0xFF, ETH_ALEN);
-		list += ETH_ALEN;
-	}
-	wpa_ssid->num_p2p_clients = clients.size();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>>
-P2pNetwork::getClientListInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->p2p_client_list) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	std::vector<hidl_array<uint8_t, 6>> clients;
-	u8 *list = wpa_ssid->p2p_client_list;
-	for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) {
-		clients.emplace_back(list);
-		list += 2 * ETH_ALEN;
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, clients};
-}
-
-/**
- * Retrieve the underlying |wpa_ssid| struct pointer for
- * this network.
- * If the underlying network is removed or the interface
- * this network belong to is removed, all RPC method calls
- * on this object will return failure.
- */
-struct wpa_ssid *P2pNetwork::retrieveNetworkPtr()
-{
-	wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (!wpa_s)
-		return nullptr;
-	return wpa_config_get_network(wpa_s->conf, network_id_);
-}
-
-/**
- * Retrieve the underlying |wpa_supplicant| struct
- * pointer for this network.
- */
-struct wpa_supplicant *P2pNetwork::retrieveIfacePtr()
-{
-	return wpa_supplicant_get_iface(
-	    (struct wpa_global *)wpa_global_, ifname_.c_str());
-}
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wpa_supplicant/hidl/1.4/p2p_network.h b/wpa_supplicant/hidl/1.4/p2p_network.h
deleted file mode 100644
index 94e3763..0000000
--- a/wpa_supplicant/hidl/1.4/p2p_network.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
-#define WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
-
-#include <android-base/macros.h>
-
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetwork.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/includes.h"
-#include "wpa_supplicant_i.h"
-}
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using V1_0::ISupplicantP2pNetwork;
-using V1_0::ISupplicantP2pNetworkCallback;
-
-/**
- * Implementation of P2pNetwork hidl object. Each unique hidl
- * object is used for control operations on a specific network
- * controlled by wpa_supplicant.
- */
-class P2pNetwork : public ISupplicantP2pNetwork
-{
-public:
-	P2pNetwork(
-	    struct wpa_global* wpa_global, const char ifname[], int network_id);
-	~P2pNetwork() override = default;
-	// Refer to |StaIface::invalidate()|.
-	void invalidate();
-	bool isValid();
-
-	// Hidl methods exposed.
-	Return<void> getId(getId_cb _hidl_cb) override;
-	Return<void> getInterfaceName(getInterfaceName_cb _hidl_cb) override;
-	Return<void> getType(getType_cb _hidl_cb) override;
-	Return<void> registerCallback(
-	    const sp<ISupplicantP2pNetworkCallback>& callback,
-	    registerCallback_cb _hidl_cb) override;
-	Return<void> getSsid(getSsid_cb _hidl_cb) override;
-	Return<void> getBssid(getBssid_cb _hidl_cb) override;
-	Return<void> isCurrent(isCurrent_cb _hidl_cb) override;
-	Return<void> isPersistent(isPersistent_cb _hidl_cb) override;
-	Return<void> isGo(isGo_cb _hidl_cb) override;
-	Return<void> setClientList(
-	    const hidl_vec<hidl_array<uint8_t, 6>>& clients,
-	    setClientList_cb _hidl_cb) override;
-	Return<void> getClientList(getClientList_cb _hidl_cb) override;
-
-private:
-	// Corresponding worker functions for the HIDL methods.
-	std::pair<SupplicantStatus, uint32_t> getIdInternal();
-	std::pair<SupplicantStatus, std::string> getInterfaceNameInternal();
-	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
-	SupplicantStatus registerCallbackInternal(
-	    const sp<ISupplicantP2pNetworkCallback>& callback);
-	std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal();
-	std::pair<SupplicantStatus, std::array<uint8_t, 6>> getBssidInternal();
-	std::pair<SupplicantStatus, bool> isCurrentInternal();
-	std::pair<SupplicantStatus, bool> isPersistentInternal();
-	std::pair<SupplicantStatus, bool> isGoInternal();
-	SupplicantStatus setClientListInternal(
-	    const std::vector<hidl_array<uint8_t, 6>>& clients);
-	std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>>
-	getClientListInternal();
-
-	struct wpa_ssid* retrieveNetworkPtr();
-	struct wpa_supplicant* retrieveIfacePtr();
-
-	// Reference to the global wpa_struct. This is assumed to be valid
-	// for the lifetime of the process.
-	const struct wpa_global* wpa_global_;
-	// Name of the iface this network belongs to.
-	const std::string ifname_;
-	// Id of the network this hidl object controls.
-	const int network_id_;
-	bool is_valid_;
-
-	DISALLOW_COPY_AND_ASSIGN(P2pNetwork);
-};
-
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
deleted file mode 100644
index 1bf279e..0000000
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ /dev/null
@@ -1,1827 +0,0 @@
-/*
- * 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.
- */
-
-#include "hidl_manager.h"
-#include "hidl_return_util.h"
-#include "iface_config_utils.h"
-#include "misc_utils.h"
-#include "sta_iface.h"
-
-extern "C"
-{
-#include "utils/eloop.h"
-#include "gas_query.h"
-#include "interworking.h"
-#include "hs20_supplicant.h"
-#include "wps_supplicant.h"
-#include "dpp.h"
-#include "dpp_supplicant.h"
-#include "rsn_supp/wpa.h"
-#include "rsn_supp/pmksa_cache.h"
-}
-
-namespace {
-using ISupplicantStaNetworkV1_2 =
-	android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork;
-using ISupplicantStaNetworkV1_3 =
-	android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
-using android::hardware::wifi::V1_0::WifiChannelWidthInMhz;
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
-using android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
-using android::hardware::wifi::supplicant::V1_3::WifiTechnology;
-using android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface;
-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";
-constexpr char kStartRxFilter[] = "RXFILTER-START";
-constexpr char kStopRxFilter[] = "RXFILTER-STOP";
-constexpr char kAddRxFilter[] = "RXFILTER-ADD";
-constexpr char kRemoveRxFilter[] = "RXFILTER-REMOVE";
-constexpr char kSetBtCoexistenceMode[] = "BTCOEXMODE";
-constexpr char kSetBtCoexistenceScanStart[] = "BTCOEXSCAN-START";
-constexpr char kSetBtCoexistenceScanStop[] = "BTCOEXSCAN-STOP";
-constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
-constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
-constexpr char kSetCountryCode[] = "COUNTRY";
-constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec = static_cast<uint32_t>(
-    ISupplicantStaIface::ExtRadioWorkDefaults::TIMEOUT_IN_SECS);
-constexpr char kExtRadioWorkNamePrefix[] = "ext:";
-
-uint8_t convertHidlRxFilterTypeToInternal(
-    ISupplicantStaIface::RxFilterType type)
-{
-	switch (type) {
-	case ISupplicantStaIface::RxFilterType::V4_MULTICAST:
-		return 2;
-	case ISupplicantStaIface::RxFilterType::V6_MULTICAST:
-		return 3;
-	};
-	WPA_ASSERT(false);
-}
-
-uint8_t convertHidlBtCoexModeToInternal(
-    ISupplicantStaIface::BtCoexistenceMode mode)
-{
-	switch (mode) {
-	case ISupplicantStaIface::BtCoexistenceMode::ENABLED:
-		return 0;
-	case ISupplicantStaIface::BtCoexistenceMode::DISABLED:
-		return 1;
-	case ISupplicantStaIface::BtCoexistenceMode::SENSE:
-		return 2;
-	};
-	WPA_ASSERT(false);
-}
-
-SupplicantStatus doZeroArgDriverCommand(
-    struct wpa_supplicant *wpa_s, const char *cmd)
-{
-	std::vector<char> cmd_vec(cmd, cmd + strlen(cmd) + 1);
-	char driver_cmd_reply_buf[4096] = {};
-	if (wpa_drv_driver_cmd(
-		wpa_s, cmd_vec.data(), driver_cmd_reply_buf,
-		sizeof(driver_cmd_reply_buf))) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus doOneArgDriverCommand(
-    struct wpa_supplicant *wpa_s, const char *cmd, uint8_t arg)
-{
-	std::string cmd_str = std::string(cmd) + " " + std::to_string(arg);
-	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
-}
-
-SupplicantStatus doOneArgDriverCommand(
-    struct wpa_supplicant *wpa_s, const char *cmd, const std::string &arg)
-{
-	std::string cmd_str = std::string(cmd) + " " + arg;
-	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
-}
-
-void endExtRadioWork(struct wpa_radio_work *work)
-{
-	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
-	work->wpa_s->ext_work_in_progress = 0;
-	radio_work_done(work);
-	os_free(ework);
-}
-
-void extRadioWorkTimeoutCb(void *eloop_ctx, void *timeout_ctx)
-{
-	auto *work = static_cast<struct wpa_radio_work *>(eloop_ctx);
-	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
-	wpa_dbg(
-	    work->wpa_s, MSG_DEBUG, "Timing out external radio work %u (%s)",
-	    ework->id, work->type);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	WPA_ASSERT(hidl_manager);
-	hidl_manager->notifyExtRadioWorkTimeout(work->wpa_s, ework->id);
-
-	endExtRadioWork(work);
-}
-
-void startExtRadioWork(struct wpa_radio_work *work)
-{
-	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
-	work->wpa_s->ext_work_in_progress = 1;
-	if (!ework->timeout) {
-		ework->timeout = kExtRadioWorkDefaultTimeoutInSec;
-	}
-	eloop_register_timeout(
-	    ework->timeout, 0, extRadioWorkTimeoutCb, work, nullptr);
-}
-
-void extRadioWorkStartCb(struct wpa_radio_work *work, int deinit)
-{
-	// deinit==1 is invoked during interface removal. Since the HIDL
-	// interface does not support interface addition/removal, we don't
-	// need to handle this scenario.
-	WPA_ASSERT(!deinit);
-
-	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
-	wpa_dbg(
-	    work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
-	    ework->id, ework->type);
-
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	WPA_ASSERT(hidl_manager);
-	hidl_manager->notifyExtRadioWorkStart(work->wpa_s, ework->id);
-
-	startExtRadioWork(work);
-}
-
-uint32_t convertWpaKeyMgmtCapabilitiesToHidl (
-    struct wpa_supplicant *wpa_s, struct wpa_driver_capa *capa) {
-
-	uint32_t mask = 0;
-	/* Logic from ctrl_iface.c, NONE and IEEE8021X have no capability
-	 * flags and always enabled.
-	 */
-	mask |=
-	    (ISupplicantStaNetwork::KeyMgmtMask::NONE |
-	     ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X);
-
-	if (capa->key_mgmt &
-	    (WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
-		mask |= ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP;
-	}
-
-	if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
-			     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
-		mask |= ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK;
-	}
-#ifdef CONFIG_SUITEB192
-	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
-		mask |= ISupplicantStaNetworkV1_2::ISupplicantStaNetwork::KeyMgmtMask::SUITE_B_192;
-	}
-#endif /* CONFIG_SUITEB192 */
-#ifdef CONFIG_OWE
-	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
-		mask |= ISupplicantStaNetworkV1_2::ISupplicantStaNetwork::KeyMgmtMask::OWE;
-	}
-#endif /* CONFIG_OWE */
-#ifdef CONFIG_SAE
-	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
-		mask |= ISupplicantStaNetworkV1_2::ISupplicantStaNetwork::KeyMgmtMask::SAE;
-	}
-#endif /* CONFIG_SAE */
-#ifdef CONFIG_DPP
-	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
-		mask |= ISupplicantStaNetworkV1_2::ISupplicantStaNetwork::KeyMgmtMask::DPP;
-	}
-#endif
-#ifdef CONFIG_WAPI_INTERFACE
-	mask |= ISupplicantStaNetworkV1_3::ISupplicantStaNetwork::KeyMgmtMask::WAPI_PSK;
-	mask |= ISupplicantStaNetworkV1_3::ISupplicantStaNetwork::KeyMgmtMask::WAPI_CERT;
-#endif /* CONFIG_WAPI_INTERFACE */
-#ifdef CONFIG_FILS
-	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
-		mask |= ISupplicantStaNetworkV1_3::ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256;
-	}
-	if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
-		mask |= ISupplicantStaNetworkV1_3::ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384;
-	}
-#endif /* CONFIG_FILS */
-	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 {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using V1_0::ISupplicantStaIfaceCallback;
-using V1_0::SupplicantStatusCode;
-
-StaIface::StaIface(struct wpa_global *wpa_global, const char ifname[])
-    : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
-{}
-
-void StaIface::invalidate() { is_valid_ = false; }
-bool StaIface::isValid()
-{
-	return (is_valid_ && (retrieveIfacePtr() != nullptr));
-}
-
-Return<void> StaIface::getName(getName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::getNameInternal, _hidl_cb);
-}
-
-Return<void> StaIface::getType(getType_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::getTypeInternal, _hidl_cb);
-}
-
-Return<void> StaIface::addNetwork(addNetwork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::addNetworkInternal, _hidl_cb);
-}
-
-Return<void> StaIface::removeNetwork(
-    SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::removeNetworkInternal, _hidl_cb, id);
-}
-
-Return<void> StaIface::filsHlpFlushRequest(filsHlpFlushRequest_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::filsHlpFlushRequestInternal, _hidl_cb);
-}
-
-Return<void> StaIface::filsHlpAddRequest(
-    const hidl_array<uint8_t, 6> &dst_mac, const hidl_vec<uint8_t> &pkt,
-    filsHlpAddRequest_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::filsHlpAddRequestInternal, _hidl_cb, dst_mac, pkt);
-}
-
-Return<void> StaIface::getNetwork(
-    SupplicantNetworkId id, getNetwork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::getNetworkInternal, _hidl_cb, id);
-}
-
-Return<void> StaIface::listNetworks(listNetworks_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::listNetworksInternal, _hidl_cb);
-}
-
-Return<void> StaIface::registerCallback(
-    const sp<ISupplicantStaIfaceCallback> &callback,
-    registerCallback_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::registerCallbackInternal, _hidl_cb, callback);
-}
-
-Return<void> StaIface::registerCallback_1_1(
-    const sp<V1_1::ISupplicantStaIfaceCallback> &callback,
-    registerCallback_cb _hidl_cb)
-{
-	sp<V1_0::ISupplicantStaIfaceCallback> callback_1_0 = callback;
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &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::registerCallback_1_3(
-    const sp<V1_3::ISupplicantStaIfaceCallback> &callback,
-    registerCallback_cb _hidl_cb)
-{
-	sp<V1_3::ISupplicantStaIfaceCallback> callback_1_3 = callback;
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::registerCallbackInternal, _hidl_cb, callback_1_3);
-}
-
-Return<void> StaIface::registerCallback_1_4(
-    const sp<V1_4::ISupplicantStaIfaceCallback> &callback,
-    registerCallback_1_4_cb _hidl_cb)
-{
-	sp<V1_4::ISupplicantStaIfaceCallback> callback_1_4 = callback;
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::registerCallbackInternal_1_4, _hidl_cb, callback_1_4);
-}
-
-Return<void> StaIface::reassociate(reassociate_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::reassociateInternal, _hidl_cb);
-}
-
-Return<void> StaIface::reconnect(reconnect_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::reconnectInternal, _hidl_cb);
-}
-
-Return<void> StaIface::disconnect(disconnect_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::disconnectInternal, _hidl_cb);
-}
-
-Return<void> StaIface::setPowerSave(bool enable, setPowerSave_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setPowerSaveInternal, _hidl_cb, enable);
-}
-
-Return<void> StaIface::initiateTdlsDiscover(
-    const hidl_array<uint8_t, 6> &mac_address, initiateTdlsDiscover_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::initiateTdlsDiscoverInternal, _hidl_cb, mac_address);
-}
-
-Return<void> StaIface::initiateTdlsSetup(
-    const hidl_array<uint8_t, 6> &mac_address, initiateTdlsSetup_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::initiateTdlsSetupInternal, _hidl_cb, mac_address);
-}
-
-Return<void> StaIface::initiateTdlsTeardown(
-    const hidl_array<uint8_t, 6> &mac_address, initiateTdlsTeardown_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::initiateTdlsTeardownInternal, _hidl_cb, mac_address);
-}
-Return<void> StaIface::initiateAnqpQuery(
-    const hidl_array<uint8_t, 6> &mac_address,
-    const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId> &info_elements,
-    const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types,
-    initiateAnqpQuery_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::initiateAnqpQueryInternal, _hidl_cb, mac_address,
-	    info_elements, sub_types);
-}
-
-Return<void> StaIface::initiateVenueUrlAnqpQuery(
-    const hidl_array<uint8_t, 6> &mac_address,
-	initiateVenueUrlAnqpQuery_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::initiateVenueUrlAnqpQueryInternal, _hidl_cb, mac_address);
-}
-
-Return<void> StaIface::initiateHs20IconQuery(
-    const hidl_array<uint8_t, 6> &mac_address, const hidl_string &file_name,
-    initiateHs20IconQuery_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::initiateHs20IconQueryInternal, _hidl_cb, mac_address,
-	    file_name);
-}
-
-Return<void> StaIface::getMacAddress(getMacAddress_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::getMacAddressInternal, _hidl_cb);
-}
-
-Return<void> StaIface::startRxFilter(startRxFilter_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::startRxFilterInternal, _hidl_cb);
-}
-
-Return<void> StaIface::stopRxFilter(stopRxFilter_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::stopRxFilterInternal, _hidl_cb);
-}
-
-Return<void> StaIface::addRxFilter(
-    ISupplicantStaIface::RxFilterType type, addRxFilter_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::addRxFilterInternal, _hidl_cb, type);
-}
-
-Return<void> StaIface::removeRxFilter(
-    ISupplicantStaIface::RxFilterType type, removeRxFilter_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::removeRxFilterInternal, _hidl_cb, type);
-}
-
-Return<void> StaIface::setBtCoexistenceMode(
-    ISupplicantStaIface::BtCoexistenceMode mode,
-    setBtCoexistenceMode_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setBtCoexistenceModeInternal, _hidl_cb, mode);
-}
-
-Return<void> StaIface::setBtCoexistenceScanModeEnabled(
-    bool enable, setBtCoexistenceScanModeEnabled_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setBtCoexistenceScanModeEnabledInternal, _hidl_cb,
-	    enable);
-}
-
-Return<void> StaIface::setSuspendModeEnabled(
-    bool enable, setSuspendModeEnabled_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setSuspendModeEnabledInternal, _hidl_cb, enable);
-}
-
-Return<void> StaIface::setCountryCode(
-    const hidl_array<int8_t, 2> &code, setCountryCode_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setCountryCodeInternal, _hidl_cb, code);
-}
-
-Return<void> StaIface::startWpsRegistrar(
-    const hidl_array<uint8_t, 6> &bssid, const hidl_string &pin,
-    startWpsRegistrar_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::startWpsRegistrarInternal, _hidl_cb, bssid, pin);
-}
-
-Return<void> StaIface::startWpsPbc(
-    const hidl_array<uint8_t, 6> &bssid, startWpsPbc_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::startWpsPbcInternal, _hidl_cb, bssid);
-}
-
-Return<void> StaIface::startWpsPinKeypad(
-    const hidl_string &pin, startWpsPinKeypad_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::startWpsPinKeypadInternal, _hidl_cb, pin);
-}
-
-Return<void> StaIface::startWpsPinDisplay(
-    const hidl_array<uint8_t, 6> &bssid, startWpsPinDisplay_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::startWpsPinDisplayInternal, _hidl_cb, bssid);
-}
-
-Return<void> StaIface::cancelWps(cancelWps_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::cancelWpsInternal, _hidl_cb);
-}
-
-Return<void> StaIface::setWpsDeviceName(
-    const hidl_string &name, setWpsDeviceName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setWpsDeviceNameInternal, _hidl_cb, name);
-}
-
-Return<void> StaIface::setWpsDeviceType(
-    const hidl_array<uint8_t, 8> &type, setWpsDeviceType_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setWpsDeviceTypeInternal, _hidl_cb, type);
-}
-
-Return<void> StaIface::setWpsManufacturer(
-    const hidl_string &manufacturer, setWpsManufacturer_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
-}
-
-Return<void> StaIface::setWpsModelName(
-    const hidl_string &model_name, setWpsModelName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setWpsModelNameInternal, _hidl_cb, model_name);
-}
-
-Return<void> StaIface::setWpsModelNumber(
-    const hidl_string &model_number, setWpsModelNumber_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setWpsModelNumberInternal, _hidl_cb, model_number);
-}
-
-Return<void> StaIface::setWpsSerialNumber(
-    const hidl_string &serial_number, setWpsSerialNumber_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
-}
-
-Return<void> StaIface::setWpsConfigMethods(
-    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
-}
-
-Return<void> StaIface::setExternalSim(
-    bool useExternalSim, setExternalSim_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::setExternalSimInternal, _hidl_cb, useExternalSim);
-}
-
-Return<void> StaIface::addExtRadioWork(
-    const hidl_string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec,
-    addExtRadioWork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::addExtRadioWorkInternal, _hidl_cb, name, freq_in_mhz,
-	    timeout_in_sec);
-}
-
-Return<void> StaIface::removeExtRadioWork(
-    uint32_t id, removeExtRadioWork_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::removeExtRadioWorkInternal, _hidl_cb, id);
-}
-
-Return<void> StaIface::enableAutoReconnect(
-    bool enable, enableAutoReconnect_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &StaIface::enableAutoReconnectInternal, _hidl_cb, enable);
-}
-
-Return<void> StaIface::getKeyMgmtCapabilities(
-    getKeyMgmtCapabilities_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &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);
-}
-
-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)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_UNKNOWN,
-	    &StaIface::getWpaDriverCapabilitiesInternal, _hidl_cb);
-}
-
-Return<void> StaIface::getWpaDriverCapabilities_1_4(
-		getWpaDriverCapabilities_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_UNKNOWN,
-	    &StaIface::getWpaDriverCapabilitiesInternal_1_4, _hidl_cb);
-}
-
-Return<void> StaIface::setMboCellularDataStatus(bool available,
-		setMboCellularDataStatus_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_UNKNOWN,
-	    &StaIface::setMboCellularDataStatusInternal, _hidl_cb, available);
-}
-
-Return<void> StaIface::getKeyMgmtCapabilities_1_3(
-    getKeyMgmtCapabilities_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaIface::getKeyMgmtCapabilitiesInternal_1_3, _hidl_cb);
-}
-
-std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
-}
-
-std::pair<SupplicantStatus, IfaceType> StaIface::getTypeInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::STA};
-}
-
-SupplicantStatus StaIface::filsHlpFlushRequestInternal()
-{
-#ifdef CONFIG_FILS
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-
-	wpas_flush_fils_hlp_req(wpa_s);
-	return {SupplicantStatusCode::SUCCESS, ""};
-#else /* CONFIG_FILS */
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-#endif /* CONFIG_FILS */
-}
-
-SupplicantStatus StaIface::filsHlpAddRequestInternal(
-    const std::array<uint8_t, 6> &dst_mac, const std::vector<uint8_t> &pkt)
-{
-#ifdef CONFIG_FILS
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct fils_hlp_req *req;
-
-	if (!pkt.size())
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-
-
-	req = (struct fils_hlp_req *)os_zalloc(sizeof(*req));
-	if (!req)
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-
-	os_memcpy(req->dst, dst_mac.data(), ETH_ALEN);
-
-	req->pkt = wpabuf_alloc_copy(pkt.data(), pkt.size());
-	if (!req->pkt) {
-		os_free(req);
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-
-	dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
-	return {SupplicantStatusCode::SUCCESS, ""};
-#else /* CONFIG_FILS */
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-#endif /* CONFIG_FILS */
-}
-
-std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
-StaIface::addNetworkInternal()
-{
-	android::sp<V1_3::ISupplicantStaNetwork> network;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
-	if (!ssid) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
-	}
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
-		wpa_s->ifname, ssid->id, &network)) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, network};
-}
-
-Return<void> StaIface::getConnectionCapabilities(
-    getConnectionCapabilities_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_UNKNOWN,
-	    &StaIface::getConnectionCapabilitiesInternal, _hidl_cb);
-}
-
-Return<void> StaIface::getConnectionCapabilities_1_4(
-    getConnectionCapabilities_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_UNKNOWN,
-	    &StaIface::getConnectionCapabilitiesInternal_1_4, _hidl_cb);
-}
-
-SupplicantStatus StaIface::removeNetworkInternal(SupplicantNetworkId id)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	int result = wpa_supplicant_remove_network(wpa_s, id);
-	if (result == -1) {
-		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
-	}
-	if (result != 0) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
-StaIface::getNetworkInternal(SupplicantNetworkId id)
-{
-	android::sp<V1_3::ISupplicantStaNetwork> network;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);
-	if (!ssid) {
-		return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
-			network};
-	}
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
-		wpa_s->ifname, ssid->id, &network)) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, network};
-}
-
-std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
-StaIface::listNetworksInternal()
-{
-	std::vector<SupplicantNetworkId> network_ids;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	for (struct wpa_ssid *wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
-	     wpa_ssid = wpa_ssid->next) {
-		network_ids.emplace_back(wpa_ssid->id);
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
-}
-
-SupplicantStatus StaIface::registerCallbackInternal(
-    const sp<ISupplicantStaIfaceCallback> &callback)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-V1_4::SupplicantStatus StaIface::registerCallbackInternal_1_4(
-    const sp<V1_4::ISupplicantStaIfaceCallback> &callback)
-{
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->addStaIfaceCallbackHidlObject(ifname_, callback)) {
-		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::reassociateInternal()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
-		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-	}
-	wpas_request_connection(wpa_s);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::reconnectInternal()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
-		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-	}
-	if (!wpa_s->disconnected) {
-		return {SupplicantStatusCode::FAILURE_IFACE_NOT_DISCONNECTED,
-			""};
-	}
-	wpas_request_connection(wpa_s);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::disconnectInternal()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
-		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-	}
-	wpas_request_disconnection(wpa_s);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::setPowerSaveInternal(bool enable)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
-		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-	}
-	if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::initiateTdlsDiscoverInternal(
-    const std::array<uint8_t, 6> &mac_address)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	int ret;
-	const u8 *peer = mac_address.data();
-	if (wpa_tdls_is_external_setup(wpa_s->wpa)) {
-		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
-	} else {
-		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
-	}
-	if (ret) {
-		wpa_printf(MSG_INFO, "StaIface: TDLS discover failed: %d", ret);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::initiateTdlsSetupInternal(
-    const std::array<uint8_t, 6> &mac_address)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	int ret;
-	const u8 *peer = mac_address.data();
-	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
-	    !(wpa_s->conf->tdls_external_control)) {
-		wpa_tdls_remove(wpa_s->wpa, peer);
-		ret = wpa_tdls_start(wpa_s->wpa, peer);
-	} else {
-		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
-	}
-	if (ret) {
-		wpa_printf(MSG_INFO, "StaIface: TDLS setup failed: %d", ret);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::initiateTdlsTeardownInternal(
-    const std::array<uint8_t, 6> &mac_address)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	int ret;
-	const u8 *peer = mac_address.data();
-	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
-	    !(wpa_s->conf->tdls_external_control)) {
-		ret = wpa_tdls_teardown_link(
-		    wpa_s->wpa, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
-	} else {
-		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
-	}
-	if (ret) {
-		wpa_printf(MSG_INFO, "StaIface: TDLS teardown failed: %d", ret);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::initiateAnqpQueryInternal(
-    const std::array<uint8_t, 6> &mac_address,
-    const std::vector<ISupplicantStaIface::AnqpInfoId> &info_elements,
-    const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (info_elements.size() > kMaxAnqpElems) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	uint16_t info_elems_buf[kMaxAnqpElems];
-	uint32_t num_info_elems = 0;
-	for (const auto &info_element : info_elements) {
-		info_elems_buf[num_info_elems++] =
-		    static_cast<std::underlying_type<
-			ISupplicantStaIface::AnqpInfoId>::type>(info_element);
-	}
-	uint32_t sub_types_bitmask = 0;
-	for (const auto &type : sub_types) {
-		sub_types_bitmask |= BIT(
-		    static_cast<std::underlying_type<
-			ISupplicantStaIface::Hs20AnqpSubtypes>::type>(type));
-	}
-
-	if (anqp_send_req(
-		wpa_s, mac_address.data(), 0, info_elems_buf, num_info_elems,
-		sub_types_bitmask, 0)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-V1_4::SupplicantStatus StaIface::initiateVenueUrlAnqpQueryInternal(
-    const std::array<uint8_t, 6> &mac_address)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	uint16_t info_elems_buf[1] = {ANQP_VENUE_URL};
-
-	if (anqp_send_req(
-		wpa_s, mac_address.data(), 0, info_elems_buf, 1, 0, 0)) {
-		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::initiateHs20IconQueryInternal(
-    const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	wpa_s->fetch_osu_icon_in_progress = 0;
-	if (hs20_anqp_send_req(
-		wpa_s, mac_address.data(), BIT(HS20_STYPE_ICON_REQUEST),
-		reinterpret_cast<const uint8_t *>(file_name.c_str()),
-		file_name.size(), true)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, std::array<uint8_t, 6>>
-StaIface::getMacAddressInternal()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	std::vector<char> cmd(
-	    kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
-	char driver_cmd_reply_buf[4096] = {};
-	int ret = wpa_drv_driver_cmd(
-	    wpa_s, cmd.data(), driver_cmd_reply_buf,
-	    sizeof(driver_cmd_reply_buf));
-	// Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
-	std::string reply_str = driver_cmd_reply_buf;
-	if (ret < 0 || reply_str.empty() ||
-	    reply_str.find("=") == std::string::npos) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	// Remove all whitespace first and then split using the delimiter "=".
-	reply_str.erase(
-	    remove_if(reply_str.begin(), reply_str.end(), isspace),
-	    reply_str.end());
-	std::string mac_addr_str =
-	    reply_str.substr(reply_str.find("=") + 1, reply_str.size());
-	std::array<uint8_t, 6> mac_addr;
-	if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, mac_addr};
-}
-
-SupplicantStatus StaIface::startRxFilterInternal()
-{
-	return doZeroArgDriverCommand(retrieveIfacePtr(), kStartRxFilter);
-}
-
-SupplicantStatus StaIface::stopRxFilterInternal()
-{
-	return doZeroArgDriverCommand(retrieveIfacePtr(), kStopRxFilter);
-}
-
-SupplicantStatus StaIface::addRxFilterInternal(
-    ISupplicantStaIface::RxFilterType type)
-{
-	return doOneArgDriverCommand(
-	    retrieveIfacePtr(), kAddRxFilter,
-	    convertHidlRxFilterTypeToInternal(type));
-}
-
-SupplicantStatus StaIface::removeRxFilterInternal(
-    ISupplicantStaIface::RxFilterType type)
-{
-	return doOneArgDriverCommand(
-	    retrieveIfacePtr(), kRemoveRxFilter,
-	    convertHidlRxFilterTypeToInternal(type));
-}
-
-SupplicantStatus StaIface::setBtCoexistenceModeInternal(
-    ISupplicantStaIface::BtCoexistenceMode mode)
-{
-	return doOneArgDriverCommand(
-	    retrieveIfacePtr(), kSetBtCoexistenceMode,
-	    convertHidlBtCoexModeToInternal(mode));
-}
-
-SupplicantStatus StaIface::setBtCoexistenceScanModeEnabledInternal(bool enable)
-{
-	const char *cmd;
-	if (enable) {
-		cmd = kSetBtCoexistenceScanStart;
-	} else {
-		cmd = kSetBtCoexistenceScanStop;
-	}
-	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
-}
-
-SupplicantStatus StaIface::setSuspendModeEnabledInternal(bool enable)
-{
-	const char *cmd;
-	if (enable) {
-		cmd = kSetSupendModeEnabled;
-	} else {
-		cmd = kSetSupendModeDisabled;
-	}
-	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
-}
-
-SupplicantStatus StaIface::setCountryCodeInternal(
-    const std::array<int8_t, 2> &code)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	SupplicantStatus status = doOneArgDriverCommand(
-	    wpa_s, kSetCountryCode,
-	    std::string(std::begin(code), std::end(code)));
-	if (status.code != SupplicantStatusCode::SUCCESS) {
-		return status;
-	}
-	struct p2p_data *p2p = wpa_s->global->p2p;
-	if (p2p) {
-		char country[3];
-		country[0] = code[0];
-		country[1] = code[1];
-		country[2] = 0x04;
-		p2p_set_country(p2p, country);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::startWpsRegistrarInternal(
-    const std::array<uint8_t, 6> &bssid, const std::string &pin)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpas_wps_start_reg(wpa_s, bssid.data(), pin.c_str(), nullptr)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::startWpsPbcInternal(
-    const std::array<uint8_t, 6> &bssid)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	const uint8_t *bssid_addr =
-	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
-	if (wpas_wps_start_pbc(wpa_s, bssid_addr, 0, 0)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::startWpsPinKeypadInternal(const std::string &pin)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpas_wps_start_pin(
-		wpa_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, std::string> StaIface::startWpsPinDisplayInternal(
-    const std::array<uint8_t, 6> &bssid)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	const uint8_t *bssid_addr =
-	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
-	int pin =
-	    wpas_wps_start_pin(wpa_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
-	if (pin < 0) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		misc_utils::convertWpsPinToString(pin)};
-}
-
-SupplicantStatus StaIface::cancelWpsInternal()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpas_wps_cancel(wpa_s)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaIface::setWpsDeviceNameInternal(const std::string &name)
-{
-	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
-}
-
-SupplicantStatus StaIface::setWpsDeviceTypeInternal(
-    const std::array<uint8_t, 8> &type)
-{
-	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
-}
-
-SupplicantStatus StaIface::setWpsManufacturerInternal(
-    const std::string &manufacturer)
-{
-	return iface_config_utils::setWpsManufacturer(
-	    retrieveIfacePtr(), manufacturer);
-}
-
-SupplicantStatus StaIface::setWpsModelNameInternal(
-    const std::string &model_name)
-{
-	return iface_config_utils::setWpsModelName(
-	    retrieveIfacePtr(), model_name);
-}
-
-SupplicantStatus StaIface::setWpsModelNumberInternal(
-    const std::string &model_number)
-{
-	return iface_config_utils::setWpsModelNumber(
-	    retrieveIfacePtr(), model_number);
-}
-
-SupplicantStatus StaIface::setWpsSerialNumberInternal(
-    const std::string &serial_number)
-{
-	return iface_config_utils::setWpsSerialNumber(
-	    retrieveIfacePtr(), serial_number);
-}
-
-SupplicantStatus StaIface::setWpsConfigMethodsInternal(uint16_t config_methods)
-{
-	return iface_config_utils::setWpsConfigMethods(
-	    retrieveIfacePtr(), config_methods);
-}
-
-SupplicantStatus StaIface::setExternalSimInternal(bool useExternalSim)
-{
-	return iface_config_utils::setExternalSim(
-	    retrieveIfacePtr(), useExternalSim);
-}
-
-std::pair<SupplicantStatus, uint32_t> StaIface::addExtRadioWorkInternal(
-    const std::string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	auto *ework = static_cast<struct wpa_external_work *>(
-	    os_zalloc(sizeof(struct wpa_external_work)));
-	if (!ework) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
-			UINT32_MAX};
-	}
-
-	std::string radio_work_name = kExtRadioWorkNamePrefix + name;
-	os_strlcpy(ework->type, radio_work_name.c_str(), sizeof(ework->type));
-	ework->timeout = timeout_in_sec;
-	wpa_s->ext_work_id++;
-	if (wpa_s->ext_work_id == 0) {
-		wpa_s->ext_work_id++;
-	}
-	ework->id = wpa_s->ext_work_id;
-
-	if (radio_add_work(
-		wpa_s, freq_in_mhz, ework->type, 0, extRadioWorkStartCb,
-		ework)) {
-		os_free(ework);
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
-			UINT32_MAX};
-	}
-	return {SupplicantStatus{SupplicantStatusCode::SUCCESS, ""}, ework->id};
-}
-
-SupplicantStatus StaIface::removeExtRadioWorkInternal(uint32_t id)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct wpa_radio_work *work;
-	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
-	{
-		if (os_strncmp(
-			work->type, kExtRadioWorkNamePrefix,
-			sizeof(kExtRadioWorkNamePrefix)) != 0)
-			continue;
-
-		auto *ework =
-		    static_cast<struct wpa_external_work *>(work->ctx);
-		if (ework->id != id)
-			continue;
-
-		wpa_dbg(
-		    wpa_s, MSG_DEBUG, "Completed external radio work %u (%s)",
-		    ework->id, ework->type);
-		eloop_cancel_timeout(extRadioWorkTimeoutCb, work, NULL);
-		endExtRadioWork(work);
-
-		return {SupplicantStatusCode::SUCCESS, ""};
-	}
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-}
-
-SupplicantStatus StaIface::enableAutoReconnectInternal(bool enable)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	wpa_s->auto_reconnect_disabled = enable ? 0 : 1;
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, uint32_t>
-StaIface::getKeyMgmtCapabilitiesInternal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-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 (dpp_bootstrap_remove(wpa_s->dpp, 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) : "";
-
-	/* 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) &&
-			(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, ""};
-		}
-	}
-
-	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;
-
-	if (net_role == DppNetRole::STA) {
-		/* DPP R2 connection status request */
-		cmd += " conn_status=1";
-	}
-
-	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
-}
-
-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()
-{
-  struct android::hardware::wifi::supplicant::V1_3::ConnectionCapabilities capa;
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, capa};
-}
-
-std::pair<V1_4::SupplicantStatus, ConnectionCapabilities>
-StaIface::getConnectionCapabilitiesInternal_1_4()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct ConnectionCapabilities capa;
-
-	if (wpa_s->connection_set) {
-		capa.legacyMode = LegacyMode::UNKNOWN;
-		if (wpa_s->connection_he) {
-			capa.V1_3.technology = WifiTechnology::HE;
-		} else if (wpa_s->connection_vht) {
-			capa.V1_3.technology = WifiTechnology::VHT;
-		} else if (wpa_s->connection_ht) {
-			capa.V1_3.technology = WifiTechnology::HT;
-		} else {
-			capa.V1_3.technology = WifiTechnology::LEGACY;
-			if (wpas_freq_to_band(wpa_s->assoc_freq) == BAND_2_4_GHZ) {
-				capa.legacyMode = (wpa_s->connection_11b_only) ? LegacyMode::B_MODE
-						: LegacyMode::G_MODE; 
-			} else {
-				capa.legacyMode = LegacyMode::A_MODE;
-			}
-		}
-		switch (wpa_s->connection_channel_bandwidth) {
-		case CHAN_WIDTH_20:
-			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
-			break;
-		case CHAN_WIDTH_40:
-			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_40;
-			break;
-		case CHAN_WIDTH_80:
-			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80;
-			break;
-		case CHAN_WIDTH_160:
-			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_160;
-			break;
-		case CHAN_WIDTH_80P80:
-			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80P80;
-			break;
-		default:
-			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
-			break;
-		}
-		capa.V1_3.maxNumberRxSpatialStreams = wpa_s->connection_max_nss_rx;
-		capa.V1_3.maxNumberTxSpatialStreams = wpa_s->connection_max_nss_tx;
-	} else {
-		capa.V1_3.technology = WifiTechnology::UNKNOWN;
-		capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
-		capa.V1_3.maxNumberTxSpatialStreams = 1;
-		capa.V1_3.maxNumberRxSpatialStreams = 1;
-		capa.legacyMode = LegacyMode::UNKNOWN;
-	}
-	return {{V1_4::SupplicantStatusCode::SUCCESS, ""}, capa};
-}
-
-std::pair<SupplicantStatus, uint32_t>
-StaIface::getWpaDriverCapabilitiesInternal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-std::pair<V1_4::SupplicantStatus, uint32_t>
-StaIface::getWpaDriverCapabilitiesInternal_1_4()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	uint32_t mask = 0;
-
-#ifdef CONFIG_MBO
-	/* MBO has no capability flags. It's mainly legacy 802.11v BSS
-	 * transition + Cellular steering. 11v is a default feature in
-	 * supplicant. And cellular steering is handled in framework.
-	 */
-	mask |= V1_3::WpaDriverCapabilitiesMask::MBO;
-	if (wpa_s->enable_oce & OCE_STA) {
-		mask |= V1_3::WpaDriverCapabilitiesMask::OCE;
-	}
-#endif
-#ifdef CONFIG_SAE_PK
-	mask |= V1_4::WpaDriverCapabilitiesMask::SAE_PK;
-#endif
-	mask |= V1_4::WpaDriverCapabilitiesMask::WFD_R2;
-
-	wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);
-
-	return {{V1_4::SupplicantStatusCode::SUCCESS, ""}, mask};
-}
-
-SupplicantStatus StaIface::setMboCellularDataStatusInternal(bool available)
-{
-#ifdef CONFIG_MBO
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	enum mbo_cellular_capa mbo_cell_capa;
-
-	if (available) {
-		mbo_cell_capa = MBO_CELL_CAPA_AVAILABLE;
-	} else {
-		mbo_cell_capa = MBO_CELL_CAPA_NOT_AVAILABLE;
-	}
-
-#ifdef ENABLE_PRIV_CMD_UPDATE_MBO_CELL_STATUS
-	char mbo_cmd[32];
-	char buf[32];
-
-	os_snprintf(mbo_cmd, sizeof(mbo_cmd), "%s %d", "MBO CELL_DATA_CAP", mbo_cell_capa);
-	if (wpa_drv_driver_cmd(wpa_s, mbo_cmd, buf, sizeof(buf)) < 0) {
-		wpa_printf(MSG_ERROR, "MBO CELL_DATA_CAP cmd failed CAP:%d", mbo_cell_capa);
-	}
-#else
-	wpas_mbo_update_cell_capa(wpa_s, mbo_cell_capa);
-#endif
-
-	return {SupplicantStatusCode::SUCCESS, ""};
-#else
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-#endif
-}
-
-std::pair<SupplicantStatus, uint32_t>
-StaIface::getKeyMgmtCapabilitiesInternal_1_3()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct wpa_driver_capa capa;
-	uint32_t mask = 0;
-
-	/* Get capabilities from driver and populate the key management mask */
-	if (wpa_drv_get_capa(wpa_s, &capa) < 0) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, mask};
-	}
-
-	return {{SupplicantStatusCode::SUCCESS, ""},
-	    convertWpaKeyMgmtCapabilitiesToHidl(wpa_s, &capa)};
-}
-
-/**
- * Retrieve the underlying |wpa_supplicant| struct
- * pointer for this iface.
- * If the underlying iface is removed, then all RPC method calls on this object
- * will return failure.
- */
-wpa_supplicant *StaIface::retrieveIfacePtr()
-{
-	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
-}
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
deleted file mode 100644
index d49e469..0000000
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_STA_IFACE_H
-#define WPA_SUPPLICANT_HIDL_STA_IFACE_H
-
-#include <array>
-#include <vector>
-
-#include <android-base/macros.h>
-
-#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIface.h>
-#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.h>
-#include <android/hardware/wifi/supplicant/1.3/ISupplicantStaNetwork.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/includes.h"
-#include "wpa_supplicant_i.h"
-#include "config.h"
-#include "driver_i.h"
-#include "wpa.h"
-}
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using V1_0::ISupplicantNetwork;
-using android::hardware::wifi::supplicant::V1_2::DppAkm;
-using android::hardware::wifi::supplicant::V1_2::DppNetRole;
-
-/**
- * Implementation of StaIface hidl object. Each unique hidl
- * object is used for control operations on a specific interface
- * controlled by wpa_supplicant.
- */
-class StaIface : public V1_4::ISupplicantStaIface
-{
-public:
-	StaIface(struct wpa_global* wpa_global, const char ifname[]);
-	~StaIface() override = default;
-	// HIDL does not provide a built-in mechanism to let the server
-	// invalidate a HIDL interface object after creation. If any client
-	// process holds onto a reference to the object in their context,
-	// any method calls on that reference will continue to be directed to
-	// the server.
-	// However Supplicant HAL needs to control the lifetime of these
-	// objects. So, add a public |invalidate| method to all |Iface| and
-	// |Network| objects.
-	// This will be used to mark an object invalid when the corresponding
-	// iface or network is removed.
-	// All HIDL method implementations should check if the object is still
-	// marked valid before processing them.
-	void invalidate();
-	bool isValid();
-
-	// Hidl methods exposed.
-	Return<void> getName(getName_cb _hidl_cb) override;
-	Return<void> getType(getType_cb _hidl_cb) override;
-	Return<void> addNetwork(addNetwork_cb _hidl_cb) override;
-	Return<void> removeNetwork(
-	    SupplicantNetworkId id, removeNetwork_cb _hidl_cb) override;
-	Return<void> filsHlpFlushRequest(
-	    filsHlpFlushRequest_cb _hidl_cb) override;
-	Return<void> filsHlpAddRequest(
-	    const hidl_array<uint8_t, 6>& dst_mac, const hidl_vec<uint8_t>& pkt,
-	    filsHlpAddRequest_cb _hidl_cb) override;
-	Return<void> getNetwork(
-	    SupplicantNetworkId id, getNetwork_cb _hidl_cb) override;
-	Return<void> listNetworks(listNetworks_cb _hidl_cb) override;
-	Return<void> registerCallback(
-	    const sp<V1_0::ISupplicantStaIfaceCallback>& callback,
-	    registerCallback_cb _hidl_cb) override;
-	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> registerCallback_1_3(
-	    const sp<V1_3::ISupplicantStaIfaceCallback>& callback,
-	    registerCallback_cb _hidl_cb) override;
-	Return<void> registerCallback_1_4(
-	    const sp<V1_4::ISupplicantStaIfaceCallback> &callback,
-	    registerCallback_1_4_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;
-	Return<void> setPowerSave(
-	    bool enable, setPowerSave_cb _hidl_cb) override;
-	Return<void> initiateTdlsDiscover(
-	    const hidl_array<uint8_t, 6>& mac_address,
-	    initiateTdlsDiscover_cb _hidl_cb) override;
-	Return<void> initiateTdlsSetup(
-	    const hidl_array<uint8_t, 6>& mac_address,
-	    initiateTdlsSetup_cb _hidl_cb) override;
-	Return<void> initiateTdlsTeardown(
-	    const hidl_array<uint8_t, 6>& mac_address,
-	    initiateTdlsTeardown_cb _hidl_cb) override;
-	Return<void> initiateAnqpQuery(
-	    const hidl_array<uint8_t, 6>& mac_address,
-	    const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId>& info_elements,
-	    const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes>& sub_types,
-	    initiateAnqpQuery_cb _hidl_cb) override;
-	Return<void> initiateVenueUrlAnqpQuery(
-	    const hidl_array<uint8_t, 6>& mac_address,
-		initiateVenueUrlAnqpQuery_cb _hidl_cb) override;
-	Return<void> initiateHs20IconQuery(
-	    const hidl_array<uint8_t, 6>& mac_address,
-	    const hidl_string& file_name,
-	    initiateHs20IconQuery_cb _hidl_cb) override;
-	Return<void> getMacAddress(getMacAddress_cb _hidl_cb) override;
-	Return<void> startRxFilter(startRxFilter_cb _hidl_cb) override;
-	Return<void> stopRxFilter(stopRxFilter_cb _hidl_cb) override;
-	Return<void> addRxFilter(
-	    ISupplicantStaIface::RxFilterType type,
-	    addRxFilter_cb _hidl_cb) override;
-	Return<void> removeRxFilter(
-	    ISupplicantStaIface::RxFilterType type,
-	    removeRxFilter_cb _hidl_cb) override;
-	Return<void> setBtCoexistenceMode(
-	    ISupplicantStaIface::BtCoexistenceMode mode,
-	    setBtCoexistenceMode_cb _hidl_cb) override;
-	Return<void> setBtCoexistenceScanModeEnabled(
-	    bool enable, setBtCoexistenceScanModeEnabled_cb _hidl_cb) override;
-	Return<void> setSuspendModeEnabled(
-	    bool enable, setSuspendModeEnabled_cb _hidl_cb) override;
-	Return<void> setCountryCode(
-	    const hidl_array<int8_t, 2>& code,
-	    setCountryCode_cb _hidl_cb) override;
-	Return<void> startWpsRegistrar(
-	    const hidl_array<uint8_t, 6>& bssid, const hidl_string& pin,
-	    startWpsRegistrar_cb _hidl_cb) override;
-	Return<void> startWpsPbc(
-	    const hidl_array<uint8_t, 6>& bssid,
-	    startWpsPbc_cb _hidl_cb) override;
-	Return<void> startWpsPinKeypad(
-	    const hidl_string& pin, startWpsPinKeypad_cb _hidl_cb) override;
-	Return<void> startWpsPinDisplay(
-	    const hidl_array<uint8_t, 6>& bssid,
-	    startWpsPinDisplay_cb _hidl_cb) override;
-	Return<void> cancelWps(cancelWps_cb _hidl_cb) override;
-	Return<void> setWpsDeviceName(
-	    const hidl_string& name, setWpsDeviceName_cb _hidl_cb) override;
-	Return<void> setWpsDeviceType(
-	    const hidl_array<uint8_t, 8>& type,
-	    setWpsDeviceType_cb _hidl_cb) override;
-	Return<void> setWpsManufacturer(
-	    const hidl_string& manufacturer,
-	    setWpsManufacturer_cb _hidl_cb) override;
-	Return<void> setWpsModelName(
-	    const hidl_string& model_name,
-	    setWpsModelName_cb _hidl_cb) override;
-	Return<void> setWpsModelNumber(
-	    const hidl_string& model_number,
-	    setWpsModelNumber_cb _hidl_cb) override;
-	Return<void> setWpsSerialNumber(
-	    const hidl_string& serial_number,
-	    setWpsSerialNumber_cb _hidl_cb) override;
-	Return<void> setWpsConfigMethods(
-	    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb) override;
-	Return<void> setExternalSim(
-	    bool useExternalSim, setExternalSim_cb _hidl_cb) override;
-	Return<void> addExtRadioWork(
-	    const hidl_string& name, uint32_t freq_in_mhz,
-	    uint32_t timeout_in_sec, addExtRadioWork_cb _hidl_cb) override;
-	Return<void> removeExtRadioWork(
-	    uint32_t id, removeExtRadioWork_cb _hidl_cb) override;
-	Return<void> enableAutoReconnect(
-	    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;
-	Return<void> getConnectionCapabilities(
-	    getConnectionCapabilities_cb _hidl_cb) override;
-	Return<void> getConnectionCapabilities_1_4(
-	    getConnectionCapabilities_1_4_cb _hidl_cb) override;
-	Return<void> getWpaDriverCapabilities(
-	    getWpaDriverCapabilities_cb _hidl_cb) override;
-	Return<void> setMboCellularDataStatus(bool available,
-	    setMboCellularDataStatus_cb _hidl_cb) override;
-	Return<void> getKeyMgmtCapabilities_1_3(
-	    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.
-	std::pair<SupplicantStatus, std::string> getNameInternal();
-	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
-	std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
-	addNetworkInternal();
-	SupplicantStatus filsHlpFlushRequestInternal();
-	SupplicantStatus filsHlpAddRequestInternal(
-	    const std::array<uint8_t, 6>& dst_mac,
-	    const std::vector<uint8_t>& pkt);
-	SupplicantStatus removeNetworkInternal(SupplicantNetworkId id);
-	std::pair<SupplicantStatus, sp<ISupplicantNetwork>> getNetworkInternal(
-	    SupplicantNetworkId id);
-	std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
-	listNetworksInternal();
-	SupplicantStatus registerCallbackInternal(
-	    const sp<V1_0::ISupplicantStaIfaceCallback>& callback);
-	SupplicantStatus registerCallbackInternal_1_1(
-	    const sp<V1_1::ISupplicantStaIfaceCallback>& callback);
-	V1_4::SupplicantStatus registerCallbackInternal_1_4(
-	    const sp<V1_4::ISupplicantStaIfaceCallback>& callback);
-	SupplicantStatus reassociateInternal();
-	SupplicantStatus reconnectInternal();
-	SupplicantStatus disconnectInternal();
-	SupplicantStatus setPowerSaveInternal(bool enable);
-	SupplicantStatus initiateTdlsDiscoverInternal(
-	    const std::array<uint8_t, 6>& mac_address);
-	SupplicantStatus initiateTdlsSetupInternal(
-	    const std::array<uint8_t, 6>& mac_address);
-	SupplicantStatus initiateTdlsTeardownInternal(
-	    const std::array<uint8_t, 6>& mac_address);
-	SupplicantStatus initiateAnqpQueryInternal(
-	    const std::array<uint8_t, 6>& mac_address,
-	    const std::vector<ISupplicantStaIface::AnqpInfoId>& info_elements,
-	    const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes>&
-		sub_types);
-	V1_4::SupplicantStatus initiateVenueUrlAnqpQueryInternal(
-	    const std::array<uint8_t, 6>& mac_address);
-	SupplicantStatus initiateHs20IconQueryInternal(
-	    const std::array<uint8_t, 6>& mac_address,
-	    const std::string& file_name);
-	std::pair<SupplicantStatus, std::array<uint8_t, 6>>
-	getMacAddressInternal();
-	SupplicantStatus startRxFilterInternal();
-	SupplicantStatus stopRxFilterInternal();
-	SupplicantStatus addRxFilterInternal(
-	    ISupplicantStaIface::RxFilterType type);
-	SupplicantStatus removeRxFilterInternal(
-	    ISupplicantStaIface::RxFilterType type);
-	SupplicantStatus setBtCoexistenceModeInternal(
-	    ISupplicantStaIface::BtCoexistenceMode mode);
-	SupplicantStatus setBtCoexistenceScanModeEnabledInternal(bool enable);
-	SupplicantStatus setSuspendModeEnabledInternal(bool enable);
-	SupplicantStatus setCountryCodeInternal(
-	    const std::array<int8_t, 2>& code);
-	SupplicantStatus startWpsRegistrarInternal(
-	    const std::array<uint8_t, 6>& bssid, const std::string& pin);
-	SupplicantStatus startWpsPbcInternal(
-	    const std::array<uint8_t, 6>& bssid);
-	SupplicantStatus startWpsPinKeypadInternal(const std::string& pin);
-	std::pair<SupplicantStatus, std::string> startWpsPinDisplayInternal(
-	    const std::array<uint8_t, 6>& bssid);
-	SupplicantStatus cancelWpsInternal();
-	SupplicantStatus setWpsDeviceNameInternal(const std::string& name);
-	SupplicantStatus setWpsDeviceTypeInternal(
-	    const std::array<uint8_t, 8>& type);
-	SupplicantStatus setWpsManufacturerInternal(
-	    const std::string& manufacturer);
-	SupplicantStatus setWpsModelNameInternal(const std::string& model_name);
-	SupplicantStatus setWpsModelNumberInternal(
-	    const std::string& model_number);
-	SupplicantStatus setWpsSerialNumberInternal(
-	    const std::string& serial_number);
-	SupplicantStatus setWpsConfigMethodsInternal(uint16_t config_methods);
-	SupplicantStatus setExternalSimInternal(bool useExternalSim);
-	std::pair<SupplicantStatus, uint32_t> addExtRadioWorkInternal(
-	    const std::string& name, uint32_t freq_in_mhz,
-	    uint32_t timeout_in_sec);
-	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();
-	std::pair<SupplicantStatus, V1_3::ConnectionCapabilities> getConnectionCapabilitiesInternal();
-	std::pair<V1_4::SupplicantStatus, V1_4::ConnectionCapabilities>
-			getConnectionCapabilitiesInternal_1_4();
-	std::pair<SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal();
-	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();
-
-	// Reference to the global wpa_struct. This is assumed to be valid for
-	// the lifetime of the process.
-	struct wpa_global* wpa_global_;
-	// Name of the iface this hidl object controls
-	const std::string ifname_;
-	bool is_valid_;
-
-	DISALLOW_COPY_AND_ASSIGN(StaIface);
-};
-
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WPA_SUPPLICANT_HIDL_STA_IFACE_H
diff --git a/wpa_supplicant/hidl/1.4/sta_network.cpp b/wpa_supplicant/hidl/1.4/sta_network.cpp
deleted file mode 100644
index ee132ac..0000000
--- a/wpa_supplicant/hidl/1.4/sta_network.cpp
+++ /dev/null
@@ -1,2657 +0,0 @@
-/*
- * 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.
- */
-
-#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::SupplicantStatus;
-using android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
-using ISupplicantStaNetworkV1_2 = android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork;
-using ISupplicantStaNetworkV1_3 = android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
-using ISupplicantStaNetworkV1_4 = android::hardware::wifi::supplicant::V1_4::ISupplicantStaNetwork;
-
-constexpr uint8_t kZeroBssid[6] = {0, 0, 0, 0, 0, 0};
-
-constexpr uint32_t kAllowedKeyMgmtMask =
-    (static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::NONE) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::FT_EAP) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::FT_PSK) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::OSEN) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_2::KeyMgmtMask::SAE) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_2::KeyMgmtMask::SUITE_B_192) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_2::KeyMgmtMask::OWE) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_2::KeyMgmtMask::WPA_PSK_SHA256) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_2::KeyMgmtMask::WPA_EAP_SHA256) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_3::KeyMgmtMask::WAPI_PSK) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_3::KeyMgmtMask::WAPI_CERT) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_3::KeyMgmtMask::FILS_SHA256) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_3::KeyMgmtMask::FILS_SHA384));
-constexpr uint32_t kAllowedProtoMask =
-    (static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::WPA) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::RSN) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::OSEN) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_3::ProtoMask::WAPI));
-constexpr uint32_t kAllowedAuthAlgMask =
-    (static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::OPEN) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::SHARED) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::LEAP) |
-	 static_cast<uint32_t>(ISupplicantStaNetworkV1_3::AuthAlgMask::SAE));
-constexpr uint32_t kAllowedGroupCipherMask =
-    (static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::WEP40) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::WEP104) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::TKIP) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::CCMP) |
-     static_cast<uint32_t>(
-	 ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_2::GroupCipherMask::GCMP_256) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_3::GroupCipherMask::SMS4) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_4::GroupCipherMask::GCMP_128));
-constexpr uint32_t kAllowedPairwisewCipherMask =
-    (static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::NONE) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::TKIP) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::CCMP) |
-     static_cast<uint32_t>(
-	 ISupplicantStaNetworkV1_2::PairwiseCipherMask::GCMP_256) |
-     static_cast<uint32_t>(
-	 ISupplicantStaNetworkV1_3::PairwiseCipherMask::SMS4) |
-     static_cast<uint32_t>(ISupplicantStaNetworkV1_4::PairwiseCipherMask::GCMP_128));
-constexpr uint32_t kAllowedGroupMgmtCipherMask =
-	(static_cast<uint32_t>(
-			ISupplicantStaNetworkV1_2::GroupMgmtCipherMask::BIP_GMAC_128) |
-	 static_cast<uint32_t>(
-			 ISupplicantStaNetworkV1_2::GroupMgmtCipherMask::BIP_GMAC_256) |
-	 static_cast<uint32_t>(
-			 ISupplicantStaNetworkV1_2::GroupMgmtCipherMask::BIP_CMAC_256));
-
-constexpr uint32_t kEapMethodMax =
-    static_cast<uint32_t>(ISupplicantStaNetwork::EapMethod::WFA_UNAUTH_TLS) + 1;
-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::AKA_PRIME) +
-    1;
-constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
-    "", "PAP", "MSCHAP", "MSCHAPV2", "GTC", "SIM", "AKA", "AKA'"};
-constexpr char kEapPhase2AuthPrefix[] = "auth=";
-constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
-constexpr char kNetworkEapSimGsmAuthResponse[] = "GSM-AUTH";
-constexpr char kNetworkEapSimUmtsAuthResponse[] = "UMTS-AUTH";
-constexpr char kNetworkEapSimUmtsAutsResponse[] = "UMTS-AUTS";
-constexpr char kNetworkEapSimGsmAuthFailure[] = "GSM-FAIL";
-constexpr char kNetworkEapSimUmtsAuthFailure[] = "UMTS-FAIL";
-
-#ifdef CONFIG_WAPI_INTERFACE
-std::string dummyWapiCertSuite;
-std::vector<uint8_t> dummyWapiPsk;
-#endif /* CONFIG_WAPI_INTERFACE */
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using V1_0::SupplicantStatus;
-using V1_0::SupplicantStatusCode;
-
-StaNetwork::StaNetwork(
-    struct wpa_global *wpa_global, const char ifname[], int network_id)
-    : wpa_global_(wpa_global),
-      ifname_(ifname),
-      network_id_(network_id),
-      is_valid_(true)
-{}
-
-void StaNetwork::invalidate() { is_valid_ = false; }
-bool StaNetwork::isValid()
-{
-	return (is_valid_ && (retrieveNetworkPtr() != nullptr));
-}
-
-Return<void> StaNetwork::getId(getId_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getIdInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getInterfaceNameInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getType(getType_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getTypeInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::registerCallback(
-    const sp<ISupplicantStaNetworkCallback> &callback,
-    registerCallback_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::registerCallbackInternal, _hidl_cb, callback);
-}
-
-Return<void> StaNetwork::registerCallback_1_4(
-    const sp<V1_4::ISupplicantStaNetworkCallback> &callback,
-    registerCallback_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::registerCallback_1_4Internal, _hidl_cb, callback);
-}
-
-Return<void> StaNetwork::setSsid(
-    const hidl_vec<uint8_t> &ssid, setSsid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setSsidInternal, _hidl_cb, ssid);
-}
-
-Return<void> StaNetwork::setBssid(
-    const hidl_array<uint8_t, 6> &bssid, setBssid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setBssidInternal, _hidl_cb, bssid);
-}
-
-Return<void> StaNetwork::setScanSsid(bool enable, setScanSsid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setScanSsidInternal, _hidl_cb, enable);
-}
-
-Return<void> StaNetwork::setKeyMgmt(
-    uint32_t key_mgmt_mask, setKeyMgmt_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setKeyMgmtInternal, _hidl_cb, key_mgmt_mask);
-}
-
-Return<void> StaNetwork::setProto(uint32_t proto_mask, setProto_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setProtoInternal, _hidl_cb, proto_mask);
-}
-
-Return<void> StaNetwork::setAuthAlg(
-    uint32_t auth_alg_mask,
-    std::function<void(const SupplicantStatus &status)> _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setAuthAlgInternal, _hidl_cb, auth_alg_mask);
-}
-
-Return<void> StaNetwork::setGroupCipher(
-    uint32_t group_cipher_mask, setGroupCipher_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setGroupCipherInternal, _hidl_cb, group_cipher_mask);
-}
-
-Return<void> StaNetwork::setPairwiseCipher(
-    uint32_t pairwise_cipher_mask, setPairwiseCipher_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setPairwiseCipherInternal, _hidl_cb,
-	    pairwise_cipher_mask);
-}
-
-Return<void> StaNetwork::setPskPassphrase(
-    const hidl_string &psk, setPskPassphrase_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setPskPassphraseInternal, _hidl_cb, psk);
-}
-
-Return<void> StaNetwork::setPsk(
-    const hidl_array<uint8_t, 32> &psk, setPsk_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setPskInternal, _hidl_cb, psk);
-}
-
-Return<void> StaNetwork::setWepKey(
-    uint32_t key_idx, const hidl_vec<uint8_t> &wep_key, setWepKey_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setWepKeyInternal, _hidl_cb, key_idx, wep_key);
-}
-
-Return<void> StaNetwork::setWepTxKeyIdx(
-    uint32_t key_idx, setWepTxKeyIdx_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setWepTxKeyIdxInternal, _hidl_cb, key_idx);
-}
-
-Return<void> StaNetwork::setRequirePmf(bool enable, setRequirePmf_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setRequirePmfInternal, _hidl_cb, enable);
-}
-
-Return<void> StaNetwork::setEapMethod(
-    ISupplicantStaNetwork::EapMethod method, setEapMethod_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapMethodInternal, _hidl_cb, method);
-}
-
-Return<void> StaNetwork::setEapPhase2Method(
-    ISupplicantStaNetwork::EapPhase2Method method,
-    setEapPhase2Method_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapPhase2MethodInternal, _hidl_cb, method);
-}
-
-Return<void> StaNetwork::setEapIdentity(
-    const hidl_vec<uint8_t> &identity, setEapIdentity_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapIdentityInternal, _hidl_cb, identity);
-}
-
-Return<void> StaNetwork::setEapEncryptedImsiIdentity(
-    const EapSimEncryptedIdentity &identity,
-    setEapEncryptedImsiIdentity_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapEncryptedImsiIdentityInternal, _hidl_cb,
-	    identity);
-}
-
-Return<void> StaNetwork::setEapAnonymousIdentity(
-    const hidl_vec<uint8_t> &identity, setEapAnonymousIdentity_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapAnonymousIdentityInternal, _hidl_cb, identity);
-}
-
-Return<void> StaNetwork::setEapPassword(
-    const hidl_vec<uint8_t> &password, setEapPassword_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapPasswordInternal, _hidl_cb, password);
-}
-
-Return<void> StaNetwork::setEapCACert(
-    const hidl_string &path, setEapCACert_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapCACertInternal, _hidl_cb, path);
-}
-
-Return<void> StaNetwork::setEapCAPath(
-    const hidl_string &path, setEapCAPath_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapCAPathInternal, _hidl_cb, path);
-}
-
-Return<void> StaNetwork::setEapClientCert(
-    const hidl_string &path, setEapClientCert_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapClientCertInternal, _hidl_cb, path);
-}
-
-Return<void> StaNetwork::setEapPrivateKeyId(
-    const hidl_string &id, setEapPrivateKeyId_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapPrivateKeyIdInternal, _hidl_cb, id);
-}
-
-Return<void> StaNetwork::setEapSubjectMatch(
-    const hidl_string &match, setEapSubjectMatch_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapSubjectMatchInternal, _hidl_cb, match);
-}
-
-Return<void> StaNetwork::setEapAltSubjectMatch(
-    const hidl_string &match, setEapAltSubjectMatch_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapAltSubjectMatchInternal, _hidl_cb, match);
-}
-
-Return<void> StaNetwork::setEapEngine(bool enable, setEapEngine_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapEngineInternal, _hidl_cb, enable);
-}
-
-Return<void> StaNetwork::setEapEngineID(
-    const hidl_string &id, setEapEngineID_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapEngineIDInternal, _hidl_cb, id);
-}
-
-Return<void> StaNetwork::setEapDomainSuffixMatch(
-    const hidl_string &match, setEapDomainSuffixMatch_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapDomainSuffixMatchInternal, _hidl_cb, match);
-}
-
-Return<void> StaNetwork::setProactiveKeyCaching(
-    bool enable, setProactiveKeyCaching_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setProactiveKeyCachingInternal, _hidl_cb, enable);
-}
-
-Return<void> StaNetwork::setIdStr(
-    const hidl_string &id_str, setIdStr_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setIdStrInternal, _hidl_cb, id_str);
-}
-
-Return<void> StaNetwork::setUpdateIdentifier(
-    uint32_t id, setUpdateIdentifier_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setUpdateIdentifierInternal, _hidl_cb, id);
-}
-
-Return<void> StaNetwork::setWapiCertSuite(
-    const hidl_string& suite, setWapiCertSuite_cb _hidl_cb) {
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setWapiCertSuiteInternal, _hidl_cb, suite);
-}
-
-Return<void> StaNetwork::setEdmg(bool enable, setEdmg_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEdmgInternal, _hidl_cb, enable);
-}
-
-Return<void> StaNetwork::getSsid(getSsid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getSsidInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getBssid(getBssid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getBssidInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getScanSsid(getScanSsid_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getScanSsidInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getKeyMgmt(getKeyMgmt_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getKeyMgmtInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getProto(getProto_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getProtoInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getAuthAlg(getAuthAlg_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getAuthAlgInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getGroupCipher(getGroupCipher_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getGroupCipherInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getPairwiseCipher(getPairwiseCipher_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getPairwiseCipherInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getPskPassphrase(getPskPassphrase_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getPskPassphraseInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getPsk(getPsk_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getPskInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getSaePassword(getSaePassword_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getSaePasswordInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getSaePasswordId(getSaePasswordId_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getSaePasswordIdInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getWepKey(uint32_t key_idx, getWepKey_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getWepKeyInternal, _hidl_cb, key_idx);
-}
-
-Return<void> StaNetwork::getWepTxKeyIdx(getWepTxKeyIdx_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getWepTxKeyIdxInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getRequirePmf(getRequirePmf_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getRequirePmfInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapMethod(getEapMethod_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapMethodInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapPhase2Method(getEapPhase2Method_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapPhase2MethodInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapIdentity(getEapIdentity_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapIdentityInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapAnonymousIdentity(
-    getEapAnonymousIdentity_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapAnonymousIdentityInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapPassword(getEapPassword_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapPasswordInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapCACert(getEapCACert_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapCACertInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapCAPath(getEapCAPath_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapCAPathInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapClientCert(getEapClientCert_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapClientCertInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapPrivateKeyId(getEapPrivateKeyId_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapPrivateKeyIdInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapSubjectMatch(getEapSubjectMatch_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapSubjectMatchInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapAltSubjectMatch(
-    getEapAltSubjectMatch_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapAltSubjectMatchInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapEngine(getEapEngine_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapEngineInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapEngineID(getEapEngineID_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapEngineIDInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEapDomainSuffixMatch(
-    getEapDomainSuffixMatch_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEapDomainSuffixMatchInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getIdStr(getIdStr_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &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::getWapiCertSuite(getWapiCertSuite_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getWapiCertSuiteInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getEdmg(getEdmg_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getEdmgInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::enable(bool no_connect, enable_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::enableInternal, _hidl_cb, no_connect);
-}
-
-Return<void> StaNetwork::disable(disable_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::disableInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::select(select_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::selectInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::sendNetworkEapSimGsmAuthResponse(
-    const hidl_vec<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
-	&vec_params,
-    sendNetworkEapSimGsmAuthResponse_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::sendNetworkEapSimGsmAuthResponseInternal, _hidl_cb,
-	    vec_params);
-}
-
-Return<void> StaNetwork::sendNetworkEapSimGsmAuthFailure(
-    sendNetworkEapSimGsmAuthFailure_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::sendNetworkEapSimGsmAuthFailureInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::sendNetworkEapSimUmtsAuthResponse(
-    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams &params,
-    sendNetworkEapSimUmtsAuthResponse_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal, _hidl_cb,
-	    params);
-}
-
-Return<void> StaNetwork::sendNetworkEapSimUmtsAutsResponse(
-    const hidl_array<uint8_t, 14> &auts,
-    sendNetworkEapSimUmtsAutsResponse_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal, _hidl_cb,
-	    auts);
-}
-
-Return<void> StaNetwork::sendNetworkEapSimUmtsAuthFailure(
-    sendNetworkEapSimUmtsAuthFailure_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::sendNetworkEapIdentityResponse(
-    const hidl_vec<uint8_t> &identity,
-    sendNetworkEapIdentityResponse_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::sendNetworkEapIdentityResponseInternal, _hidl_cb,
-	    identity);
-}
-
-Return<void> StaNetwork::sendNetworkEapIdentityResponse_1_1(
-    const EapSimIdentity &identity,
-    const EapSimEncryptedIdentity &encrypted_imsi_identity,
-    sendNetworkEapIdentityResponse_1_1_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::sendNetworkEapIdentityResponseInternal_1_1, _hidl_cb,
-	    identity, encrypted_imsi_identity);
-}
-
-Return<void> StaNetwork::setKeyMgmt_1_2(
-    uint32_t key_mgmt_mask, setKeyMgmt_1_2_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setKeyMgmtInternal, _hidl_cb, key_mgmt_mask);
-}
-
-Return<void> StaNetwork::setGroupCipher_1_2(
-    uint32_t group_cipher_mask, setGroupCipher_1_2_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setGroupCipherInternal, _hidl_cb, group_cipher_mask);
-}
-
-Return<void> StaNetwork::setGroupMgmtCipher(
-    uint32_t group_mgmt_cipher_mask, setGroupMgmtCipher_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setGroupMgmtCipherInternal,
-		_hidl_cb, group_mgmt_cipher_mask);
-}
-
-Return<void> StaNetwork::getGroupMgmtCipher(getGroupMgmtCipher_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getGroupMgmtCipherInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setPairwiseCipher_1_2(
-    uint32_t pairwise_cipher_mask, setPairwiseCipher_1_2_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setPairwiseCipherInternal, _hidl_cb,
-	    pairwise_cipher_mask);
-}
-
-Return<void> StaNetwork::getKeyMgmt_1_2(getKeyMgmt_1_2_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getKeyMgmtInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getGroupCipher_1_2(getGroupCipher_1_2_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getGroupCipherInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getPairwiseCipher_1_2(
-    getPairwiseCipher_1_2_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getPairwiseCipherInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::enableTlsSuiteBEapPhase1Param(
-    bool enable, enableTlsSuiteBEapPhase1Param_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::enableTlsSuiteBEapPhase1ParamInternal, _hidl_cb, enable);
-}
-
-Return<void> StaNetwork::enableSuiteBEapOpenSslCiphers(
-    enableSuiteBEapOpenSslCiphers_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::enableSuiteBEapOpenSslCiphersInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setSaePassword(
-    const hidl_string &sae_password, setSaePassword_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setSaePasswordInternal, _hidl_cb, sae_password);
-}
-
-Return<void> StaNetwork::setSaePasswordId(
-    const hidl_string &sae_password_id, setSaePasswordId_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setSaePasswordIdInternal, _hidl_cb, sae_password_id);
-}
-
-Return<void> StaNetwork::setOcsp(
-    V1_3::OcspType ocspType, setOcsp_cb _hidl_cb) {
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setOcspInternal, _hidl_cb, ocspType);
-}
-
-Return<void> StaNetwork::getOcsp(
-    getOcsp_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getOcspInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setPmkCache(const hidl_vec<uint8_t> &serializedEntry,
-    setPmkCache_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setPmkCacheInternal, _hidl_cb, serializedEntry);
-}
-
-Return<void> StaNetwork::setKeyMgmt_1_3(
-    uint32_t key_mgmt_mask, setKeyMgmt_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setKeyMgmt_1_3Internal, _hidl_cb, key_mgmt_mask);
-}
-
-Return<void> StaNetwork::getKeyMgmt_1_3(getKeyMgmt_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getKeyMgmt_1_3Internal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setProto_1_3(uint32_t proto_mask, setProto_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setProto_1_3Internal, _hidl_cb, proto_mask);
-}
-
-Return<void> StaNetwork::getProto_1_3(getProto_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getProto_1_3Internal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setGroupCipher_1_3(
-    uint32_t group_cipher_mask, setGroupCipher_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setGroupCipher_1_3Internal, _hidl_cb, group_cipher_mask);
-}
-
-Return<void> StaNetwork::getGroupCipher_1_3(getGroupCipher_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getGroupCipher_1_3Internal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setPairwiseCipher_1_3(
-    uint32_t pairwise_cipher_mask, setPairwiseCipher_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setPairwiseCipher_1_3Internal, _hidl_cb,
-	    pairwise_cipher_mask);
-}
-
-Return<void> StaNetwork::getPairwiseCipher_1_3(
-    getPairwiseCipher_1_3_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getPairwiseCipher_1_3Internal, _hidl_cb);
-}
-
-Return<void> StaNetwork::getAuthAlg_1_3(getAuthAlg_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getAuthAlgInternal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setAuthAlg_1_3(
-    uint32_t auth_alg_mask,
-    std::function<void(const SupplicantStatus &status)> _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setAuthAlgInternal, _hidl_cb, auth_alg_mask);
-}
-
-Return<void> StaNetwork::setEapErp(bool enable, setEapErp_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setEapErpInternal, _hidl_cb, enable);
-}
-
-Return<void> StaNetwork::setGroupCipher_1_4(
-    uint32_t group_cipher_mask, setGroupCipher_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setGroupCipher_1_4Internal, _hidl_cb, group_cipher_mask);
-}
-
-Return<void> StaNetwork::getGroupCipher_1_4(getGroupCipher_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getGroupCipher_1_4Internal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setPairwiseCipher_1_4(
-    uint32_t pairwise_cipher_mask, setPairwiseCipher_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setPairwiseCipher_1_4Internal, _hidl_cb,
-	    pairwise_cipher_mask);
-}
-
-Return<void> StaNetwork::getPairwiseCipher_1_4(
-    getPairwiseCipher_1_4_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::getPairwiseCipher_1_4Internal, _hidl_cb);
-}
-
-Return<void> StaNetwork::setSaeH2eMode(
-    ISupplicantStaNetworkV1_4::SaeH2eMode mode, setSaeH2eMode_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::setSaeH2eModeInternal, _hidl_cb, mode);
-}
-
-Return<void> StaNetwork::enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::enableSaePkOnlyModeInternal, _hidl_cb, enable);
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getIdInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getInterfaceNameInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
-}
-
-std::pair<SupplicantStatus, IfaceType> StaNetwork::getTypeInternal()
-{
-	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::STA};
-}
-
-SupplicantStatus StaNetwork::registerCallbackInternal(
-    const sp<ISupplicantStaNetworkCallback> &callback)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-V1_4::SupplicantStatus StaNetwork::registerCallback_1_4Internal(
-    const sp<V1_4::ISupplicantStaNetworkCallback> &callback)
-{
-	HidlManager *hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager || hidl_manager->addStaNetworkCallbackHidlObject(
-				 ifname_, network_id_, callback)) {
-		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setSsidInternal(const std::vector<uint8_t> &ssid)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (ssid.size() == 0 ||
-	    ssid.size() >
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  SSID_MAX_LEN_IN_BYTES)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	if (setByteArrayFieldAndResetState(
-		ssid.data(), ssid.size(), &(wpa_ssid->ssid),
-		&(wpa_ssid->ssid_len), "ssid")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	if (wpa_ssid->passphrase) {
-		wpa_config_update_psk(wpa_ssid);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setBssidInternal(
-    const std::array<uint8_t, 6> &bssid)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	int prev_bssid_set = wpa_ssid->bssid_set;
-	u8 prev_bssid[ETH_ALEN];
-	os_memcpy(prev_bssid, wpa_ssid->bssid, ETH_ALEN);
-	// Zero'ed array is used to clear out the BSSID value.
-	if (os_memcmp(bssid.data(), kZeroBssid, ETH_ALEN) == 0) {
-		wpa_ssid->bssid_set = 0;
-		wpa_printf(MSG_MSGDUMP, "BSSID any");
-	} else {
-		os_memcpy(wpa_ssid->bssid, bssid.data(), ETH_ALEN);
-		wpa_ssid->bssid_set = 1;
-		wpa_hexdump(MSG_MSGDUMP, "BSSID", wpa_ssid->bssid, ETH_ALEN);
-	}
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if ((wpa_ssid->bssid_set != prev_bssid_set ||
-	     os_memcmp(wpa_ssid->bssid, prev_bssid, ETH_ALEN) != 0)) {
-		wpas_notify_network_bssid_set_changed(wpa_s, wpa_ssid);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setScanSsidInternal(bool enable)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->scan_ssid = enable ? 1 : 0;
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setKeyMgmtInternal(uint32_t key_mgmt_mask)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-SupplicantStatus StaNetwork::setProtoInternal(uint32_t proto_mask)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-SupplicantStatus StaNetwork::setAuthAlgInternal(uint32_t auth_alg_mask)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (auth_alg_mask & ~kAllowedAuthAlgMask) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	wpa_ssid->auth_alg = auth_alg_mask;
-	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", wpa_ssid->auth_alg);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-V1_4::SupplicantStatus StaNetwork::setEdmgInternal(bool enable)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->enable_edmg = enable ? 1 : 0;
-	resetInternalStateAfterParamsUpdate();
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setGroupCipherInternal(uint32_t group_cipher_mask)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-SupplicantStatus StaNetwork::setPairwiseCipherInternal(
-    uint32_t pairwise_cipher_mask)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-SupplicantStatus StaNetwork::setPskPassphraseInternal(const std::string &rawPsk)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	std::string psk = rawPsk;
-#ifdef CONFIG_WAPI_INTERFACE
-	if (wpa_ssid->key_mgmt & WPA_KEY_MGMT_WAPI_PSK) {
-		if (rawPsk.size() > 2 && rawPsk.front()== '"' && rawPsk.back() == '"') {
-			psk = rawPsk.substr(1, rawPsk.size() - 2);
-		} else {
-			if ((rawPsk.size() & 1)) {
-				return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-			}
-			size_t len = psk.size() / 2;
-			uint8_t *buf = (uint8_t *) os_malloc(len);
-			if (hexstr2bin(psk.c_str(), buf, len) < 0) {
-			        os_free(buf);
-				return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-			}
-			std::vector<uint8_t> bytes(buf, buf + len);
-			os_free(buf);
-			return setWapiPskInternal(bytes);
-		}
-	}
-#endif
-	if (isPskPassphraseValid(psk)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	if (wpa_ssid->passphrase &&
-	    os_strlen(wpa_ssid->passphrase) == psk.size() &&
-	    os_memcmp(wpa_ssid->passphrase, psk.c_str(), psk.size()) == 0) {
-		return {SupplicantStatusCode::SUCCESS, ""};
-	}
-	// Flag to indicate if raw psk is calculated or not using
-	// |wpa_config_update_psk|. Deferred if ssid not already set.
-	wpa_ssid->psk_set = 0;
-	if (setStringKeyFieldAndResetState(
-		psk.c_str(), &(wpa_ssid->passphrase), "psk passphrase")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	if (wpa_ssid->ssid_len) {
-		wpa_config_update_psk(wpa_ssid);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setPskInternal(const std::array<uint8_t, 32> &psk)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
-	str_clear_free(wpa_ssid->passphrase);
-	wpa_ssid->passphrase = nullptr;
-	os_memcpy(wpa_ssid->psk, psk.data(), sizeof(wpa_ssid->psk));
-	wpa_ssid->psk_set = 1;
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setWepKeyInternal(
-    uint32_t key_idx, const std::vector<uint8_t> &wep_key)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (key_idx >=
-	    static_cast<uint32_t>(
-		ISupplicantStaNetwork::ParamSizeLimits::WEP_KEYS_MAX_NUM)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	if (wep_key.size() !=
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  WEP40_KEY_LEN_IN_BYTES) &&
-	    wep_key.size() !=
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  WEP104_KEY_LEN_IN_BYTES)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	os_memcpy(wpa_ssid->wep_key[key_idx], wep_key.data(), wep_key.size());
-	wpa_ssid->wep_key_len[key_idx] = wep_key.size();
-	std::string msg_dump_title("wep_key" + std::to_string(key_idx));
-	wpa_hexdump_key(
-	    MSG_MSGDUMP, msg_dump_title.c_str(), wpa_ssid->wep_key[key_idx],
-	    wpa_ssid->wep_key_len[key_idx]);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setWepTxKeyIdxInternal(uint32_t key_idx)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (key_idx >=
-	    static_cast<uint32_t>(
-		ISupplicantStaNetwork::ParamSizeLimits::WEP_KEYS_MAX_NUM)) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	wpa_ssid->wep_tx_keyidx = key_idx;
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setRequirePmfInternal(bool enable)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (enable) {
-		wpa_ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
-	}
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapMethodInternal(
-    ISupplicantStaNetwork::EapMethod method)
-{
-	uint32_t eap_method_idx = static_cast<
-	    std::underlying_type<ISupplicantStaNetwork::EapMethod>::type>(
-	    method);
-	if (eap_method_idx >= kEapMethodMax) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	int retrieved_vendor, retrieved_method;
-	const char *method_str = kEapMethodStrings[eap_method_idx];
-	// This string lookup is needed to check if the device supports the
-	// corresponding EAP type.
-	retrieved_method = eap_peer_get_type(method_str, &retrieved_vendor);
-	if (retrieved_vendor == EAP_VENDOR_IETF &&
-	    retrieved_method == EAP_TYPE_NONE) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	if (wpa_ssid->eap.eap_methods) {
-		os_free(wpa_ssid->eap.eap_methods);
-	}
-	// wpa_supplicant can support setting multiple eap methods for each
-	// network. But, this is not really used by Android. So, just adding
-	// support for setting one EAP method for each network. The additional
-	// |eap_method_type| member in the array is used to indicate the end
-	// of list.
-	wpa_ssid->eap.eap_methods =
-	    (eap_method_type *)os_malloc(sizeof(eap_method_type) * 2);
-	if (!wpa_ssid->eap.eap_methods) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	wpa_ssid->eap.eap_methods[0].vendor = retrieved_vendor;
-	wpa_ssid->eap.eap_methods[0].method = retrieved_method;
-	wpa_ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
-	wpa_ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
-
-	wpa_ssid->leap = 0;
-	wpa_ssid->non_leap = 0;
-	if (retrieved_vendor == EAP_VENDOR_IETF &&
-	    retrieved_method == EAP_TYPE_LEAP) {
-		wpa_ssid->leap++;
-	} else {
-		wpa_ssid->non_leap++;
-	}
-	wpa_hexdump(
-	    MSG_MSGDUMP, "eap methods", (u8 *)wpa_ssid->eap.eap_methods,
-	    sizeof(eap_method_type) * 2);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapPhase2MethodInternal(
-    ISupplicantStaNetwork::EapPhase2Method method)
-{
-	uint32_t eap_phase2_method_idx = static_cast<
-	    std::underlying_type<ISupplicantStaNetwork::EapPhase2Method>::type>(
-	    method);
-	if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	// EAP method needs to be set for us to construct the eap
-	// phase 2 method string.
-	SupplicantStatus status;
-	ISupplicantStaNetwork::EapMethod eap_method;
-	std::tie(status, eap_method) = getEapMethodInternal();
-	if (status.code != SupplicantStatusCode::SUCCESS) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN,
-			"EAP method not set"};
-	}
-	std::string eap_phase2_str;
-	if (method == ISupplicantStaNetwork::EapPhase2Method::NONE) {
-		eap_phase2_str = "";
-	} else if (
-	    eap_method == ISupplicantStaNetwork::EapMethod::TTLS &&
-	    method == ISupplicantStaNetwork::EapPhase2Method::GTC) {
-		eap_phase2_str = kEapPhase2AuthEapPrefix;
-	} else {
-		eap_phase2_str = kEapPhase2AuthPrefix;
-	}
-	eap_phase2_str += kEapPhase2MethodStrings[eap_phase2_method_idx];
-	if (setStringFieldAndResetState(
-		eap_phase2_str.c_str(), &(wpa_ssid->eap.phase2),
-		"eap phase2")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapIdentityInternal(
-    const std::vector<uint8_t> &identity)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setByteArrayFieldAndResetState(
-		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
-		&(wpa_ssid->eap.identity_len), "eap identity")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	// plain IMSI identity
-	if (setByteArrayFieldAndResetState(
-		identity.data(), identity.size(),
-		&(wpa_ssid->eap.imsi_identity),
-		&(wpa_ssid->eap.imsi_identity_len), "eap imsi identity")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapEncryptedImsiIdentityInternal(
-    const std::vector<uint8_t> &identity)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	// encrypted IMSI identity
-	if (setByteArrayFieldAndResetState(
-		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
-		&(wpa_ssid->eap.identity_len), "eap encrypted imsi identity")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapAnonymousIdentityInternal(
-    const std::vector<uint8_t> &identity)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setByteArrayFieldAndResetState(
-		identity.data(), identity.size(),
-		&(wpa_ssid->eap.anonymous_identity),
-		&(wpa_ssid->eap.anonymous_identity_len),
-		"eap anonymous_identity")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapPasswordInternal(
-    const std::vector<uint8_t> &password)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setByteArrayKeyFieldAndResetState(
-		password.data(), password.size(), &(wpa_ssid->eap.password),
-		&(wpa_ssid->eap.password_len), "eap password")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
-	wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapCACertInternal(const std::string &path)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		path.c_str(), &(wpa_ssid->eap.cert.ca_cert), "eap ca_cert")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapCAPathInternal(const std::string &path)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		path.c_str(), &(wpa_ssid->eap.cert.ca_path), "eap ca_path")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapClientCertInternal(const std::string &path)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		path.c_str(), &(wpa_ssid->eap.cert.client_cert),
-		"eap client_cert")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapPrivateKeyIdInternal(const std::string &id)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		id.c_str(), &(wpa_ssid->eap.cert.key_id), "eap key_id")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapSubjectMatchInternal(
-    const std::string &match)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		match.c_str(), &(wpa_ssid->eap.cert.subject_match),
-		"eap subject_match")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapAltSubjectMatchInternal(
-    const std::string &match)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		match.c_str(), &(wpa_ssid->eap.cert.altsubject_match),
-		"eap altsubject_match")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapEngineInternal(bool enable)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->eap.cert.engine = enable ? 1 : 0;
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapEngineIDInternal(const std::string &id)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		id.c_str(), &(wpa_ssid->eap.cert.engine_id), "eap engine_id")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setEapDomainSuffixMatchInternal(
-    const std::string &match)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		match.c_str(), &(wpa_ssid->eap.cert.domain_suffix_match),
-		"eap domain_suffix_match")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setProactiveKeyCachingInternal(bool enable)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->proactive_key_caching = enable ? 1 : 0;
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setIdStrInternal(const std::string &id_str)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setStringFieldAndResetState(
-		id_str.c_str(), &(wpa_ssid->id_str), "id_str")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setUpdateIdentifierInternal(uint32_t id)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->update_identifier = id;
-	wpa_printf(
-	    MSG_MSGDUMP, "update_identifier: %d", wpa_ssid->update_identifier);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setWapiCertSuiteInternal(const std::string &suite)
-{
-#ifdef CONFIG_WAPI_INTERFACE
-	dummyWapiCertSuite = suite;
-	return {SupplicantStatusCode::SUCCESS, "Dummy implementation"};
-#else
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "Not implemented"};
-#endif
-}
-
-SupplicantStatus StaNetwork::setWapiPskInternal(const std::vector<uint8_t> &psk)
-{
-#ifdef CONFIG_WAPI_INTERFACE
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	str_clear_free(wpa_ssid->passphrase);
-	wpa_ssid->passphrase = nullptr;
-
-	dummyWapiPsk = psk;
-
-	wpa_ssid->psk_set = 1;
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, "Dummy implementation"};
-#else
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "Not implemented"};
-#endif
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>> StaNetwork::getSsidInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	std::vector<uint8_t> ssid;
-	ssid.assign(wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len);
-	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ssid)};
-}
-
-std::pair<SupplicantStatus, std::array<uint8_t, 6>>
-StaNetwork::getBssidInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	std::array<uint8_t, 6> bssid{};
-	os_memcpy(bssid.data(), kZeroBssid, ETH_ALEN);
-	if (wpa_ssid->bssid_set) {
-		os_memcpy(bssid.data(), wpa_ssid->bssid, ETH_ALEN);
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(bssid)};
-}
-
-std::pair<SupplicantStatus, bool> StaNetwork::getScanSsidInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		(wpa_ssid->scan_ssid == 1)};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getKeyMgmtInternal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getProtoInternal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getAuthAlgInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		wpa_ssid->auth_alg & kAllowedAuthAlgMask};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getGroupCipherInternal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getPairwiseCipherInternal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getPskPassphraseInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-#ifdef CONFIG_WAPI_INTERFACE
-	if (wpa_ssid->key_mgmt & WPA_KEY_MGMT_WAPI_PSK) {
-		if (wpa_ssid->psk_set) {
-			std::pair<SupplicantStatus, std::vector<uint8_t>> ret = getWapiPskInternal();
-			std::string psk;
-			char buf[3] = {0};
-			for (int i = 0; i < ret.second.size(); i++) {
-				snprintf(buf, sizeof(buf), "%02x", ret.second[i]);
-				psk.append(buf);
-			}
-			return {{SupplicantStatusCode::SUCCESS, ""}, psk};
-		} else {
-			if (!wpa_ssid->passphrase) {
-				return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-			}
-			std::string passphrase;
-			passphrase.append("\"");
-			passphrase.append(wpa_ssid->passphrase);
-			passphrase.append("\"");
-			return {{SupplicantStatusCode::SUCCESS, ""}, passphrase};
-		}
-	}
-#endif
-	if (!wpa_ssid->passphrase) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->passphrase};
-}
-
-std::pair<SupplicantStatus, std::array<uint8_t, 32>>
-StaNetwork::getPskInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
-	if (!wpa_ssid->psk_set) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	std::array<uint8_t, 32> psk;
-	os_memcpy(psk.data(), wpa_ssid->psk, psk.size());
-	return {{SupplicantStatusCode::SUCCESS, ""}, psk};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getSaePasswordInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->sae_password) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->sae_password};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getSaePasswordIdInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->sae_password_id) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->sae_password_id};
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>> StaNetwork::getWepKeyInternal(
-    uint32_t key_idx)
-{
-	std::vector<uint8_t> wep_key;
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (key_idx >=
-	    static_cast<uint32_t>(
-		ISupplicantStaNetwork::ParamSizeLimits::WEP_KEYS_MAX_NUM)) {
-		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""},
-			wep_key};
-	}
-	wep_key.assign(
-	    wpa_ssid->wep_key[key_idx],
-	    wpa_ssid->wep_key[key_idx] + wpa_ssid->wep_key_len[key_idx]);
-	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(wep_key)};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getWepTxKeyIdxInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->wep_tx_keyidx};
-}
-
-std::pair<SupplicantStatus, bool> StaNetwork::getRequirePmfInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		(wpa_ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)};
-}
-
-std::pair<SupplicantStatus, ISupplicantStaNetwork::EapMethod>
-StaNetwork::getEapMethodInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.eap_methods) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	// wpa_supplicant can support setting multiple eap methods for each
-	// network. But, this is not really used by Android. So, just reading
-	// the first EAP method for each network.
-	const std::string eap_method_str = eap_get_name(
-	    wpa_ssid->eap.eap_methods[0].vendor,
-	    static_cast<enum eap_type>(wpa_ssid->eap.eap_methods[0].method));
-	size_t eap_method_idx =
-	    std::find(
-		std::begin(kEapMethodStrings), std::end(kEapMethodStrings),
-		eap_method_str) -
-	    std::begin(kEapMethodStrings);
-	if (eap_method_idx >= kEapMethodMax) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		static_cast<ISupplicantStaNetwork::EapMethod>(eap_method_idx)};
-}
-
-std::pair<SupplicantStatus, ISupplicantStaNetwork::EapPhase2Method>
-StaNetwork::getEapPhase2MethodInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.phase2) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	const std::string eap_phase2_method_str_with_prefix =
-	    wpa_ssid->eap.phase2;
-	std::string eap_phase2_method_str;
-	// Strip out the phase 2 method prefix before doing a reverse lookup
-	// of phase 2 string to the Eap Phase 2 type.
-	if (eap_phase2_method_str_with_prefix.find(kEapPhase2AuthPrefix) == 0) {
-		eap_phase2_method_str =
-		    eap_phase2_method_str_with_prefix.substr(
-			strlen(kEapPhase2AuthPrefix),
-			eap_phase2_method_str_with_prefix.size());
-	} else if (
-	    eap_phase2_method_str_with_prefix.find(kEapPhase2AuthEapPrefix) ==
-	    0) {
-		eap_phase2_method_str =
-		    eap_phase2_method_str_with_prefix.substr(
-			strlen(kEapPhase2AuthEapPrefix),
-			eap_phase2_method_str_with_prefix.size());
-	}
-	size_t eap_phase2_method_idx =
-	    std::find(
-		std::begin(kEapPhase2MethodStrings),
-		std::end(kEapPhase2MethodStrings), eap_phase2_method_str) -
-	    std::begin(kEapPhase2MethodStrings);
-	if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		static_cast<ISupplicantStaNetwork::EapPhase2Method>(
-		    eap_phase2_method_idx)};
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>>
-StaNetwork::getEapIdentityInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.identity) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		std::vector<uint8_t>(
-		    wpa_ssid->eap.identity,
-		    wpa_ssid->eap.identity + wpa_ssid->eap.identity_len)};
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>>
-StaNetwork::getEapAnonymousIdentityInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.anonymous_identity) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		std::vector<uint8_t>(
-		    wpa_ssid->eap.anonymous_identity,
-		    wpa_ssid->eap.anonymous_identity +
-			wpa_ssid->eap.anonymous_identity_len)};
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>>
-StaNetwork::getEapPasswordInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.password) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		std::vector<uint8_t>(
-		    wpa_ssid->eap.password,
-		    wpa_ssid->eap.password + wpa_ssid->eap.password_len)};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getEapCACertInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.ca_cert) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		reinterpret_cast<char *>(wpa_ssid->eap.cert.ca_cert)};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getEapCAPathInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.ca_path) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		reinterpret_cast<char *>(wpa_ssid->eap.cert.ca_path)};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getEapClientCertInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.client_cert) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		reinterpret_cast<char *>(wpa_ssid->eap.cert.client_cert)};
-}
-
-std::pair<SupplicantStatus, std::string>
-StaNetwork::getEapPrivateKeyIdInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.key_id) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->eap.cert.key_id};
-}
-
-std::pair<SupplicantStatus, std::string>
-StaNetwork::getEapSubjectMatchInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.subject_match) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		reinterpret_cast<char *>(wpa_ssid->eap.cert.subject_match)};
-}
-
-std::pair<SupplicantStatus, std::string>
-StaNetwork::getEapAltSubjectMatchInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.altsubject_match) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		reinterpret_cast<char *>(wpa_ssid->eap.cert.altsubject_match)};
-}
-
-std::pair<SupplicantStatus, bool> StaNetwork::getEapEngineInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->eap.cert.engine == 1};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getEapEngineIDInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.engine_id) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, {wpa_ssid->eap.cert.engine_id}};
-}
-
-std::pair<SupplicantStatus, std::string>
-StaNetwork::getEapDomainSuffixMatchInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->eap.cert.domain_suffix_match) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		{wpa_ssid->eap.cert.domain_suffix_match}};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getIdStrInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (!wpa_ssid->id_str) {
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, {wpa_ssid->id_str}};
-}
-
-std::pair<V1_4::SupplicantStatus, bool> StaNetwork::getEdmgInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{V1_4::SupplicantStatusCode::SUCCESS, ""},
-		(wpa_ssid->enable_edmg == 1)};
-}
-
-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())};
-}
-
-std::pair<SupplicantStatus, std::string> StaNetwork::getWapiCertSuiteInternal()
-{
-#ifdef CONFIG_WAPI_INTERFACE
-	return {{SupplicantStatusCode::SUCCESS, "Dummy implementation"}, dummyWapiCertSuite};
-#else
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "Not implemented"}, {}};
-#endif
-}
-
-std::pair<SupplicantStatus, std::vector<uint8_t>> StaNetwork::getWapiPskInternal()
-{
-#ifdef CONFIG_WAPI_INTERFACE
-	return {{SupplicantStatusCode::SUCCESS, "Dummy implementation"}, dummyWapiPsk};
-#else
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "Not implemented"}, {}};
-#endif
-}
-
-SupplicantStatus StaNetwork::enableInternal(bool no_connect)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (wpa_ssid->disabled == 2) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (no_connect) {
-		wpa_ssid->disabled = 0;
-	} else {
-		wpa_s->scan_min_time.sec = 0;
-		wpa_s->scan_min_time.usec = 0;
-		wpa_supplicant_enable_network(wpa_s, wpa_ssid);
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::disableInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (wpa_ssid->disabled == 2) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	wpa_supplicant_disable_network(wpa_s, wpa_ssid);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::selectInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (wpa_ssid->disabled == 2) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	wpa_s->scan_min_time.sec = 0;
-	wpa_s->scan_min_time.usec = 0;
-	wpa_supplicant_select_network(wpa_s, wpa_ssid);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::sendNetworkEapSimGsmAuthResponseInternal(
-    const std::vector<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
-	&vec_params)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	// Convert the incoming parameters to a string to pass to
-	// wpa_supplicant.
-	std::string ctrl_rsp_param = std::string(kNetworkEapSimGsmAuthResponse);
-	for (const auto &params : vec_params) {
-		uint32_t kc_hex_len = params.kc.size() * 2 + 1;
-		std::vector<char> kc_hex(kc_hex_len);
-		uint32_t sres_hex_len = params.sres.size() * 2 + 1;
-		std::vector<char> sres_hex(sres_hex_len);
-		wpa_snprintf_hex(
-		    kc_hex.data(), kc_hex.size(), params.kc.data(),
-		    params.kc.size());
-		wpa_snprintf_hex(
-		    sres_hex.data(), sres_hex.size(), params.sres.data(),
-		    params.sres.size());
-		ctrl_rsp_param += ":" + std::string(kc_hex.data()) + ":" +
-				  std::string(sres_hex.data());
-	}
-	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
-		ctrl_rsp_param.size())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	eapol_sm_notify_ctrl_response(wpa_s->eapol);
-	wpa_hexdump_ascii_key(
-	    MSG_DEBUG, "network sim gsm auth response param",
-	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::sendNetworkEapSimGsmAuthFailureInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
-	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, kNetworkEapSimGsmAuthFailure,
-		strlen(kNetworkEapSimGsmAuthFailure))) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	eapol_sm_notify_ctrl_response(wpa_s->eapol);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal(
-    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams &params)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	// Convert the incoming parameters to a string to pass to
-	// wpa_supplicant.
-	uint32_t ik_hex_len = params.ik.size() * 2 + 1;
-	std::vector<char> ik_hex(ik_hex_len);
-	uint32_t ck_hex_len = params.ck.size() * 2 + 1;
-	std::vector<char> ck_hex(ck_hex_len);
-	uint32_t res_hex_len = params.res.size() * 2 + 1;
-	std::vector<char> res_hex(res_hex_len);
-	wpa_snprintf_hex(
-	    ik_hex.data(), ik_hex.size(), params.ik.data(), params.ik.size());
-	wpa_snprintf_hex(
-	    ck_hex.data(), ck_hex.size(), params.ck.data(), params.ck.size());
-	wpa_snprintf_hex(
-	    res_hex.data(), res_hex.size(), params.res.data(),
-	    params.res.size());
-	std::string ctrl_rsp_param =
-	    std::string(kNetworkEapSimUmtsAuthResponse) + ":" +
-	    std::string(ik_hex.data()) + ":" + std::string(ck_hex.data()) +
-	    ":" + std::string(res_hex.data());
-	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
-		ctrl_rsp_param.size())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	eapol_sm_notify_ctrl_response(wpa_s->eapol);
-	wpa_hexdump_ascii_key(
-	    MSG_DEBUG, "network sim umts auth response param",
-	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal(
-    const std::array<uint8_t, 14> &auts)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	uint32_t auts_hex_len = auts.size() * 2 + 1;
-	std::vector<char> auts_hex(auts_hex_len);
-	wpa_snprintf_hex(
-	    auts_hex.data(), auts_hex.size(), auts.data(), auts.size());
-	std::string ctrl_rsp_param =
-	    std::string(kNetworkEapSimUmtsAutsResponse) + ":" +
-	    std::string(auts_hex.data());
-	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
-		ctrl_rsp_param.size())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	eapol_sm_notify_ctrl_response(wpa_s->eapol);
-	wpa_hexdump_ascii_key(
-	    MSG_DEBUG, "network sim umts auts response param",
-	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
-	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, kNetworkEapSimUmtsAuthFailure,
-		strlen(kNetworkEapSimUmtsAuthFailure))) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	eapol_sm_notify_ctrl_response(wpa_s->eapol);
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal(
-    const std::vector<uint8_t> &identity)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	std::string ctrl_rsp_param(identity.begin(), identity.end());
-	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
-		ctrl_rsp_param.size())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	eapol_sm_notify_ctrl_response(wpa_s->eapol);
-	wpa_hexdump_ascii_key(
-	    MSG_DEBUG, "network identity response param",
-	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal_1_1(
-    const std::vector<uint8_t> &identity,
-    const std::vector<uint8_t> &encrypted_imsi_identity)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	// format: plain identity + ":" + encrypted
-	// identity(encrypted_imsi_identity)
-	std::string ctrl_rsp_param =
-	    std::string(identity.begin(), identity.end()) + ":" +
-	    std::string(
-		encrypted_imsi_identity.begin(), encrypted_imsi_identity.end());
-	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
-		ctrl_rsp_param.size())) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	eapol_sm_notify_ctrl_response(wpa_s->eapol);
-	wpa_hexdump_ascii_key(
-	    MSG_DEBUG, "network identity response param",
-	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::enableTlsSuiteBEapPhase1ParamInternal(bool enable)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	int val = enable == true ? 1 : 0;
-	std::string suiteb_phase1("tls_suiteb=" + std::to_string(val));
-
-	if (setStringKeyFieldAndResetState(
-		suiteb_phase1.c_str(), &(wpa_ssid->eap.phase1), "phase1")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::enableSuiteBEapOpenSslCiphersInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	const char openssl_suiteb_cipher[] = "SUITEB192";
-
-	if (setStringKeyFieldAndResetState(
-		openssl_suiteb_cipher, &(wpa_ssid->eap.openssl_ciphers),
-		"openssl_ciphers")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setSaePasswordInternal(
-    const std::string &sae_password)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (sae_password.length() < 1) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	if (wpa_ssid->sae_password &&
-	    os_strlen(wpa_ssid->sae_password) == sae_password.length() &&
-	    os_memcmp(
-		wpa_ssid->sae_password, sae_password.c_str(),
-		sae_password.length()) == 0) {
-		return {SupplicantStatusCode::SUCCESS, ""};
-	}
-	wpa_ssid->psk_set = 1;
-	if (setStringKeyFieldAndResetState(
-		sae_password.c_str(), &(wpa_ssid->sae_password),
-		"sae password")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setSaePasswordIdInternal(
-    const std::string &sae_password_id)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (sae_password_id.length() < 1) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	if (wpa_ssid->sae_password_id &&
-	    os_strlen(wpa_ssid->sae_password_id) == sae_password_id.length() &&
-	    os_memcmp(
-		wpa_ssid->sae_password_id, sae_password_id.c_str(),
-		sae_password_id.length()) == 0) {
-		return {SupplicantStatusCode::SUCCESS, ""};
-	}
-	wpa_ssid->psk_set = 1;
-	if (setStringKeyFieldAndResetState(
-		sae_password_id.c_str(), &(wpa_ssid->sae_password_id),
-		"sae password id")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setGroupMgmtCipherInternal(uint32_t
-		group_mgmt_cipher_mask)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (group_mgmt_cipher_mask & ~kAllowedGroupMgmtCipherMask) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	wpa_ssid->group_mgmt_cipher = group_mgmt_cipher_mask;
-	wpa_printf(MSG_MSGDUMP, "group_mgmt_cipher: 0x%x",
-			wpa_ssid->group_mgmt_cipher);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getGroupMgmtCipherInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		wpa_ssid->group_mgmt_cipher & kAllowedGroupMgmtCipherMask};
-}
-
-SupplicantStatus StaNetwork::setOcspInternal(V1_3::OcspType ocspType) {
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (ocspType < V1_3::OcspType::NONE || ocspType > V1_3::OcspType::REQUIRE_ALL_CERTS_STATUS) {
-		return{ SupplicantStatusCode::FAILURE_ARGS_INVALID, "" };
-	}
-	wpa_ssid->eap.cert.ocsp = (int) ocspType;
-	wpa_printf(
-	    MSG_MSGDUMP, "ocsp: %d", wpa_ssid->eap.cert.ocsp);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, V1_3::OcspType> StaNetwork::getOcspInternal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		(V1_3::OcspType) wpa_ssid->eap.cert.ocsp};
-}
-
-SupplicantStatus StaNetwork::setPmkCacheInternal(const std::vector<uint8_t>& serializedEntry) {
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	struct rsn_pmksa_cache_entry *new_entry = NULL;
-
-	new_entry = (struct rsn_pmksa_cache_entry *) os_zalloc(sizeof(*new_entry));
-	if (!new_entry) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, "Allocating memory failed"};
-	}
-
-	std::stringstream ss(
-	    std::stringstream::in | std::stringstream::out | std::stringstream::binary);
-	ss.write((char *) serializedEntry.data(), std::streamsize(serializedEntry.size()));
-	misc_utils::deserializePmkCacheEntry(ss, new_entry);
-	new_entry->network_ctx = wpa_ssid;
-	wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, new_entry);
-
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus StaNetwork::setKeyMgmt_1_3Internal(uint32_t key_mgmt_mask)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (key_mgmt_mask & ~kAllowedKeyMgmtMask) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	setFastTransitionKeyMgmt(key_mgmt_mask);
-
-	if (key_mgmt_mask & WPA_KEY_MGMT_OWE) {
-		// Do not allow to connect to Open network when OWE is selected
-		wpa_ssid->owe_only = 1;
-	}
-	wpa_ssid->key_mgmt = key_mgmt_mask;
-	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", wpa_ssid->key_mgmt);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getKeyMgmt_1_3Internal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	uint32_t key_mgmt_mask = wpa_ssid->key_mgmt & kAllowedKeyMgmtMask;
-
-	resetFastTransitionKeyMgmt(key_mgmt_mask);
-	return {{SupplicantStatusCode::SUCCESS, ""}, key_mgmt_mask};
-}
-
-SupplicantStatus StaNetwork::setProto_1_3Internal(uint32_t proto_mask)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (proto_mask & ~kAllowedProtoMask) {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	wpa_ssid->proto = proto_mask;
-	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", wpa_ssid->proto);
-	resetInternalStateAfterParamsUpdate();
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getProto_1_3Internal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		wpa_ssid->proto & kAllowedProtoMask};
-}
-
-SupplicantStatus StaNetwork::setGroupCipher_1_3Internal(uint32_t group_cipher_mask)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getGroupCipher_1_3Internal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-SupplicantStatus StaNetwork::setPairwiseCipher_1_3Internal(
-    uint32_t pairwise_cipher_mask)
-{
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"};
-}
-
-std::pair<SupplicantStatus, uint32_t> StaNetwork::getPairwiseCipher_1_3Internal()
-{
-	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
-}
-
-V1_4::SupplicantStatus StaNetwork::setGroupCipher_1_4Internal(uint32_t group_cipher_mask)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (group_cipher_mask & ~kAllowedGroupCipherMask) {
-		return {V1_4::SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	wpa_ssid->group_cipher = group_cipher_mask;
-	wpa_printf(MSG_MSGDUMP, "group_cipher: 0x%x", wpa_ssid->group_cipher);
-	resetInternalStateAfterParamsUpdate();
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<V1_4::SupplicantStatus, uint32_t> StaNetwork::getGroupCipher_1_4Internal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{V1_4::SupplicantStatusCode::SUCCESS, ""},
-		wpa_ssid->group_cipher & kAllowedGroupCipherMask};
-}
-
-V1_4::SupplicantStatus StaNetwork::setPairwiseCipher_1_4Internal(
-    uint32_t pairwise_cipher_mask)
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (pairwise_cipher_mask & ~kAllowedPairwisewCipherMask) {
-		return {V1_4::SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	wpa_ssid->pairwise_cipher = pairwise_cipher_mask;
-	wpa_printf(
-	    MSG_MSGDUMP, "pairwise_cipher: 0x%x", wpa_ssid->pairwise_cipher);
-	resetInternalStateAfterParamsUpdate();
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<V1_4::SupplicantStatus, uint32_t> StaNetwork::getPairwiseCipher_1_4Internal()
-{
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{V1_4::SupplicantStatusCode::SUCCESS, ""},
-		wpa_ssid->pairwise_cipher & kAllowedPairwisewCipherMask};
-}
-
-/**
- * Retrieve the underlying |wpa_ssid| struct pointer for
- * this network.
- * If the underlying network is removed or the interface
- * this network belong to
- * is removed, all RPC method calls on this object will
- * return failure.
- */
-struct wpa_ssid *StaNetwork::retrieveNetworkPtr()
-{
-	wpa_supplicant *wpa_s = retrieveIfacePtr();
-	if (!wpa_s)
-		return nullptr;
-	return wpa_config_get_network(wpa_s->conf, network_id_);
-}
-
-/**
- * Retrieve the underlying |wpa_supplicant| struct
- * pointer for
- * this network.
- */
-struct wpa_supplicant *StaNetwork::retrieveIfacePtr()
-{
-	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
-}
-
-/**
- * Check if the provided psk passhrase is valid or not.
- *
- * Returns 0 if valid, 1 otherwise.
- */
-int StaNetwork::isPskPassphraseValid(const std::string &psk)
-{
-	if (psk.size() <
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
-	    psk.size() >
-		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
-					  PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
-		return 1;
-	}
-	if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
-		return 1;
-	}
-	return 0;
-}
-
-/**
- * Reset internal wpa_supplicant state machine state
- * after params update (except
- * bssid).
- */
-void StaNetwork::resetInternalStateAfterParamsUpdate()
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-
-	wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_ssid);
-
-	if (wpa_s->current_ssid == wpa_ssid || wpa_s->current_ssid == NULL) {
-		/*
-		 * Invalidate the EAP session cache if
-		 * anything in the
-		 * current or previously used
-		 * configuration changes.
-		 */
-		eapol_sm_invalidate_cached_session(wpa_s->eapol);
-	}
-}
-
-/**
- * Helper function to set value in a string field in |wpa_ssid| structue
- * instance for this network.
- * This function frees any existing data in these fields.
- */
-int StaNetwork::setStringFieldAndResetState(
-    const char *value, uint8_t **to_update_field, const char *hexdump_prefix)
-{
-	return setStringFieldAndResetState(
-	    value, (char **)to_update_field, hexdump_prefix);
-}
-
-/**
- * Helper function to set value in a string field in |wpa_ssid| structue
- * instance for this network.
- * This function frees any existing data in these fields.
- */
-int StaNetwork::setStringFieldAndResetState(
-    const char *value, char **to_update_field, const char *hexdump_prefix)
-{
-	int value_len = strlen(value);
-	if (*to_update_field) {
-		os_free(*to_update_field);
-	}
-	*to_update_field = dup_binstr(value, value_len);
-	if (!(*to_update_field)) {
-		return 1;
-	}
-	wpa_hexdump_ascii(
-	    MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
-	resetInternalStateAfterParamsUpdate();
-	return 0;
-}
-
-/**
- * Helper function to set value in a string key field in |wpa_ssid| structue
- * instance for this network.
- * This function frees any existing data in these fields.
- */
-int StaNetwork::setStringKeyFieldAndResetState(
-    const char *value, char **to_update_field, const char *hexdump_prefix)
-{
-	int value_len = strlen(value);
-	if (*to_update_field) {
-		str_clear_free(*to_update_field);
-	}
-	*to_update_field = dup_binstr(value, value_len);
-	if (!(*to_update_field)) {
-		return 1;
-	}
-	wpa_hexdump_ascii_key(
-	    MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
-	resetInternalStateAfterParamsUpdate();
-	return 0;
-}
-
-/**
- * Helper function to set value in a string field with a corresponding length
- * field in |wpa_ssid| structue instance for this network.
- * This function frees any existing data in these fields.
- */
-int StaNetwork::setByteArrayFieldAndResetState(
-    const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
-    size_t *to_update_field_len, const char *hexdump_prefix)
-{
-	if (*to_update_field) {
-		os_free(*to_update_field);
-	}
-	*to_update_field = (uint8_t *)os_malloc(value_len);
-	if (!(*to_update_field)) {
-		return 1;
-	}
-	os_memcpy(*to_update_field, value, value_len);
-	*to_update_field_len = value_len;
-
-	wpa_hexdump_ascii(
-	    MSG_MSGDUMP, hexdump_prefix, *to_update_field,
-	    *to_update_field_len);
-	resetInternalStateAfterParamsUpdate();
-	return 0;
-}
-
-/**
- * Helper function to set value in a string key field with a corresponding
- * length field in |wpa_ssid| structue instance for this network.
- * This function frees any existing data in these fields.
- */
-int StaNetwork::setByteArrayKeyFieldAndResetState(
-    const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
-    size_t *to_update_field_len, const char *hexdump_prefix)
-{
-	if (*to_update_field) {
-		bin_clear_free(*to_update_field, *to_update_field_len);
-	}
-	*to_update_field = (uint8_t *)os_malloc(value_len);
-	if (!(*to_update_field)) {
-		return 1;
-	}
-	os_memcpy(*to_update_field, value, value_len);
-	*to_update_field_len = value_len;
-
-	wpa_hexdump_ascii_key(
-	    MSG_MSGDUMP, hexdump_prefix, *to_update_field,
-	    *to_update_field_len);
-	resetInternalStateAfterParamsUpdate();
-	return 0;
-}
-
-/**
- * Helper function to set the fast transition bits in the key management
- * bitmask, to allow FT support when possible.
- */
-void StaNetwork::setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	int res;
-	struct wpa_driver_capa capa;
-
-	if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
-		key_mgmt_mask |= WPA_KEY_MGMT_FT_PSK;
-	}
-
-	if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
-		key_mgmt_mask |= WPA_KEY_MGMT_FT_IEEE8021X;
-	}
-
-	res = wpa_drv_get_capa(wpa_s, &capa);
-	if (res == 0) {
-#ifdef CONFIG_IEEE80211R
-#ifdef CONFIG_SAE
-		if ((key_mgmt_mask & WPA_KEY_MGMT_SAE) &&
-		    (capa.key_mgmt_iftype[WPA_IF_STATION] & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE)) {
-			key_mgmt_mask |= WPA_KEY_MGMT_FT_SAE;
-		}
-#endif
-#endif
-	}
-
-}
-
-/**
- * Helper function to reset the fast transition bits in the key management
- * bitmask.
- */
-void StaNetwork::resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
-{
-	if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
-		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_PSK;
-	}
-
-	if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
-		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_IEEE8021X;
-	}
-#ifdef CONFIG_IEEE80211R
-#ifdef CONFIG_SAE
-	if (key_mgmt_mask & WPA_KEY_MGMT_SAE) {
-		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_SAE;
-	}
-#endif
-#endif
-}
-
-/**
- * Helper function to enable erp keys generation while connecting to FILS
- * enabled APs.
- */
-SupplicantStatus StaNetwork::setEapErpInternal(bool enable)
-{
-#ifdef CONFIG_FILS
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->eap.erp = enable ? 1 : 0;
-	return {SupplicantStatusCode::SUCCESS, ""};
-#else /* CONFIG_FILS */
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-#endif /* CONFIG_FILS */
-}
-
-V1_4::SupplicantStatus StaNetwork::setSaeH2eModeInternal(
-    ISupplicantStaNetworkV1_4::SaeH2eMode mode)
-{
-	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	switch (mode) {
-	case ISupplicantStaNetworkV1_4::SaeH2eMode::DISABLED:
-		wpa_s->conf->sae_pwe = 0;
-		break;
-	case ISupplicantStaNetworkV1_4::SaeH2eMode::H2E_MANDATORY:
-		wpa_s->conf->sae_pwe = 1;
-		break;
-	case ISupplicantStaNetworkV1_4::SaeH2eMode::H2E_OPTIONAL:
-		wpa_s->conf->sae_pwe = 2;
-		break;
-	}
-	resetInternalStateAfterParamsUpdate();
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-}
-
-V1_4::SupplicantStatus StaNetwork::enableSaePkOnlyModeInternal(bool enable)
-{
-#ifdef CONFIG_SAE_PK
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->sae_pk = enable ? SAE_PK_MODE_ONLY : SAE_PK_MODE_AUTOMATIC;
-	resetInternalStateAfterParamsUpdate();
-	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
-#else
-	return {V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""};
-#endif
-}
-
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wpa_supplicant/hidl/1.4/sta_network.h b/wpa_supplicant/hidl/1.4/sta_network.h
deleted file mode 100644
index 152f00f..0000000
--- a/wpa_supplicant/hidl/1.4/sta_network.h
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_STA_NETWORK_H
-#define WPA_SUPPLICANT_HIDL_STA_NETWORK_H
-
-#include <array>
-#include <vector>
-
-#include <android-base/macros.h>
-
-#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaNetwork.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/includes.h"
-#include "config.h"
-#include "wpa_supplicant_i.h"
-#include "notify.h"
-#include "eapol_supp/eapol_supp_sm.h"
-#include "eap_peer/eap.h"
-#include "rsn_supp/wpa.h"
-}
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using V1_0::ISupplicantStaNetworkCallback;
-using V1_2::DppFailureCode;
-using V1_2::DppProgressCode;
-
-/**
- * Implementation of StaNetwork hidl object. Each unique hidl
- * object is used for control operations on a specific network
- * controlled by wpa_supplicant.
- */
-class StaNetwork : public V1_4::ISupplicantStaNetwork
-{
-public:
-	StaNetwork(
-	    struct wpa_global* wpa_global, const char ifname[], int network_id);
-	~StaNetwork() override = default;
-	// Refer to |StaIface::invalidate()|.
-	void invalidate();
-	bool isValid();
-
-	// Hidl methods exposed.
-	Return<void> getId(getId_cb _hidl_cb) override;
-	Return<void> getInterfaceName(getInterfaceName_cb _hidl_cb) override;
-	Return<void> getType(getType_cb _hidl_cb) override;
-	Return<void> registerCallback(
-	    const sp<ISupplicantStaNetworkCallback>& callback,
-	    registerCallback_cb _hidl_cb) override;
-	Return<void> registerCallback_1_4(
-	    const sp<V1_4::ISupplicantStaNetworkCallback>& callback,
-	    registerCallback_1_4_cb _hidl_cb) override;
-	Return<void> setSsid(
-	    const hidl_vec<uint8_t>& ssid, setSsid_cb _hidl_cb) override;
-	Return<void> setBssid(
-	    const hidl_array<uint8_t, 6>& bssid, setBssid_cb _hidl_cb) override;
-	Return<void> setScanSsid(bool enable, setScanSsid_cb _hidl_cb) override;
-	Return<void> setKeyMgmt(
-	    uint32_t key_mgmt_mask, setKeyMgmt_cb _hidl_cb) override;
-	Return<void> setProto(
-	    uint32_t proto_mask, setProto_cb _hidl_cb) override;
-	Return<void> setAuthAlg(
-	    uint32_t auth_alg_mask, setAuthAlg_cb _hidl_cb) override;
-	Return<void> setGroupCipher(
-	    uint32_t group_cipher_mask, setGroupCipher_cb _hidl_cb) override;
-	Return<void> setPairwiseCipher(
-	    uint32_t pairwise_cipher_mask,
-	    setPairwiseCipher_cb _hidl_cb) override;
-	Return<void> setPskPassphrase(
-	    const hidl_string& psk, setPskPassphrase_cb _hidl_cb) override;
-	Return<void> setPsk(
-	    const hidl_array<uint8_t, 32>& psk, setPsk_cb _hidl_cb) override;
-	Return<void> setWepKey(
-	    uint32_t key_idx, const hidl_vec<uint8_t>& wep_key,
-	    setWepKey_cb _hidl_cb) override;
-	Return<void> setWepTxKeyIdx(
-	    uint32_t key_idx, setWepTxKeyIdx_cb _hidl_cb) override;
-	Return<void> setRequirePmf(
-	    bool enable, setRequirePmf_cb _hidl_cb) override;
-	Return<void> setEapMethod(
-	    ISupplicantStaNetwork::EapMethod method,
-	    setEapMethod_cb _hidl_cb) override;
-	Return<void> setEapPhase2Method(
-	    ISupplicantStaNetwork::EapPhase2Method method,
-	    setEapPhase2Method_cb _hidl_cb) override;
-	Return<void> setEapIdentity(
-	    const hidl_vec<uint8_t>& identity,
-	    setEapIdentity_cb _hidl_cb) override;
-	Return<void> setEapAnonymousIdentity(
-	    const hidl_vec<uint8_t>& identity,
-	    setEapAnonymousIdentity_cb _hidl_cb) override;
-	Return<void> setEapPassword(
-	    const hidl_vec<uint8_t>& password,
-	    setEapPassword_cb _hidl_cb) override;
-	Return<void> setEapCACert(
-	    const hidl_string& path, setEapCACert_cb _hidl_cb) override;
-	Return<void> setEapCAPath(
-	    const hidl_string& path, setEapCAPath_cb _hidl_cb) override;
-	Return<void> setEapClientCert(
-	    const hidl_string& path, setEapClientCert_cb _hidl_cb) override;
-	Return<void> setEapPrivateKeyId(
-	    const hidl_string& id, setEapPrivateKeyId_cb _hidl_cb) override;
-	Return<void> setEapEncryptedImsiIdentity(
-	    const EapSimEncryptedIdentity& identity,
-	    setEapEncryptedImsiIdentity_cb _hidl_cb) override;
-	Return<void> setEapSubjectMatch(
-	    const hidl_string& match, setEapSubjectMatch_cb _hidl_cb) override;
-	Return<void> setEapAltSubjectMatch(
-	    const hidl_string& match,
-	    setEapAltSubjectMatch_cb _hidl_cb) override;
-	Return<void> setEapEngine(
-	    bool enable, setEapEngine_cb _hidl_cb) override;
-	Return<void> setEapEngineID(
-	    const hidl_string& id, setEapEngineID_cb _hidl_cb) override;
-	Return<void> setEapDomainSuffixMatch(
-	    const hidl_string& match,
-	    setEapDomainSuffixMatch_cb _hidl_cb) override;
-	Return<void> setProactiveKeyCaching(
-	    bool enable, setProactiveKeyCaching_cb _hidl_cb) override;
-	Return<void> setIdStr(
-	    const hidl_string& id_str, setIdStr_cb _hidl_cb) override;
-	Return<void> setUpdateIdentifier(
-	    uint32_t id, setUpdateIdentifier_cb _hidl_cb) override;
-	Return<void> setEdmg(bool enable, setEdmg_cb _hidl_cb) override;
-	Return<void> getSsid(getSsid_cb _hidl_cb) override;
-	Return<void> getBssid(getBssid_cb _hidl_cb) override;
-	Return<void> getScanSsid(getScanSsid_cb _hidl_cb) override;
-	Return<void> getKeyMgmt(getKeyMgmt_cb _hidl_cb) override;
-	Return<void> getProto(getProto_cb _hidl_cb) override;
-	Return<void> getAuthAlg(getAuthAlg_cb _hidl_cb) override;
-	Return<void> getGroupCipher(getGroupCipher_cb _hidl_cb) override;
-	Return<void> getPairwiseCipher(getPairwiseCipher_cb _hidl_cb) override;
-	Return<void> getPskPassphrase(getPskPassphrase_cb _hidl_cb) override;
-	Return<void> getPsk(getPsk_cb _hidl_cb) override;
-	Return<void> getSaePassword(getSaePassword_cb _hidl_cb) override;
-	Return<void> getSaePasswordId(getSaePasswordId_cb _hidl_cb) override;
-	Return<void> getWepKey(
-	    uint32_t key_idx, getWepKey_cb _hidl_cb) override;
-	Return<void> getWepTxKeyIdx(getWepTxKeyIdx_cb _hidl_cb) override;
-	Return<void> getRequirePmf(getRequirePmf_cb _hidl_cb) override;
-	Return<void> getEapMethod(getEapMethod_cb _hidl_cb) override;
-	Return<void> getEapPhase2Method(
-	    getEapPhase2Method_cb _hidl_cb) override;
-	Return<void> getEapIdentity(getEapIdentity_cb _hidl_cb) override;
-	Return<void> getEapAnonymousIdentity(
-	    getEapAnonymousIdentity_cb _hidl_cb) override;
-	Return<void> getEapPassword(getEapPassword_cb _hidl_cb) override;
-	Return<void> getEapCACert(getEapCACert_cb _hidl_cb) override;
-	Return<void> getEapCAPath(getEapCAPath_cb _hidl_cb) override;
-	Return<void> getEapClientCert(getEapClientCert_cb _hidl_cb) override;
-	Return<void> getEapPrivateKeyId(
-	    getEapPrivateKeyId_cb _hidl_cb) override;
-	Return<void> getEapSubjectMatch(
-	    getEapSubjectMatch_cb _hidl_cb) override;
-	Return<void> getEapAltSubjectMatch(
-	    getEapAltSubjectMatch_cb _hidl_cb) override;
-	Return<void> getEapEngine(getEapEngine_cb _hidl_cb) override;
-	Return<void> getEapEngineID(getEapEngineID_cb _hidl_cb) override;
-	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> getEdmg(getEdmg_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;
-	Return<void> sendNetworkEapSimGsmAuthResponse(
-	    const hidl_vec<
-		ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>&
-		vec_params,
-	    sendNetworkEapSimGsmAuthResponse_cb _hidl_cb) override;
-	Return<void> sendNetworkEapSimGsmAuthFailure(
-	    sendNetworkEapSimGsmAuthFailure_cb _hidl_cb) override;
-	Return<void> sendNetworkEapSimUmtsAuthResponse(
-	    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams&
-		params,
-	    sendNetworkEapSimUmtsAuthResponse_cb _hidl_cb) override;
-	Return<void> sendNetworkEapSimUmtsAutsResponse(
-	    const hidl_array<uint8_t, 14>& auts,
-	    sendNetworkEapSimUmtsAutsResponse_cb _hidl_cb) override;
-	Return<void> sendNetworkEapSimUmtsAuthFailure(
-	    sendNetworkEapSimUmtsAuthFailure_cb _hidl_cb) override;
-	Return<void> sendNetworkEapIdentityResponse(
-	    const hidl_vec<uint8_t>& identity,
-	    sendNetworkEapIdentityResponse_cb _hidl_cb) override;
-	Return<void> sendNetworkEapIdentityResponse_1_1(
-	    const EapSimIdentity& identity,
-	    const EapSimEncryptedIdentity& imsiIdentity,
-	    sendNetworkEapIdentityResponse_1_1_cb _hidl_cb) override;
-	Return<void> setKeyMgmt_1_2(
-	    uint32_t key_mgmt_mask, setKeyMgmt_1_2_cb _hidl_cb) override;
-	Return<void> getKeyMgmt_1_2(getKeyMgmt_1_2_cb _hidl_cb) override;
-	Return<void> setPairwiseCipher_1_2(
-	    uint32_t pairwise_cipher_mask,
-	    setPairwiseCipher_1_2_cb _hidl_cb) override;
-	Return<void> getPairwiseCipher_1_2(
-	    getPairwiseCipher_1_2_cb _hidl_cb) override;
-	Return<void> setGroupCipher_1_2(
-	    uint32_t group_cipher_mask,
-	    setGroupCipher_1_2_cb _hidl_cb) override;
-	Return<void> getGroupCipher_1_2(
-	    getGroupCipher_1_2_cb _hidl_cb) override;
-	Return<void> setGroupMgmtCipher(
-	    uint32_t group_mgmt_cipher_mask,
-	    setGroupMgmtCipher_cb _hidl_cb) override;
-	Return<void> getGroupMgmtCipher(
-	    getGroupMgmtCipher_cb _hidl_cb) override;
-	Return<void> enableTlsSuiteBEapPhase1Param(
-	    bool enable, enableTlsSuiteBEapPhase1Param_cb _hidl_cb) override;
-	Return<void> enableSuiteBEapOpenSslCiphers(
-	    enableSuiteBEapOpenSslCiphers_cb _hidl_cb) override;
-	Return<void> setSaePassword(
-	    const hidl_string& sae_password,
-	    setSaePassword_cb _hidl_cb) override;
-	Return<void> setSaePasswordId(
-	    const hidl_string& sae_password_id,
-	    setSaePasswordId_cb _hidl_cb) override;
-	Return<void> setOcsp(
-	    V1_3::OcspType ocspType, setOcsp_cb _hidl_cb) override;
-	Return<void> getOcsp(
-	    getOcsp_cb _hidl_cb) override;
-	Return<void> setPmkCache(const hidl_vec<uint8_t>& serializedEntry,
-			setPmkCache_cb _hidl_cb) override;
-	Return<void> setKeyMgmt_1_3(
-	    uint32_t key_mgmt_mask, setKeyMgmt_1_3_cb _hidl_cb) override;
-	Return<void> getKeyMgmt_1_3(getKeyMgmt_1_3_cb _hidl_cb) override;
-	Return<void> setProto_1_3(
-	    uint32_t proto_mask, setProto_cb _hidl_cb) override;
-	Return<void> getProto_1_3(getProto_cb _hidl_cb) override;
-	Return<void> setPairwiseCipher_1_3(
-	    uint32_t pairwise_cipher_mask,
-	    setPairwiseCipher_1_3_cb _hidl_cb) override;
-	Return<void> getPairwiseCipher_1_3(
-	    getPairwiseCipher_1_3_cb _hidl_cb) override;
-	Return<void> setGroupCipher_1_3(
-	    uint32_t group_cipher_mask,
-	    setGroupCipher_1_3_cb _hidl_cb) override;
-	Return<void> getGroupCipher_1_3(
-	    getGroupCipher_1_3_cb _hidl_cb) override;
-	Return<void> setWapiCertSuite(
-	    const hidl_string& suite, setWapiCertSuite_cb _hidl_cb) override;
-	Return<void> getWapiCertSuite(getWapiCertSuite_cb _hidl_cb) override;
-	Return<void> getAuthAlg_1_3(getAuthAlg_cb _hidl_cb) override;
-	Return<void> setAuthAlg_1_3(uint32_t auth_alg_mask,
-			std::function<void(const SupplicantStatus &status)> _hidl_cb)
-					override;
-	Return<void> setEapErp(bool enable, setEapErp_cb _hidl_cb) override;
-	Return<void> setPairwiseCipher_1_4(
-	    uint32_t pairwise_cipher_mask,
-	    setPairwiseCipher_1_4_cb _hidl_cb) override;
-	Return<void> getPairwiseCipher_1_4(
-	    getPairwiseCipher_1_4_cb _hidl_cb) override;
-	Return<void> setGroupCipher_1_4(
-	    uint32_t group_cipher_mask,
-	    setGroupCipher_1_4_cb _hidl_cb) override;
-	Return<void> getGroupCipher_1_4(
-	    getGroupCipher_1_4_cb _hidl_cb) override;
-	Return<void> setSaeH2eMode(V1_4::ISupplicantStaNetwork::SaeH2eMode mode,
-	    setSaeH2eMode_cb _hidl_cb) override;
-	Return<void> enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb) override;
-
-private:
-	// Corresponding worker functions for the HIDL methods.
-	std::pair<SupplicantStatus, uint32_t> getIdInternal();
-	std::pair<SupplicantStatus, std::string> getInterfaceNameInternal();
-	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
-	SupplicantStatus registerCallbackInternal(
-	    const sp<ISupplicantStaNetworkCallback>& callback);
-	V1_4::SupplicantStatus registerCallback_1_4Internal(
-	    const sp<V1_4::ISupplicantStaNetworkCallback>& callback);
-	SupplicantStatus setSsidInternal(const std::vector<uint8_t>& ssid);
-	SupplicantStatus setBssidInternal(const std::array<uint8_t, 6>& bssid);
-	SupplicantStatus setScanSsidInternal(bool enable);
-	SupplicantStatus setKeyMgmtInternal(uint32_t key_mgmt_mask);
-	SupplicantStatus setProtoInternal(uint32_t proto_mask);
-	SupplicantStatus setAuthAlgInternal(uint32_t auth_alg_mask);
-	SupplicantStatus setGroupCipherInternal(uint32_t group_cipher_mask);
-	SupplicantStatus setPairwiseCipherInternal(
-	    uint32_t pairwise_cipher_mask);
-	SupplicantStatus setPskPassphraseInternal(const std::string& psk);
-	SupplicantStatus setPskInternal(const std::array<uint8_t, 32>& psk);
-	SupplicantStatus setWepKeyInternal(
-	    uint32_t key_idx, const std::vector<uint8_t>& wep_key);
-	SupplicantStatus setWepTxKeyIdxInternal(uint32_t key_idx);
-	SupplicantStatus setRequirePmfInternal(bool enable);
-	SupplicantStatus setEapMethodInternal(
-	    ISupplicantStaNetwork::EapMethod method);
-	SupplicantStatus setEapPhase2MethodInternal(
-	    ISupplicantStaNetwork::EapPhase2Method method);
-	SupplicantStatus setEapIdentityInternal(
-	    const std::vector<uint8_t>& identity);
-	SupplicantStatus setEapEncryptedImsiIdentityInternal(
-	    const std::vector<uint8_t>& identity);
-	SupplicantStatus setEapAnonymousIdentityInternal(
-	    const std::vector<uint8_t>& identity);
-	SupplicantStatus setEapPasswordInternal(
-	    const std::vector<uint8_t>& password);
-	SupplicantStatus setEapCACertInternal(const std::string& path);
-	SupplicantStatus setEapCAPathInternal(const std::string& path);
-	SupplicantStatus setEapClientCertInternal(const std::string& path);
-	SupplicantStatus setEapPrivateKeyIdInternal(const std::string& id);
-	SupplicantStatus setEapSubjectMatchInternal(const std::string& match);
-	SupplicantStatus setEapAltSubjectMatchInternal(
-	    const std::string& match);
-	SupplicantStatus setEapEngineInternal(bool enable);
-	SupplicantStatus setEapEngineIDInternal(const std::string& id);
-	SupplicantStatus setEapDomainSuffixMatchInternal(
-	    const std::string& match);
-	SupplicantStatus setProactiveKeyCachingInternal(bool enable);
-	SupplicantStatus setIdStrInternal(const std::string& id_str);
-	SupplicantStatus setUpdateIdentifierInternal(uint32_t id);
-	V1_4::SupplicantStatus setEdmgInternal(bool enable);
-	std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal();
-	std::pair<SupplicantStatus, std::array<uint8_t, 6>> getBssidInternal();
-	std::pair<SupplicantStatus, bool> getScanSsidInternal();
-	std::pair<SupplicantStatus, uint32_t> getKeyMgmtInternal();
-	std::pair<SupplicantStatus, uint32_t> getProtoInternal();
-	std::pair<SupplicantStatus, uint32_t> getAuthAlgInternal();
-	std::pair<SupplicantStatus, uint32_t> getGroupCipherInternal();
-	std::pair<SupplicantStatus, uint32_t> getPairwiseCipherInternal();
-	std::pair<SupplicantStatus, std::string> getPskPassphraseInternal();
-	std::pair<SupplicantStatus, std::array<uint8_t, 32>> getPskInternal();
-	std::pair<SupplicantStatus, std::string> getSaePasswordInternal();
-	std::pair<SupplicantStatus, std::string> getSaePasswordIdInternal();
-	std::pair<SupplicantStatus, std::vector<uint8_t>> getWepKeyInternal(
-	    uint32_t key_idx);
-	std::pair<SupplicantStatus, uint32_t> getWepTxKeyIdxInternal();
-	std::pair<SupplicantStatus, bool> getRequirePmfInternal();
-	std::pair<SupplicantStatus, ISupplicantStaNetwork::EapMethod>
-	getEapMethodInternal();
-	std::pair<SupplicantStatus, ISupplicantStaNetwork::EapPhase2Method>
-	getEapPhase2MethodInternal();
-	std::pair<SupplicantStatus, std::vector<uint8_t>>
-	getEapIdentityInternal();
-	std::pair<SupplicantStatus, std::vector<uint8_t>>
-	getEapAnonymousIdentityInternal();
-	std::pair<SupplicantStatus, std::vector<uint8_t>>
-	getEapPasswordInternal();
-	std::pair<SupplicantStatus, std::string> getEapCACertInternal();
-	std::pair<SupplicantStatus, std::string> getEapCAPathInternal();
-	std::pair<SupplicantStatus, std::string> getEapClientCertInternal();
-	std::pair<SupplicantStatus, std::string> getEapPrivateKeyIdInternal();
-	std::pair<SupplicantStatus, std::string> getEapSubjectMatchInternal();
-	std::pair<SupplicantStatus, std::string>
-	getEapAltSubjectMatchInternal();
-	std::pair<SupplicantStatus, bool> getEapEngineInternal();
-	std::pair<SupplicantStatus, std::string> getEapEngineIDInternal();
-	std::pair<SupplicantStatus, std::string>
-	getEapDomainSuffixMatchInternal();
-	std::pair<SupplicantStatus, std::string> getIdStrInternal();
-	std::pair<SupplicantStatus, std::vector<uint8_t>>
-	getWpsNfcConfigurationTokenInternal();
-	std::pair<V1_4::SupplicantStatus, bool> getEdmgInternal();
-	SupplicantStatus enableInternal(bool no_connect);
-	SupplicantStatus disableInternal();
-	SupplicantStatus selectInternal();
-	SupplicantStatus sendNetworkEapSimGsmAuthResponseInternal(
-	    const std::vector<
-		ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>&
-		vec_params);
-	SupplicantStatus sendNetworkEapSimGsmAuthFailureInternal();
-	SupplicantStatus sendNetworkEapSimUmtsAuthResponseInternal(
-	    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams&
-		params);
-	SupplicantStatus sendNetworkEapSimUmtsAutsResponseInternal(
-	    const std::array<uint8_t, 14>& auts);
-	SupplicantStatus sendNetworkEapSimUmtsAuthFailureInternal();
-	SupplicantStatus sendNetworkEapIdentityResponseInternal(
-	    const std::vector<uint8_t>& identity);
-	SupplicantStatus sendNetworkEapIdentityResponseInternal_1_1(
-	    const std::vector<uint8_t>& identity,
-	    const std::vector<uint8_t>& imsi_identity);
-	SupplicantStatus enableTlsSuiteBEapPhase1ParamInternal(bool enable);
-	SupplicantStatus enableSuiteBEapOpenSslCiphersInternal();
-	SupplicantStatus setSaePasswordInternal(
-	    const std::string& sae_password);
-	SupplicantStatus setSaePasswordIdInternal(
-	    const std::string& sae_password_id);
-	SupplicantStatus setGroupMgmtCipherInternal(uint32_t group_mgmt_cipher_mask);
-	std::pair<SupplicantStatus, uint32_t> getGroupMgmtCipherInternal();
-	SupplicantStatus setOcspInternal(V1_3::OcspType ocspType);
-	std::pair<SupplicantStatus, V1_3::OcspType> getOcspInternal();
-	SupplicantStatus setPmkCacheInternal(const std::vector<uint8_t>& serialziedEntry);
-	SupplicantStatus setWapiCertSuiteInternal(const std::string& suite);
-	std::pair<SupplicantStatus, std::string> getWapiCertSuiteInternal();
-	SupplicantStatus setKeyMgmt_1_3Internal(uint32_t key_mgmt_mask);
-	std::pair<SupplicantStatus, uint32_t> getKeyMgmt_1_3Internal();
-	SupplicantStatus setProto_1_3Internal(uint32_t proto_mask);
-	std::pair<SupplicantStatus, uint32_t> getProto_1_3Internal();
-	std::pair<SupplicantStatus, uint32_t> getGroupCipher_1_3Internal();
-	SupplicantStatus setGroupCipher_1_3Internal(uint32_t group_cipher_mask);
-	std::pair<SupplicantStatus, uint32_t> getPairwiseCipher_1_3Internal();
-	SupplicantStatus setPairwiseCipher_1_3Internal(
-	    uint32_t pairwise_cipher_mask);
-	SupplicantStatus setWapiPskInternal(const std::vector<uint8_t>& psk);
-	std::pair<SupplicantStatus, std::vector<uint8_t>> getWapiPskInternal();
-	std::pair<V1_4::SupplicantStatus, uint32_t> getGroupCipher_1_4Internal();
-	V1_4::SupplicantStatus setGroupCipher_1_4Internal(uint32_t group_cipher_mask);
-	std::pair<V1_4::SupplicantStatus, uint32_t> getPairwiseCipher_1_4Internal();
-	V1_4::SupplicantStatus setPairwiseCipher_1_4Internal(
-	    uint32_t pairwise_cipher_mask);
-	V1_4::SupplicantStatus setSaeH2eModeInternal(V1_4::ISupplicantStaNetwork::SaeH2eMode mode);
-	V1_4::SupplicantStatus enableSaePkOnlyModeInternal(bool enable);
-
-	struct wpa_ssid* retrieveNetworkPtr();
-	struct wpa_supplicant* retrieveIfacePtr();
-	int isPskPassphraseValid(const std::string& psk);
-	void resetInternalStateAfterParamsUpdate();
-	int setStringFieldAndResetState(
-	    const char* value, uint8_t** to_update_field,
-	    const char* hexdump_prefix);
-	int setStringFieldAndResetState(
-	    const char* value, char** to_update_field,
-	    const char* hexdump_prefix);
-	int setStringKeyFieldAndResetState(
-	    const char* value, char** to_update_field,
-	    const char* hexdump_prefix);
-	int setByteArrayFieldAndResetState(
-	    const uint8_t* value, const size_t value_len,
-	    uint8_t** to_update_field, size_t* to_update_field_len,
-	    const char* hexdump_prefix);
-	int setByteArrayKeyFieldAndResetState(
-	    const uint8_t* value, const size_t value_len,
-	    uint8_t** to_update_field, size_t* to_update_field_len,
-	    const char* hexdump_prefix);
-	void setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
-	void resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
-	SupplicantStatus setEapErpInternal(bool enable);
-
-	// Reference to the global wpa_struct. This is assumed to be valid
-	// for the lifetime of the process.
-	struct wpa_global* wpa_global_;
-	// Name of the iface this network belongs to.
-	const std::string ifname_;
-	// Id of the network this hidl object controls.
-	const int network_id_;
-	bool is_valid_;
-
-	DISALLOW_COPY_AND_ASSIGN(StaNetwork);
-};
-
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WPA_SUPPLICANT_HIDL_STA_NETWORK_H
diff --git a/wpa_supplicant/hidl/1.4/supplicant.cpp b/wpa_supplicant/hidl/1.4/supplicant.cpp
deleted file mode 100644
index d8b18bb..0000000
--- a/wpa_supplicant/hidl/1.4/supplicant.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * 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.
- */
-
-#include "hidl_manager.h"
-#include "hidl_return_util.h"
-#include "supplicant.h"
-#include "p2p_iface.h"
-
-#include <android-base/file.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-namespace {
-
-// Pre-populated interface params for interfaces controlled by wpa_supplicant.
-// Note: This may differ for other OEM's. So, modify this accordingly.
-constexpr char kIfaceDriverName[] = "nl80211";
-constexpr char kStaIfaceConfPath[] =
-    "/data/vendor/wifi/wpa/wpa_supplicant.conf";
-static const char* kStaIfaceConfOverlayPaths[] = {
-    "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant_overlay.conf",
-    "/vendor/etc/wifi/wpa_supplicant_overlay.conf",
-};
-constexpr char kP2pIfaceConfPath[] =
-    "/data/vendor/wifi/wpa/p2p_supplicant.conf";
-static const char* kP2pIfaceConfOverlayPaths[] = {
-    "/apex/com.android.wifi.hal/etc/wifi/p2p_supplicant_overlay.conf",
-    "/vendor/etc/wifi/p2p_supplicant_overlay.conf",
-};
-// Migrate conf files for existing devices.
-static const char* kTemplateConfPaths[] = {
-    "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant.conf",
-    "/vendor/etc/wifi/wpa_supplicant.conf",
-    "/system/etc/wifi/wpa_supplicant.conf",
-};
-constexpr char kOldStaIfaceConfPath[] = "/data/misc/wifi/wpa_supplicant.conf";
-constexpr char kOldP2pIfaceConfPath[] = "/data/misc/wifi/p2p_supplicant.conf";
-constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
-
-const char* resolvePath(const char* paths[], size_t size)
-{
-	for (int i = 0; i < size; ++i) {
-		if (access(paths[i], R_OK) == 0) {
-			return paths[i];
-		}
-	}
-	return nullptr;
-}
-
-int copyFile(
-    const std::string& src_file_path, const std::string& dest_file_path)
-{
-	std::string file_contents;
-	if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
-		wpa_printf(
-		    MSG_ERROR, "Failed to read from %s. Errno: %s",
-		    src_file_path.c_str(), strerror(errno));
-		return -1;
-	}
-	if (!android::base::WriteStringToFile(
-		file_contents, dest_file_path, kConfigFileMode, getuid(),
-		getgid())) {
-		wpa_printf(
-		    MSG_ERROR, "Failed to write to %s. Errno: %s",
-		    dest_file_path.c_str(), strerror(errno));
-		return -1;
-	}
-	return 0;
-}
-
-/**
- * Copy |src_file_path| to |dest_file_path| if it exists.
- *
- * Returns 1 if |src_file_path| does not exist or not accessible,
- * Returns -1 if the copy fails.
- * Returns 0 if the copy succeeds.
- */
-int copyFileIfItExists(
-    const std::string& src_file_path, const std::string& dest_file_path)
-{
-	int ret = access(src_file_path.c_str(), R_OK);
-	// Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT.
-	if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) {
-		return 1;
-	}
-	ret = copyFile(src_file_path, dest_file_path);
-	if (ret != 0) {
-		wpa_printf(
-		    MSG_ERROR, "Failed copying %s to %s.",
-		    src_file_path.c_str(), dest_file_path.c_str());
-		return -1;
-	}
-	return 0;
-}
-
-/**
- * Ensure that the specified config file pointed by |config_file_path| exists.
- * a) If the |config_file_path| exists with the correct permissions, return.
- * b) If the |config_file_path| does not exist, but |old_config_file_path|
- * exists, copy over the contents of the |old_config_file_path| to
- * |config_file_path|.
- * c) If the |config_file_path| & |old_config_file_path|
- * does not exists, copy over the contents of |template_config_file_path|.
- */
-int ensureConfigFileExists(
-    const std::string& config_file_path,
-    const std::string& old_config_file_path)
-{
-	int ret = access(config_file_path.c_str(), R_OK | W_OK);
-	if (ret == 0) {
-		return 0;
-	}
-	if (errno == EACCES) {
-		ret = chmod(config_file_path.c_str(), kConfigFileMode);
-		if (ret == 0) {
-			return 0;
-		} else {
-			wpa_printf(
-			    MSG_ERROR, "Cannot set RW to %s. Errno: %s",
-			    config_file_path.c_str(), strerror(errno));
-			return -1;
-		}
-	} else if (errno != ENOENT) {
-		wpa_printf(
-		    MSG_ERROR, "Cannot acces %s. Errno: %s",
-		    config_file_path.c_str(), strerror(errno));
-		return -1;
-	}
-	ret = copyFileIfItExists(old_config_file_path, config_file_path);
-	if (ret == 0) {
-		wpa_printf(
-		    MSG_INFO, "Migrated conf file from %s to %s",
-		    old_config_file_path.c_str(), config_file_path.c_str());
-		unlink(old_config_file_path.c_str());
-		return 0;
-	} else if (ret == -1) {
-		unlink(config_file_path.c_str());
-		return -1;
-	}
-	const char* path =
-	    resolvePath(kTemplateConfPaths, sizeof(kTemplateConfPaths));
-	if (path != nullptr) {
-		ret = copyFileIfItExists(path, config_file_path);
-		if (ret == 0) {
-			wpa_printf(
-			    MSG_INFO, "Copied template conf file from %s to %s",
-			    path, config_file_path.c_str());
-			return 0;
-		} else if (ret == -1) {
-			unlink(config_file_path.c_str());
-			return -1;
-		}
-	}
-	// Did not create the conf file.
-	return -1;
-}
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using V1_0::SupplicantStatusCode;
-
-Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
-bool Supplicant::isValid()
-{
-	// This top level object cannot be invalidated.
-	return true;
-}
-
-Return<void> Supplicant::addInterface(
-    const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &Supplicant::addInterfaceInternal, _hidl_cb, iface_info);
-}
-
-Return<void> Supplicant::removeInterface(
-    const IfaceInfo& iface_info, removeInterface_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &Supplicant::removeInterfaceInternal, _hidl_cb, iface_info);
-}
-
-Return<void> Supplicant::getInterface(
-    const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &Supplicant::getInterfaceInternal, _hidl_cb, iface_info);
-}
-
-Return<void> Supplicant::listInterfaces(listInterfaces_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &Supplicant::listInterfacesInternal, _hidl_cb);
-}
-
-Return<void> Supplicant::registerCallback(
-    const sp<ISupplicantCallback>& callback, registerCallback_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &Supplicant::registerCallbackInternal, _hidl_cb, callback);
-}
-
-Return<void> Supplicant::setDebugParams(
-    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
-    setDebugParams_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &Supplicant::setDebugParamsInternal, _hidl_cb, level,
-	    show_timestamp, show_keys);
-}
-
-Return<void> Supplicant::setConcurrencyPriority(
-    IfaceType type, setConcurrencyPriority_cb _hidl_cb)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-	    &Supplicant::setConcurrencyPriorityInternal, _hidl_cb, type);
-}
-
-Return<ISupplicant::DebugLevel> Supplicant::getDebugLevel()
-{
-	// TODO: Add SupplicantStatus in this method return for uniformity with
-	// the other methods in supplicant HIDL interface.
-	return (ISupplicant::DebugLevel)wpa_debug_level;
-}
-
-Return<bool> Supplicant::isDebugShowTimestampEnabled()
-{
-	// TODO: Add SupplicantStatus in this method return for uniformity with
-	// the other methods in supplicant HIDL interface.
-	return ((wpa_debug_timestamp != 0) ? true : false);
-}
-
-Return<bool> Supplicant::isDebugShowKeysEnabled()
-{
-	// TODO: Add SupplicantStatus in this method return for uniformity with
-	// the other methods in supplicant HIDL interface.
-	return ((wpa_debug_show_keys != 0) ? true : false);
-}
-
-Return<void> Supplicant::terminate()
-{
-	wpa_printf(MSG_INFO, "Terminating...");
-	wpa_supplicant_terminate_proc(wpa_global_);
-	return Void();
-}
-
-std::pair<SupplicantStatus, sp<ISupplicantIface>>
-Supplicant::addP2pDevInterface(struct wpa_interface iface_params)
-{
-	char primary_ifname[IFNAMSIZ];
-	u32 primary_ifname_len =
-		strlen(iface_params.ifname) - strlen(P2P_MGMT_DEVICE_PREFIX);
-
-	if(primary_ifname_len > IFNAMSIZ) {
-		wpa_printf(MSG_DEBUG, "%s, Invalid primary iface name ", __FUNCTION__);
-		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
-	}
-
-	strncpy(primary_ifname, iface_params.ifname +
-		strlen(P2P_MGMT_DEVICE_PREFIX), primary_ifname_len);
-	wpa_printf(MSG_DEBUG, "%s, Initialize p2p-dev-wlan0 iface with"
-		"primary_iface = %s", __FUNCTION__, primary_ifname);
-	struct wpa_supplicant* wpa_s =
-		wpa_supplicant_get_iface(wpa_global_, primary_ifname);
-	if (!wpa_s) {
-		wpa_printf(MSG_DEBUG, "%s,NULL wpa_s for wlan0", __FUNCTION__);
-		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
-			nullptr};
-	}
-	if (wpas_p2p_add_p2pdev_interface(
-		wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
-		wpa_printf(MSG_INFO,
-			"Failed to enable P2P Device");
-		return {{SupplicantStatusCode::FAILURE_UNKNOWN,
-			"Enable P2P Device failed"}, {}};
-	}
-	return {{SupplicantStatusCode::SUCCESS,""}, {}};
-}
-
-std::pair<SupplicantStatus, sp<ISupplicantIface>>
-Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
-{
-	android::sp<ISupplicantIface> iface;
-
-	// Check if required |ifname| argument is empty.
-	if (iface_info.name.empty()) {
-		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
-	}
-	// Try to get the wpa_supplicant record for this iface, return
-	// the iface object with the appropriate status code if it exists.
-	SupplicantStatus status;
-	std::tie(status, iface) = getInterfaceInternal(iface_info);
-	if (status.code == SupplicantStatusCode::SUCCESS) {
-		return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},
-			iface};
-	}
-
-	struct wpa_interface iface_params = {};
-	iface_params.driver = kIfaceDriverName;
-	if (iface_info.type == IfaceType::P2P) {
-		if (ensureConfigFileExists(
-			kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
-			wpa_printf(
-			    MSG_ERROR, "Conf file does not exists: %s",
-			    kP2pIfaceConfPath);
-			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
-				 "Conf file does not exist"},
-				{}};
-		}
-		iface_params.confname = kP2pIfaceConfPath;
-		const char* path = resolvePath(
-		    kP2pIfaceConfOverlayPaths,
-		    sizeof(kP2pIfaceConfOverlayPaths));
-		if (path != nullptr) {
-			iface_params.confanother = path;
-		}
-	} else {
-		if (ensureConfigFileExists(
-			kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
-			wpa_printf(
-			    MSG_ERROR, "Conf file does not exists: %s",
-			    kStaIfaceConfPath);
-			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
-				 "Conf file does not exist"},
-				{}};
-		}
-		iface_params.confname = kStaIfaceConfPath;
-		const char* path = resolvePath(
-		    kStaIfaceConfOverlayPaths,
-		    sizeof(kStaIfaceConfOverlayPaths));
-		if (path != nullptr) {
-			iface_params.confanother = path;
-		}
-	}
-	iface_params.ifname = iface_info.name.c_str();
-	if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
-		strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
-		std::tie(status, iface) = addP2pDevInterface(iface_params);
-		if (status.code != SupplicantStatusCode::SUCCESS) {
-			return {{status.code,
-				status.debugMessage.c_str()}, iface};
-		}
-	} else {
-		struct wpa_supplicant* wpa_s =
-			wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
-		if (!wpa_s) {
-			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
-		}
-		//Request the current scan results from the driver and updates
-		//the local BSS list wpa_s->bss. This is to avoid a full scan
-		//while processing the connect request on newly created interface.
-		wpa_supplicant_update_scan_results(wpa_s);
-	}
-	// The supplicant core creates a corresponding hidl object via
-	// HidlManager when |wpa_supplicant_add_iface| is called.
-	return getInterfaceInternal(iface_info);
-}
-
-SupplicantStatus Supplicant::removeInterfaceInternal(
-    const IfaceInfo& iface_info)
-{
-	struct wpa_supplicant* wpa_s =
-	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
-	if (!wpa_s) {
-		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
-	}
-	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-std::pair<SupplicantStatus, sp<ISupplicantIface>>
-Supplicant::getInterfaceInternal(const IfaceInfo& iface_info)
-{
-	struct wpa_supplicant* wpa_s =
-	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
-	if (!wpa_s) {
-		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
-			nullptr};
-	}
-	HidlManager* hidl_manager = HidlManager::getInstance();
-	if (iface_info.type == IfaceType::P2P) {
-		android::sp<ISupplicantP2pIface> iface;
-		if (!hidl_manager ||
-		    hidl_manager->getP2pIfaceHidlObjectByIfname(
-			wpa_s->ifname, &iface)) {
-			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
-				iface};
-		}
-		// Set this flag true here, since there is no HIDL initialize
-		// method for the p2p config, and the supplicant interface is
-		// not ready when the p2p iface is created.
-		wpa_s->conf->persistent_reconnect = true;
-		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
-	} else {
-		android::sp<V1_1::ISupplicantStaIface> iface;
-		if (!hidl_manager ||
-		    hidl_manager->getStaIfaceHidlObjectByIfname(
-			wpa_s->ifname, &iface)) {
-			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
-				iface};
-		}
-		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
-	}
-}
-
-std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
-Supplicant::listInterfacesInternal()
-{
-	std::vector<ISupplicant::IfaceInfo> ifaces;
-	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
-	     wpa_s = wpa_s->next) {
-		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
-			ifaces.emplace_back(ISupplicant::IfaceInfo{
-			    IfaceType::P2P, wpa_s->ifname});
-		} else {
-			ifaces.emplace_back(ISupplicant::IfaceInfo{
-			    IfaceType::STA, wpa_s->ifname});
-		}
-	}
-	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ifaces)};
-}
-
-SupplicantStatus Supplicant::registerCallbackInternal(
-    const sp<ISupplicantCallback>& callback)
-{
-	HidlManager* hidl_manager = HidlManager::getInstance();
-	if (!hidl_manager ||
-	    hidl_manager->addSupplicantCallbackHidlObject(callback)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus Supplicant::setDebugParamsInternal(
-    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys)
-{
-	if (wpa_supplicant_set_debug_params(
-		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
-		show_keys)) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
-	return {SupplicantStatusCode::SUCCESS, ""};
-}
-
-SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
-{
-	if (type == IfaceType::STA) {
-		wpa_global_->conc_pref =
-		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
-	} else if (type == IfaceType::P2P) {
-		wpa_global_->conc_pref =
-		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
-	} else {
-		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
-	}
-	return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""};
-}
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wpa_supplicant/hidl/1.4/supplicant.h b/wpa_supplicant/hidl/1.4/supplicant.h
deleted file mode 100644
index c2b172c..0000000
--- a/wpa_supplicant/hidl/1.4/supplicant.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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 WPA_SUPPLICANT_HIDL_SUPPLICANT_H
-#define WPA_SUPPLICANT_HIDL_SUPPLICANT_H
-
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantCallback.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantIface.h>
-#include <android/hardware/wifi/supplicant/1.0/types.h>
-#include <android/hardware/wifi/supplicant/1.4/ISupplicant.h>
-#include <android-base/macros.h>
-#include <hidl/Status.h>
-
-extern "C"
-{
-#include "utils/common.h"
-#include "utils/includes.h"
-#include "utils/wpa_debug.h"
-#include "wpa_supplicant_i.h"
-#include "scan.h"
-}
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace supplicant {
-namespace V1_4 {
-namespace implementation {
-using V1_0::ISupplicantCallback;
-using V1_0::ISupplicantIface;
-
-/**
- * Implementation of the supplicant hidl object. This hidl
- * object is used core for global control operations on
- * wpa_supplicant.
- */
-class Supplicant : public V1_4::ISupplicant
-{
-public:
-	Supplicant(struct wpa_global* global);
-	~Supplicant() override = default;
-	bool isValid();
-
-	// Hidl methods exposed.
-	Return<void> addInterface(
-	    const IfaceInfo& iface_info, addInterface_cb _hidl_cb) override;
-	Return<void> removeInterface(
-	    const IfaceInfo& iface_info, removeInterface_cb _hidl_cb) override;
-	Return<void> getInterface(
-	    const IfaceInfo& iface_info, getInterface_cb _hidl_cb) override;
-	Return<void> listInterfaces(listInterfaces_cb _hidl_cb) override;
-	Return<void> registerCallback(
-	    const sp<ISupplicantCallback>& callback,
-	    registerCallback_cb _hidl_cb) override;
-	Return<void> setDebugParams(
-	    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
-	    setDebugParams_cb _hidl_cb) override;
-	Return<ISupplicant::DebugLevel> getDebugLevel() override;
-	Return<bool> isDebugShowTimestampEnabled() override;
-	Return<bool> isDebugShowKeysEnabled() override;
-	Return<void> setConcurrencyPriority(
-	    IfaceType type, setConcurrencyPriority_cb _hidl_cb) override;
-	Return<void> terminate() override;
-
-private:
-	// Corresponding worker functions for the HIDL methods.
-	std::pair<SupplicantStatus, sp<ISupplicantIface>> getInterfaceInternal(
-	    const IfaceInfo& iface_info);
-	std::pair<SupplicantStatus, sp<ISupplicantIface>> addInterfaceInternal(
-	    const IfaceInfo& iface_info);
-	SupplicantStatus removeInterfaceInternal(const IfaceInfo& iface_info);
-	std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
-	listInterfacesInternal();
-	SupplicantStatus registerCallbackInternal(
-	    const sp<ISupplicantCallback>& callback);
-	SupplicantStatus setDebugParamsInternal(
-	    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys);
-	SupplicantStatus setConcurrencyPriorityInternal(IfaceType type);
-	std::pair<SupplicantStatus, sp<ISupplicantIface>> addP2pDevInterface(
-	    struct wpa_interface iface_params);
-
-	// Raw pointer to the global structure maintained by the core.
-	struct wpa_global* wpa_global_;
-	// Driver name to be used for creating interfaces.
-	static const char kDriverName[];
-	// wpa_supplicant.conf file location on the device.
-	static const char kConfigFilePath[];
-
-	DISALLOW_COPY_AND_ASSIGN(Supplicant);
-};
-
-}  // namespace implementation
-}  // namespace V1_4
-}  // namespace supplicant
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WPA_SUPPLICANT_HIDL_SUPPLICANT_H
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index b93f2a3..ca380b9 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -702,12 +702,14 @@
 	    ((cred->password == NULL ||
 	      cred->password[0] == '\0') &&
 	     (cred->private_key == NULL ||
-	      cred->private_key[0] == '\0'))) {
+	      cred->private_key[0] == '\0') &&
+	     (!cred->key_id || cred->key_id[0] == '\0'))) {
 		wpa_msg(wpa_s, MSG_DEBUG,
-			"nai-realm-find-eap: incomplete cred info: username: %s  password: %s private_key: %s",
+			"nai-realm-find-eap: incomplete cred info: username: %s  password: %s private_key: %s key_id: %s",
 			cred->username ? cred->username : "NULL",
 			cred->password ? cred->password : "NULL",
-			cred->private_key ? cred->private_key : "NULL");
+			cred->private_key ? cred->private_key : "NULL",
+			cred->key_id ? cred->key_id : "NULL");
 		return NULL;
 	}
 
@@ -716,7 +718,8 @@
 		if (cred->password && cred->password[0] &&
 		    nai_realm_cred_username(wpa_s, eap))
 			return eap;
-		if (cred->private_key && cred->private_key[0] &&
+		if (((cred->private_key && cred->private_key[0]) ||
+		     (cred->key_id && cred->key_id[0])) &&
 		    nai_realm_cred_cert(wpa_s, eap))
 			return eap;
 	}
@@ -1539,6 +1542,24 @@
 				  cred->private_key_passwd) < 0)
 		return -1;
 
+	if (cred->ca_cert_id && cred->ca_cert_id[0] &&
+	    wpa_config_set_quoted(ssid, "ca_cert_id", cred->ca_cert_id) < 0)
+		return -1;
+
+	if (cred->cert_id && cred->cert_id[0] &&
+	    wpa_config_set_quoted(ssid, "cert_id", cred->cert_id) < 0)
+		return -1;
+
+	if (cred->key_id && cred->key_id[0] &&
+	    wpa_config_set_quoted(ssid, "key_id", cred->key_id) < 0)
+		return -1;
+
+	if (cred->engine_id && cred->engine_id[0] &&
+	    wpa_config_set_quoted(ssid, "engine_id", cred->engine_id) < 0)
+		return -1;
+
+	ssid->eap.cert.engine = cred->engine;
+
 	if (cred->phase1) {
 		os_free(ssid->eap.phase1);
 		ssid->eap.phase1 = os_strdup(cred->phase1);
@@ -2481,13 +2502,9 @@
 		bh = cred_below_min_backhaul(wpa_s, cred, bss);
 		bss_load = cred_over_max_bss_load(wpa_s, cred, bss);
 		conn_capab = cred_conn_capab_missing(wpa_s, cred, bss);
-		wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d",
-			excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP,
-			MAC2STR(bss->bssid), type,
-			bh ? " below_min_backhaul=1" : "",
-			bss_load ? " over_max_bss_load=1" : "",
-			conn_capab ? " conn_capab_missing=1" : "",
-			cred->id, cred->priority, cred->sp_priority);
+		wpas_notify_interworking_ap_added(wpa_s, bss, cred, excluded,
+						  type, bh, bss_load,
+						  conn_capab);
 		if (excluded)
 			continue;
 		if (wpa_s->auto_select ||
@@ -2578,6 +2595,8 @@
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 	}
 
+	wpas_notify_interworking_select_done(wpa_s);
+
 	if (selected) {
 		wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR,
 			   MAC2STR(selected->bssid));
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 901b49b..d6b8a1a 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -140,6 +140,7 @@
 	conf->mesh_cc_id = 0;
 	conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
 	conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
+	conf->mesh_fwding = ssid->mesh_fwding;
 	conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
 	conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
 	conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
@@ -437,10 +438,42 @@
 	if (!conf)
 		goto out_free;
 
+	if (is_6ghz_freq(freq->freq)) {
+		/*
+		 * IEEE Std 802.11ax-2021, 12.12.2:
+		 * The STA shall use management frame protection (MFPR=1) when
+		 * using RSN.
+		 */
+		ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+
+		/* Set mandatory op_class parameter for setting up BSS */
+		switch (freq->bandwidth) {
+		case 20:
+			if (freq->freq == 5935)
+				conf->op_class = 136;
+			else
+				conf->op_class = 131;
+			break;
+		case 40:
+			conf->op_class = 132;
+			break;
+		case 80:
+			conf->op_class = 133;
+			break;
+		case 160:
+			conf->op_class = 134;
+			break;
+		default:
+			conf->op_class = 131;
+			break;
+		}
+	}
+
 	bss->conf = *conf->bss;
 	bss->conf->start_disabled = 1;
 	bss->conf->mesh = MESH_ENABLED;
 	bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
+	bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding;
 
 	if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
 			     wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
@@ -655,6 +688,10 @@
 	}
 	params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
 
+	/* Always explicitely set forwarding to on or off for now */
+	params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING;
+	params->conf.forwarding = ssid->mesh_fwding;
+
 	os_free(wpa_s->mesh_params);
 	wpa_s->mesh_params = params;
 	if (wpa_supplicant_mesh_init(wpa_s, ssid, &params->freq)) {
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index b6a5e88..2eb9a7e 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -251,6 +251,9 @@
 			   HE_MAX_MCS_CAPAB_SIZE +
 			   HE_MAX_PPET_CAPAB_SIZE;
 		buf_len += 3 + sizeof(struct ieee80211_he_operation);
+		if (is_6ghz_op_class(bss->iconf->op_class))
+			buf_len += sizeof(struct ieee80211_he_6ghz_oper_info) +
+				3 + sizeof(struct ieee80211_he_6ghz_band_cap);
 	}
 #endif /* CONFIG_IEEE80211AX */
 	if (type != PLINK_CLOSE)
@@ -303,9 +306,10 @@
 		info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1;
 		/* TODO: Add Connected to Mesh Gate/AS subfields */
 		wpabuf_put_u8(buf, info);
-		/* always forwarding & accepting plinks for now */
+		/* Set forwarding based on configuration and always accept
+		 * plinks for now */
 		wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER |
-			      MESH_CAP_FORWARDING);
+			      (conf->mesh_fwding ? MESH_CAP_FORWARDING : 0));
 	} else {	/* Peer closing frame */
 		/* IE: Mesh ID */
 		wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
@@ -375,11 +379,14 @@
 				HE_MAX_PHY_CAPAB_SIZE +
 				HE_MAX_MCS_CAPAB_SIZE +
 				HE_MAX_PPET_CAPAB_SIZE +
-				3 + sizeof(struct ieee80211_he_operation)];
+				3 + sizeof(struct ieee80211_he_operation) +
+				sizeof(struct ieee80211_he_6ghz_oper_info) +
+				3 + sizeof(struct ieee80211_he_6ghz_band_cap)];
 
 		pos = hostapd_eid_he_capab(bss, he_capa_oper,
 					   IEEE80211_MODE_MESH);
 		pos = hostapd_eid_he_operation(bss, pos);
+		pos = hostapd_eid_he_6ghz_band_cap(bss, pos);
 		wpabuf_put_data(buf, he_capa_oper, pos - he_capa_oper);
 	}
 #endif /* CONFIG_IEEE80211AX */
@@ -749,6 +756,7 @@
 #ifdef CONFIG_IEEE80211AX
 	copy_sta_he_capab(data, sta, IEEE80211_MODE_MESH,
 			  elems->he_capabilities, elems->he_capabilities_len);
+	copy_sta_he_6ghz_capab(data, sta, elems->he_6ghz_band_cap);
 #endif /* CONFIG_IEEE80211AX */
 
 	if (hostapd_get_aid(data, sta) < 0) {
@@ -770,6 +778,7 @@
 	params.vht_capabilities = sta->vht_capabilities;
 	params.he_capab = sta->he_capab;
 	params.he_capab_len = sta->he_capab_len;
+	params.he_6ghz_capab = sta->he_6ghz_capab;
 	params.flags |= WPA_STA_WMM;
 	params.flags_mask |= WPA_STA_AUTHENTICATED;
 	if (conf->security == MESH_CONF_SEC_NONE) {
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 834c7a1..65daa77 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -344,7 +344,6 @@
 	}
 	return sae_prepare_commit(wpa_s->own_addr, sta->addr,
 				  (u8 *) password, os_strlen(password),
-				  ssid->sae_password_id,
 				  sta->sae);
 }
 
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 5508f16..c52e88f 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -18,12 +18,13 @@
 #include "rsn_supp/wpa.h"
 #include "fst/fst.h"
 #include "crypto/tls.h"
+#include "bss.h"
 #include "driver_i.h"
 #include "scan.h"
 #include "p2p_supplicant.h"
 #include "sme.h"
 #include "notify.h"
-#include "hidl.h"
+#include "aidl.h"
 
 int wpas_notify_supplicant_initialized(struct wpa_global *global)
 {
@@ -35,11 +36,11 @@
 	}
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
-#ifdef CONFIG_HIDL
-	global->hidl = wpas_hidl_init(global);
-	if (!global->hidl)
+#ifdef CONFIG_AIDL
+	global->aidl = wpas_aidl_init(global);
+	if (!global->aidl)
 		return -1;
-#endif /* CONFIG_HIDL */
+#endif /* CONFIG_AIDL */
 
 	return 0;
 }
@@ -52,10 +53,10 @@
 		wpas_dbus_deinit(global->dbus);
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
-#ifdef CONFIG_HIDL
-	if (global->hidl)
-		wpas_hidl_deinit(global->hidl);
-#endif /* CONFIG_HIDL */
+#ifdef CONFIG_AIDL
+	if (global->aidl)
+		wpas_aidl_deinit(global->aidl);
+#endif /* CONFIG_AIDL */
 }
 
 
@@ -67,7 +68,7 @@
 	}
 
 	/* HIDL interface wants to keep track of the P2P mgmt iface. */
-	if (wpas_hidl_register_interface(wpa_s))
+	if (wpas_aidl_register_interface(wpa_s))
 		return -1;
 
 	return 0;
@@ -82,7 +83,7 @@
 	}
 
 	/* HIDL interface wants to keep track of the P2P mgmt iface. */
-	wpas_hidl_unregister_interface(wpa_s);
+	wpas_aidl_unregister_interface(wpa_s);
 }
 
 
@@ -124,7 +125,7 @@
 				  wpa_s->current_ssid->ssid_len) : "");
 #endif /* ANDROID */
 
-	wpas_hidl_notify_state_changed(wpa_s);
+	wpas_aidl_notify_state_changed(wpa_s);
 }
 
 
@@ -135,7 +136,7 @@
 
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_DISCONNECT_REASON);
 
-	wpas_hidl_notify_disconnect_reason(wpa_s);
+	wpas_aidl_notify_disconnect_reason(wpa_s);
 }
 
 
@@ -157,14 +158,14 @@
 
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ASSOC_STATUS_CODE);
 
-	wpas_hidl_notify_assoc_reject(wpa_s, bssid, timed_out, assoc_resp_ie, assoc_resp_ie_len);
+	wpas_aidl_notify_assoc_reject(wpa_s, bssid, timed_out, assoc_resp_ie, assoc_resp_ie_len);
 }
 
 void wpas_notify_auth_timeout(struct wpa_supplicant *wpa_s) {
 	if (wpa_s->p2p_mgmt)
 		return;
 
-	wpas_hidl_notify_auth_timeout(wpa_s);
+	wpas_aidl_notify_auth_timeout(wpa_s);
 }
 
 void wpas_notify_roam_time(struct wpa_supplicant *wpa_s)
@@ -202,7 +203,7 @@
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSS_TM_STATUS);
 
 #ifdef CONFIG_WNM
-	wpas_hidl_notify_bss_tm_status(wpa_s);
+	wpas_aidl_notify_bss_tm_status(wpa_s);
 #endif
 }
 
@@ -232,7 +233,7 @@
 
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_CURRENT_BSS);
 
-	wpas_hidl_notify_bssid_changed(wpa_s);
+	wpas_aidl_notify_bssid_changed(wpa_s);
 }
 
 
@@ -275,7 +276,7 @@
 
 	wpas_dbus_signal_network_request(wpa_s, ssid, rtype, default_txt);
 
-	wpas_hidl_notify_network_request(wpa_s, ssid, rtype, default_txt);
+	wpas_aidl_notify_network_request(wpa_s, ssid, rtype, default_txt);
 }
 
 
@@ -341,7 +342,7 @@
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_fail(wpa_s, fail);
 
-	wpas_hidl_notify_wps_event_fail(wpa_s, fail->peer_macaddr,
+	wpas_aidl_notify_wps_event_fail(wpa_s, fail->peer_macaddr,
 					fail->config_error,
 					fail->error_indication);
 #endif /* CONFIG_WPS */
@@ -356,7 +357,7 @@
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_success(wpa_s);
 
-	wpas_hidl_notify_wps_event_success(wpa_s);
+	wpas_aidl_notify_wps_event_success(wpa_s);
 #endif /* CONFIG_WPS */
 }
 
@@ -368,7 +369,7 @@
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_pbc_overlap(wpa_s);
 
-	wpas_hidl_notify_wps_event_pbc_overlap(wpa_s);
+	wpas_aidl_notify_wps_event_pbc_overlap(wpa_s);
 #endif /* CONFIG_WPS */
 }
 
@@ -387,7 +388,9 @@
 	 */
 	if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s) {
 		wpas_dbus_register_network(wpa_s, ssid);
-		wpas_hidl_register_network(wpa_s, ssid);
+		wpas_aidl_register_network(wpa_s, ssid);
+		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_NETWORK_ADDED "%d",
+			     ssid->id);
 	}
 }
 
@@ -397,7 +400,7 @@
 {
 #ifdef CONFIG_P2P
 	wpas_dbus_register_persistent_group(wpa_s, ssid);
-	wpas_hidl_register_network(wpa_s, ssid);
+	wpas_aidl_register_network(wpa_s, ssid);
 #endif /* CONFIG_P2P */
 }
 
@@ -407,7 +410,7 @@
 {
 #ifdef CONFIG_P2P
 	wpas_dbus_unregister_persistent_group(wpa_s, ssid->id);
-	wpas_hidl_unregister_network(wpa_s, ssid);
+	wpas_aidl_unregister_network(wpa_s, ssid);
 #endif /* CONFIG_P2P */
 }
 
@@ -422,7 +425,9 @@
 	if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s &&
 	    !wpa_s->p2p_mgmt) {
 		wpas_dbus_unregister_network(wpa_s, ssid->id);
-		wpas_hidl_unregister_network(wpa_s, ssid);
+		wpas_aidl_unregister_network(wpa_s, ssid);
+		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_NETWORK_REMOVED "%d",
+			     ssid->id);
 	}
 	if (network_is_persistent_group(ssid))
 		wpas_notify_persistent_group_removed(wpa_s, ssid);
@@ -640,7 +645,7 @@
 	/* Notify P2P find has stopped */
 	wpas_dbus_signal_p2p_find_stopped(wpa_s);
 
-	wpas_hidl_notify_p2p_find_stopped(wpa_s);
+	wpas_aidl_notify_p2p_find_stopped(wpa_s);
 }
 
 
@@ -658,7 +663,7 @@
 	/* Notify a new peer has been detected*/
 	wpas_dbus_signal_peer_device_found(wpa_s, info->p2p_device_addr);
 
-	wpas_hidl_notify_p2p_device_found(wpa_s, addr, info,
+	wpas_aidl_notify_p2p_device_found(wpa_s, addr, info,
 					  peer_wfd_device_info,
 					  peer_wfd_device_info_len,
 					  peer_wfd_r2_device_info,
@@ -674,7 +679,7 @@
 	/* Create signal on interface object*/
 	wpas_dbus_signal_peer_device_lost(wpa_s, dev_addr);
 
-	wpas_hidl_notify_p2p_device_lost(wpa_s, dev_addr);
+	wpas_aidl_notify_p2p_device_lost(wpa_s, dev_addr);
 }
 
 
@@ -686,7 +691,7 @@
 
 	wpas_dbus_unregister_p2p_group(wpa_s, ssid);
 
-	wpas_hidl_notify_p2p_group_removed(wpa_s, ssid, role);
+	wpas_aidl_notify_p2p_group_removed(wpa_s, ssid, role);
 }
 
 
@@ -695,7 +700,7 @@
 {
 	wpas_dbus_signal_p2p_go_neg_req(wpa_s, src, dev_passwd_id, go_intent);
 
-	wpas_hidl_notify_p2p_go_neg_req(wpa_s, src, dev_passwd_id, go_intent);
+	wpas_aidl_notify_p2p_go_neg_req(wpa_s, src, dev_passwd_id, go_intent);
 }
 
 
@@ -704,7 +709,7 @@
 {
 	wpas_dbus_signal_p2p_go_neg_resp(wpa_s, res);
 
-	wpas_hidl_notify_p2p_go_neg_completed(wpa_s, res);
+	wpas_aidl_notify_p2p_go_neg_completed(wpa_s, res);
 }
 
 
@@ -713,7 +718,7 @@
 {
 	wpas_dbus_signal_p2p_invitation_result(wpa_s, status, bssid);
 
-	wpas_hidl_notify_p2p_invitation_result(wpa_s, status, bssid);
+	wpas_aidl_notify_p2p_invitation_result(wpa_s, status, bssid);
 }
 
 
@@ -734,7 +739,7 @@
 	wpas_dbus_signal_p2p_sd_response(wpa_s, sa, update_indic,
 					 tlvs, tlvs_len);
 
-	wpas_hidl_notify_p2p_sd_response(wpa_s, sa, update_indic,
+	wpas_aidl_notify_p2p_sd_response(wpa_s, sa, update_indic,
 					 tlvs, tlvs_len);
 }
 
@@ -762,7 +767,7 @@
 						 status, config_methods,
 						 generated_pin);
 
-	wpas_hidl_notify_p2p_provision_discovery(wpa_s, dev_addr, request,
+	wpas_aidl_notify_p2p_provision_discovery(wpa_s, dev_addr, request,
 						 status, config_methods,
 						 generated_pin);
 
@@ -778,7 +783,7 @@
 
 	wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent, ip);
 
-	wpas_hidl_notify_p2p_group_started(wpa_s, ssid, persistent, client);
+	wpas_aidl_notify_p2p_group_started(wpa_s, ssid, persistent, client);
 }
 
 
@@ -788,7 +793,7 @@
 	/* Notify a group formation failed */
 	wpas_dbus_signal_p2p_group_formation_failure(wpa_s, reason);
 
-	wpas_hidl_notify_p2p_group_formation_failure(wpa_s, reason);
+	wpas_aidl_notify_p2p_group_formation_failure(wpa_s, reason);
 }
 
 
@@ -807,7 +812,7 @@
 	wpas_dbus_signal_p2p_invitation_received(wpa_s, sa, go_dev_addr, bssid,
 						 id, op_freq);
 
-	wpas_hidl_notify_p2p_invitation_received(wpa_s, sa, go_dev_addr, bssid,
+	wpas_aidl_notify_p2p_invitation_received(wpa_s, sa, go_dev_addr, bssid,
 						 id, op_freq);
 }
 
@@ -835,7 +840,7 @@
 	/* Notify listeners a new station has been authorized */
 	wpas_dbus_signal_sta_authorized(wpa_s, sta);
 
-	wpas_hidl_notify_ap_sta_authorized(wpa_s, sta, p2p_dev_addr);
+	wpas_aidl_notify_ap_sta_authorized(wpa_s, sta, p2p_dev_addr);
 }
 
 
@@ -855,7 +860,7 @@
 	/* Notify listeners a station has been deauthorized */
 	wpas_dbus_signal_sta_deauthorized(wpa_s, sta);
 
-        wpas_hidl_notify_ap_sta_deauthorized(wpa_s, sta, p2p_dev_addr);
+        wpas_aidl_notify_ap_sta_deauthorized(wpa_s, sta, p2p_dev_addr);
 	/* Unregister the station */
 	wpas_dbus_unregister_sta(wpa_s, sta);
 }
@@ -904,6 +909,10 @@
 		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_ALT
 			"depth=%d %s", cert->depth, cert->altsubject[i]);
 
+	wpas_aidl_notify_ceritification(wpa_s, cert->depth, cert->subject,
+				       cert->altsubject, cert->num_altsubject,
+				       cert_hash, cert->cert);
+
 	/* notify the new DBus API */
 	wpas_dbus_signal_certification(wpa_s, cert->depth, cert->subject,
 				       cert->altsubject, cert->num_altsubject,
@@ -935,7 +944,7 @@
 {
 	wpa_dbg(wpa_s, MSG_ERROR,
 		"EAP Error code = %d", error_code);
-	wpas_hidl_notify_eap_error(wpa_s, error_code);
+	wpas_aidl_notify_eap_error(wpa_s, error_code);
 }
 
 
@@ -982,7 +991,7 @@
 	if (!wpa_s || !bssid || !anqp)
 		return;
 
-	wpas_hidl_notify_anqp_query_done(wpa_s, bssid, result, anqp);
+	wpas_aidl_notify_anqp_query_done(wpa_s, bssid, result, anqp);
 #endif /* CONFIG_INTERWORKING */
 }
 
@@ -994,7 +1003,7 @@
 	if (!wpa_s || !bssid || !file_name || !image)
 		return;
 
-	wpas_hidl_notify_hs20_icon_query_done(wpa_s, bssid, file_name, image,
+	wpas_aidl_notify_hs20_icon_query_done(wpa_s, bssid, file_name, image,
 					      image_length);
 #endif /* CONFIG_HS20 */
 }
@@ -1007,7 +1016,7 @@
 	if (!wpa_s || !url)
 		return;
 
-	wpas_hidl_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
+	wpas_aidl_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
 #endif /* CONFIG_HS20 */
 }
 
@@ -1019,7 +1028,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay,
+	wpas_aidl_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay,
 			url);
 #endif /* CONFIG_HS20 */
 }
@@ -1030,7 +1039,7 @@
 	if (!wpa_s || !url)
 		return;
 
-	wpas_hidl_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
+	wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(wpa_s, url);
 #endif /* CONFIG_HS20 */
 }
 
@@ -1092,7 +1101,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_config_received(wpa_s, ssid);
+	wpas_aidl_notify_dpp_config_received(wpa_s, ssid);
 #endif /* CONFIG_DPP */
 }
 
@@ -1102,7 +1111,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_config_sent(wpa_s);
+	wpas_aidl_notify_dpp_config_sent(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1113,7 +1122,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_auth_success(wpa_s);
+	wpas_aidl_notify_dpp_auth_success(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1123,7 +1132,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_resp_pending(wpa_s);
+	wpas_aidl_notify_dpp_resp_pending(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1134,7 +1143,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_not_compatible(wpa_s);
+	wpas_aidl_notify_dpp_not_compatible(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1144,7 +1153,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_missing_auth(wpa_s);
+	wpas_aidl_notify_dpp_missing_auth(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1154,7 +1163,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_configuration_failure(wpa_s);
+	wpas_aidl_notify_dpp_configuration_failure(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1164,7 +1173,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_timeout(wpa_s);
+	wpas_aidl_notify_dpp_timeout(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1174,7 +1183,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_auth_failure(wpa_s);
+	wpas_aidl_notify_dpp_auth_failure(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
@@ -1184,21 +1193,21 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_dpp_fail(wpa_s);
+	wpas_aidl_notify_dpp_fail(wpa_s);
 #endif /* CONFIG_DPP */
 }
 
 void wpas_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP2
-	wpas_hidl_notify_dpp_config_sent_wait_response(wpa_s);
+	wpas_aidl_notify_dpp_config_sent_wait_response(wpa_s);
 #endif /* CONFIG_DPP2 */
 }
 
 void wpas_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP2
-	wpas_hidl_notify_dpp_config_accepted(wpa_s);
+	wpas_aidl_notify_dpp_config_accepted(wpa_s);
 #endif /* CONFIG_DPP2 */
 }
 
@@ -1207,14 +1216,14 @@
 		const char *channel_list, unsigned short band_list[], int size)
 {
 #ifdef CONFIG_DPP2
-	wpas_hidl_notify_dpp_conn_status(wpa_s, status, ssid, channel_list, band_list, size);
+	wpas_aidl_notify_dpp_conn_status(wpa_s, status, ssid, channel_list, band_list, size);
 #endif /* CONFIG_DPP2 */
 }
 
 void wpas_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_DPP2
-	wpas_hidl_notify_dpp_config_rejected(wpa_s);
+	wpas_aidl_notify_dpp_config_rejected(wpa_s);
 #endif /* CONFIG_DPP2 */
 }
 
@@ -1224,7 +1233,7 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_pmk_cache_added(wpa_s, entry);
+	wpas_aidl_notify_pmk_cache_added(wpa_s, entry);
 }
 
 void wpas_notify_transition_disable(struct wpa_supplicant *wpa_s,
@@ -1237,7 +1246,7 @@
 	if (!ssid)
 		return;
 
-	wpas_hidl_notify_transition_disable(wpa_s, ssid, bitmap);
+	wpas_aidl_notify_transition_disable(wpa_s, ssid, bitmap);
 }
 
 void wpas_notify_network_not_found(struct wpa_supplicant *wpa_s)
@@ -1245,5 +1254,76 @@
 	if (!wpa_s)
 		return;
 
-	wpas_hidl_notify_network_not_found(wpa_s);
+	wpas_aidl_notify_network_not_found(wpa_s);
+}
+
+#ifdef CONFIG_INTERWORKING
+
+void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s,
+				       struct wpa_bss *bss,
+				       struct wpa_cred *cred, int excluded,
+				       const char *type, int bh, int bss_load,
+				       int conn_capab)
+{
+	wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d",
+		excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP,
+		MAC2STR(bss->bssid), type,
+		bh ? " below_min_backhaul=1" : "",
+		bss_load ? " over_max_bss_load=1" : "",
+		conn_capab ? " conn_capab_missing=1" : "",
+		cred->id, cred->priority, cred->sp_priority);
+
+	wpas_dbus_signal_interworking_ap_added(wpa_s, bss, cred, type, excluded,
+					       bh, bss_load, conn_capab);
+}
+
+
+void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s)
+{
+	wpas_dbus_signal_interworking_select_done(wpa_s);
+}
+
+#endif /* CONFIG_INTERWORKING */
+
+void wpas_notify_eap_method_selected(struct wpa_supplicant *wpa_s,
+			const char* reason_string)
+{
+	wpas_aidl_notify_eap_method_selected(wpa_s, reason_string);
+}
+
+void wpas_notify_ssid_temp_disabled(struct wpa_supplicant *wpa_s,
+			const char *reason_string)
+{
+	wpas_aidl_notify_ssid_temp_disabled(wpa_s, reason_string);
+}
+
+void wpas_notify_open_ssl_failure(struct wpa_supplicant *wpa_s,
+			const char *reason_string)
+{
+	wpas_aidl_notify_open_ssl_failure(wpa_s, reason_string);
+}
+
+void wpas_notify_qos_policy_reset(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpas_aidl_notify_qos_policy_reset(wpa_s);
+}
+
+void wpas_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
+	struct dscp_policy_data *policies, int num_policies)
+{
+	if (!wpa_s || !policies)
+		return;
+
+	wpas_aidl_notify_qos_policy_request(wpa_s, policies, num_policies);
+}
+
+void wpas_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency)
+{
+	if (!wpa_s)
+		return;
+
+	wpas_aidl_notify_frequency_changed(wpa_s, frequency);
 }
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 706573c..996be84 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -18,6 +18,7 @@
 struct wps_event_m2d;
 struct wps_event_fail;
 struct tls_cert_data;
+struct wpa_cred;
 
 int wpas_notify_supplicant_initialized(struct wpa_global *global);
 void wpas_notify_supplicant_deinitialized(struct wpa_global *global);
@@ -201,5 +202,21 @@
 				    struct wpa_ssid *ssid,
 				    u8 bitmap);
 void wpas_notify_network_not_found(struct wpa_supplicant *wpa_s);
+void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s,
+				       struct wpa_bss *bss,
+				       struct wpa_cred *cred, int excluded,
+				       const char *type, int bh, int bss_load,
+				       int conn_capab);
+void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s);
+void wpas_notify_eap_method_selected(struct wpa_supplicant *wpa_s,
+		const char* reason_string);
+void wpas_notify_ssid_temp_disabled(struct wpa_supplicant *wpa_s,
+		const char *reason_string);
+void wpas_notify_open_ssl_failure(struct wpa_supplicant *wpa_s,
+		const char *reason_string);
+void wpas_notify_qos_policy_reset(struct wpa_supplicant *wpa_s);
+void wpas_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
+		struct dscp_policy_data *policies, int num_policies);
+void wpas_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency);
 
 #endif /* NOTIFY_H */
diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c
index a0ad0c2..bd53c5c 100644
--- a/wpa_supplicant/op_classes.c
+++ b/wpa_supplicant/op_classes.c
@@ -207,11 +207,15 @@
 		if (!(flag & HOSTAPD_CHAN_HT40MINUS))
 			return NOT_ALLOWED;
 		res2 = allow_channel(mode, op_class, channel - 4, NULL);
-	} else if (bw == BW40PLUS ||
-		   (bw == BW40 && !(((channel - 1) / 4) % 2))) {
+	} else if (bw == BW40PLUS) {
 		if (!(flag & HOSTAPD_CHAN_HT40PLUS))
 			return NOT_ALLOWED;
 		res2 = allow_channel(mode, op_class, channel + 4, NULL);
+	} else if (is_6ghz_op_class(op_class) && bw == BW40) {
+		if (get_6ghz_sec_channel(channel) < 0)
+			res2 = allow_channel(mode, op_class, channel - 4, NULL);
+		else
+			res2 = allow_channel(mode, op_class, channel + 4, NULL);
 	} else if (bw == BW80) {
 		/*
 		 * channel is a center channel and as such, not necessarily a
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 643dd0d..f1d033b 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -167,6 +167,17 @@
 static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx);
 
 
+static int wpas_get_6ghz_he_chwidth_capab(struct hostapd_hw_modes *mode)
+{
+	int he_capab = 0;
+
+	if (mode)
+		he_capab = mode->he_capab[WPAS_MODE_INFRA].phy_cap[
+			HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
+	return he_capab;
+}
+
+
 /*
  * Get the number of concurrent channels that the HW can operate, but that are
  * currently not in use by any of the wpa_supplicant interfaces.
@@ -350,9 +361,9 @@
 		params->only_new_results = 1;
 	}
 
-	if (wpa_s->conf->p2p_6ghz_disable && !params->freqs) {
+	if (!params->p2p_include_6ghz && !params->freqs) {
 		wpa_printf(MSG_DEBUG,
-			   "P2P: 6 GHz disabled - update the scan frequency list");
+			   "P2P: Exclude 6 GHz channels - update the scan frequency list");
 		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
 					0);
 		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
@@ -397,7 +408,8 @@
 
 static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
 			 unsigned int num_req_dev_types,
-			 const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
+			 const u8 *req_dev_types, const u8 *dev_id, u16 pw_id,
+			 bool include_6ghz)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	struct wpa_driver_scan_params *params = NULL;
@@ -435,7 +447,8 @@
 					num_req_dev_types, req_dev_types);
 	if (wps_ie == NULL)
 		goto fail;
-
+	if (!wpa_s->conf->p2p_6ghz_disable)
+		params->p2p_include_6ghz = include_6ghz;
 	switch (type) {
 	case P2P_SCAN_SOCIAL:
 		params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1,
@@ -1028,6 +1041,7 @@
 	wpa_s->p2p_group_common_freqs = NULL;
 	wpa_s->p2p_group_common_freqs_num = 0;
 	wpa_s->p2p_go_do_acs = 0;
+	wpa_s->p2p_go_allow_dfs = 0;
 
 	wpa_s->waiting_presence_resp = 0;
 
@@ -2068,6 +2082,16 @@
 	}
 	ssid->auth_alg = WPA_AUTH_ALG_OPEN;
 	ssid->key_mgmt = WPA_KEY_MGMT_PSK;
+	if (is_6ghz_freq(ssid->frequency) &&
+	    is_p2p_6ghz_capable(wpa_s->global->p2p)) {
+		ssid->auth_alg |= WPA_AUTH_ALG_SAE;
+		ssid->key_mgmt = WPA_KEY_MGMT_SAE;
+		ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+		ssid->sae_pwe = 1;
+		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use SAE auth_alg and key_mgmt");
+	} else {
+		p2p_set_6ghz_dev_capab(wpa_s->global->p2p, false);
+	}
 	ssid->proto = WPA_PROTO_RSN;
 	ssid->pairwise_cipher = WPA_CIPHER_CCMP;
 	ssid->group_cipher = WPA_CIPHER_CCMP;
@@ -2152,6 +2176,8 @@
 	d->disassoc_low_ack = s->disassoc_low_ack;
 	d->disable_scan_offload = s->disable_scan_offload;
 	d->passive_scan = s->passive_scan;
+	d->pmf = s->pmf;
+	d->p2p_6ghz_disable = s->p2p_6ghz_disable;
 
 	if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey &&
 	    !d->wps_nfc_pw_from_config) {
@@ -3265,7 +3291,7 @@
 				wpa_s->conf->p2p_go_he,
 				wpa_s->conf->p2p_go_edmg, NULL,
 				go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
-				1);
+				1, is_p2p_allow_6ghz(wpa_s->global->p2p));
 		} else if (bssid) {
 			wpa_s->user_initiated_pd = 0;
 			wpa_msg_global(wpa_s, MSG_INFO,
@@ -3494,7 +3520,8 @@
 				      channels,
 				      ssid->mode == WPAS_MODE_P2P_GO ?
 				      P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
-				      0, 1);
+				      0, 1,
+				      is_p2p_allow_6ghz(wpa_s->global->p2p));
 }
 
 
@@ -3576,27 +3603,27 @@
 }
 
 
-static int has_channel(struct wpa_global *global,
-		       struct hostapd_hw_modes *mode, u8 chan, int *flags)
+static enum chan_allowed has_channel(struct wpa_global *global,
+				     struct hostapd_hw_modes *mode, u8 op_class,
+				     u8 chan, int *flags)
 {
 	int i;
 	unsigned int freq;
 
-	freq = (mode->mode == HOSTAPD_MODE_IEEE80211A ? 5000 : 2407) +
-		chan * 5;
+	freq = ieee80211_chan_to_freq(NULL, op_class, chan);
 	if (wpas_p2p_disallowed_freq(global, freq))
 		return NOT_ALLOWED;
 
 	for (i = 0; i < mode->num_channels; i++) {
-		if (mode->channels[i].chan == chan) {
+		if ((unsigned int) mode->channels[i].freq == freq) {
 			if (flags)
 				*flags = mode->channels[i].flag;
-			if (mode->channels[i].flag &
-			    (HOSTAPD_CHAN_DISABLED |
-			     HOSTAPD_CHAN_RADAR))
+			if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
 				return NOT_ALLOWED;
 			if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR)
 				return NO_IR;
+			if (mode->channels[i].flag & HOSTAPD_CHAN_RADAR)
+				return RADAR;
 			return ALLOWED;
 		}
 	}
@@ -3607,15 +3634,15 @@
 
 static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
 				     struct hostapd_hw_modes *mode,
-				     u8 channel)
+				     u8 channel, const u8 *center_channels,
+				     size_t num_chan)
 {
-	u8 center_channels[] = { 42, 58, 106, 122, 138, 155, 171 };
 	size_t i;
 
 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
 		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(center_channels); i++)
+	for (i = 0; i < num_chan; i++)
 		/*
 		 * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
 		 * so the center channel is 6 channels away from the start/end.
@@ -3628,38 +3655,64 @@
 }
 
 
+static const u8 center_channels_5ghz_80mhz[] = { 42, 58, 106, 122, 138,
+						 155, 171 };
+static const u8 center_channels_6ghz_80mhz[] = { 7, 23, 39, 55, 71, 87, 103,
+						 119, 135, 151, 167, 183, 199,
+						 215 };
+
 static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
 					       struct hostapd_hw_modes *mode,
-					       u8 channel, u8 bw)
+					       u8 op_class, u8 channel, u8 bw)
 {
 	u8 center_chan;
 	int i, flags;
 	enum chan_allowed res, ret = ALLOWED;
+	const u8 *chans;
+	size_t num_chans;
+	bool is_6ghz = is_6ghz_op_class(op_class);
 
-	center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
+	if (is_6ghz) {
+		chans = center_channels_6ghz_80mhz;
+		num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
+	} else {
+		chans = center_channels_5ghz_80mhz;
+		num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
+	}
+	center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
+						chans, num_chans);
 	if (!center_chan)
 		return NOT_ALLOWED;
-	if (center_chan >= 58 && center_chan <= 138)
+	if (!wpa_s->p2p_go_allow_dfs &&
+	    !is_6ghz && center_chan >= 58 && center_chan <= 138)
 		return NOT_ALLOWED; /* Do not allow DFS channels for P2P */
 
 	/* check all the channels are available */
 	for (i = 0; i < 4; i++) {
 		int adj_chan = center_chan - 6 + i * 4;
 
-		res = has_channel(wpa_s->global, mode, adj_chan, &flags);
+		res = has_channel(wpa_s->global, mode, op_class, adj_chan,
+				  &flags);
 		if (res == NOT_ALLOWED)
 			return NOT_ALLOWED;
+		if (res == RADAR)
+			ret = RADAR;
 		if (res == NO_IR)
 			ret = NO_IR;
-
-		if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
+		if (!is_6ghz) {
+			if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
+				return NOT_ALLOWED;
+			if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
+				return NOT_ALLOWED;
+			if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30))
+				return NOT_ALLOWED;
+			if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
+				return NOT_ALLOWED;
+		} else if (is_6ghz &&
+			   (!(wpas_get_6ghz_he_chwidth_capab(mode) &
+			      HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))) {
 			return NOT_ALLOWED;
-		if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
-			return NOT_ALLOWED;
-		if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30))
-			return NOT_ALLOWED;
-		if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
-			return NOT_ALLOWED;
+		}
 	}
 
 	return ret;
@@ -3668,15 +3721,15 @@
 
 static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
 				     struct hostapd_hw_modes *mode,
-				     u8 channel)
+				     u8 channel, const u8 *center_channels,
+				     size_t num_chan)
 {
-	u8 center_channels[] = { 50, 114, 163 };
 	unsigned int i;
 
 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
 		return 0;
 
-	for (i = 0; i < ARRAY_SIZE(center_channels); i++)
+	for (i = 0; i < num_chan; i++)
 		/*
 		 * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
 		 * so the center channel is 14 channels away from the start/end.
@@ -3689,15 +3742,29 @@
 }
 
 
+static const u8 center_channels_5ghz_160mhz[] = { 50, 114, 163 };
+static const u8 center_channels_6ghz_160mhz[] = { 15, 47, 79, 111, 143, 175,
+						  207 };
+
 static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
 					       struct hostapd_hw_modes *mode,
-					       u8 channel, u8 bw)
+					       u8 op_class, u8 channel, u8 bw)
 {
 	u8 center_chan;
 	int i, flags;
 	enum chan_allowed res, ret = ALLOWED;
+	const u8 *chans;
+	size_t num_chans;
 
-	center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+	if (is_6ghz_op_class(op_class)) {
+		chans = center_channels_6ghz_160mhz;
+		num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
+	} else {
+		chans = center_channels_5ghz_160mhz;
+		num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
+	}
+	center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
+						 chans, num_chans);
 	if (!center_chan)
 		return NOT_ALLOWED;
 	/* VHT 160 MHz uses DFS channels in most countries. */
@@ -3706,29 +3773,38 @@
 	for (i = 0; i < 8; i++) {
 		int adj_chan = center_chan - 14 + i * 4;
 
-		res = has_channel(wpa_s->global, mode, adj_chan, &flags);
+		res = has_channel(wpa_s->global, mode, op_class, adj_chan,
+				  &flags);
 		if (res == NOT_ALLOWED)
 			return NOT_ALLOWED;
 
+		if (res == RADAR)
+			ret = RADAR;
 		if (res == NO_IR)
 			ret = NO_IR;
 
-		if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
+		if (!is_6ghz_op_class(op_class)) {
+			if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
+				return NOT_ALLOWED;
+			if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
+				return NOT_ALLOWED;
+			if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110))
+				return NOT_ALLOWED;
+			if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90))
+				return NOT_ALLOWED;
+			if (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70))
+				return NOT_ALLOWED;
+			if (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50))
+				return NOT_ALLOWED;
+			if (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30))
+				return NOT_ALLOWED;
+			if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
+				return NOT_ALLOWED;
+		} else if (is_6ghz_op_class(op_class) &&
+			   (!(wpas_get_6ghz_he_chwidth_capab(mode) &
+			      HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G))) {
 			return NOT_ALLOWED;
-		if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
-			return NOT_ALLOWED;
-		if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110))
-			return NOT_ALLOWED;
-		if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90))
-			return NOT_ALLOWED;
-		if (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70))
-			return NOT_ALLOWED;
-		if (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50))
-			return NOT_ALLOWED;
-		if (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30))
-			return NOT_ALLOWED;
-		if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
-			return NOT_ALLOWED;
+		}
 	}
 
 	return ret;
@@ -3751,24 +3827,37 @@
 
 static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
 						 struct hostapd_hw_modes *mode,
-						 u8 channel, u8 bw)
+						 u8 op_class, u8 channel, u8 bw)
 {
 	int flag = 0;
 	enum chan_allowed res, res2;
 
-	res2 = res = has_channel(wpa_s->global, mode, channel, &flag);
+	res2 = res = has_channel(wpa_s->global, mode, op_class, channel, &flag);
 	if (bw == BW40MINUS) {
 		if (!(flag & HOSTAPD_CHAN_HT40MINUS))
 			return NOT_ALLOWED;
-		res2 = has_channel(wpa_s->global, mode, channel - 4, NULL);
+		res2 = has_channel(wpa_s->global, mode, op_class, channel - 4,
+				   NULL);
 	} else if (bw == BW40PLUS) {
 		if (!(flag & HOSTAPD_CHAN_HT40PLUS))
 			return NOT_ALLOWED;
-		res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
+		res2 = has_channel(wpa_s->global, mode, op_class, channel + 4,
+				   NULL);
+	} else if (is_6ghz_op_class(op_class) && bw == BW40) {
+		if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+			return NOT_ALLOWED;
+		if (get_6ghz_sec_channel(channel) < 0)
+			res2 = has_channel(wpa_s->global, mode, op_class,
+					   channel - 4, NULL);
+		else
+			res2 = has_channel(wpa_s->global, mode, op_class,
+					   channel + 4, NULL);
 	} else if (bw == BW80) {
-		res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
+		res2 = wpas_p2p_verify_80mhz(wpa_s, mode, op_class, channel,
+					     bw);
 	} else if (bw == BW160) {
-		res2 = wpas_p2p_verify_160mhz(wpa_s, mode, channel, bw);
+		res2 = wpas_p2p_verify_160mhz(wpa_s, mode, op_class, channel,
+					      bw);
 	} else if (bw == BW4320 || bw == BW6480 || bw == BW8640) {
 		return wpas_p2p_verify_edmg(wpa_s, mode, channel);
 	}
@@ -3777,6 +3866,8 @@
 		return NOT_ALLOWED;
 	if (res == NO_IR || res2 == NO_IR)
 		return NO_IR;
+	if (res == RADAR || res2 == RADAR)
+		return RADAR;
 	return res;
 }
 
@@ -3800,7 +3891,7 @@
 
 	for (op = 0; global_op_class[op].op_class; op++) {
 		const struct oper_class_map *o = &global_op_class[op];
-		u8 ch;
+		unsigned int ch;
 		struct p2p_reg_class *reg = NULL, *cli_reg = NULL;
 
 		if (o->p2p == NO_P2P_SUPP ||
@@ -3822,7 +3913,8 @@
 			    ch < 149 && ch + o->inc > 149)
 				ch = 149;
 
-			res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
+			res = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
+						      ch, o->bw);
 			if (res == ALLOWED) {
 				if (reg == NULL) {
 					if (cla == P2P_MAX_REG_CLASSES)
@@ -3872,29 +3964,50 @@
 }
 
 
-int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
-			   struct hostapd_hw_modes *mode, u8 channel)
+int wpas_p2p_get_sec_channel_offset_40mhz(struct wpa_supplicant *wpa_s,
+					  struct hostapd_hw_modes *mode,
+					  u8 channel)
 {
 	int op;
 	enum chan_allowed ret;
 
 	for (op = 0; global_op_class[op].op_class; op++) {
 		const struct oper_class_map *o = &global_op_class[op];
-		u8 ch;
+		u16 ch;
+		int chan = channel;
 
-		if (o->p2p == NO_P2P_SUPP ||
+		/* Allow DFS channels marked as NO_P2P_SUPP to be used with
+		 * driver offloaded DFS. */
+		if ((o->p2p == NO_P2P_SUPP &&
+		     (!is_dfs_global_op_class(o->op_class) ||
+		      !wpa_s->p2p_go_allow_dfs)) ||
 		    (is_6ghz_op_class(o->op_class) &&
 		     wpa_s->conf->p2p_6ghz_disable))
 			continue;
 
+		if (is_6ghz_op_class(o->op_class) && o->bw == BW40 &&
+		    get_6ghz_sec_channel(channel) < 0)
+			chan = channel - 4;
+
 		for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
 			if (o->mode != HOSTAPD_MODE_IEEE80211A ||
-			    (o->bw != BW40PLUS && o->bw != BW40MINUS) ||
-			    ch != channel)
+			    (o->bw != BW40PLUS && o->bw != BW40MINUS &&
+			     o->bw != BW40) ||
+			    ch != chan)
 				continue;
-			ret = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
-			if (ret == ALLOWED)
+			ret = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
+						      ch, o->bw);
+			if (ret == ALLOWED) {
+				if (is_6ghz_op_class(o->op_class) &&
+				    o->bw == BW40)
+					return get_6ghz_sec_channel(channel);
 				return (o->bw == BW40MINUS) ? -1 : 1;
+			}
+			if (ret == RADAR && wpa_s->p2p_go_allow_dfs) {
+				/* Allow RADAR channels used for driver
+				 * offloaded DFS */
+				return (o->bw == BW40MINUS) ? -1 : 1;
+			}
 		}
 	}
 	return 0;
@@ -3902,21 +4015,49 @@
 
 
 int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
-			      struct hostapd_hw_modes *mode, u8 channel)
+			      struct hostapd_hw_modes *mode, u8 channel,
+			      u8 op_class)
 {
-	if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW80))
+	const u8 *chans;
+	size_t num_chans;
+	enum chan_allowed ret;
+
+	ret = wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW80);
+	if (!(ret == ALLOWED || (ret == RADAR && wpa_s->p2p_go_allow_dfs)))
 		return 0;
 
-	return wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
+	if (is_6ghz_op_class(op_class)) {
+		chans = center_channels_6ghz_80mhz;
+		num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
+	} else {
+		chans = center_channels_5ghz_80mhz;
+		num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
+	}
+	return wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
+					 chans, num_chans);
 }
 
 
 int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
-			       struct hostapd_hw_modes *mode, u8 channel)
+			       struct hostapd_hw_modes *mode, u8 channel,
+			       u8 op_class)
 {
-	if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW160))
+	const u8 *chans;
+	size_t num_chans;
+	enum chan_allowed ret;
+
+	ret = wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW160);
+	if (!(ret == ALLOWED || (ret == RADAR && wpa_s->p2p_go_allow_dfs)))
 		return 0;
-	return wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+	if (is_6ghz_op_class(op_class)) {
+		chans = center_channels_6ghz_160mhz;
+		num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
+	} else {
+		chans = center_channels_5ghz_160mhz;
+		num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
+	}
+	return wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
+					  chans, num_chans);
 }
 
 
@@ -4456,10 +4597,10 @@
 					persistent_go->mode ==
 					WPAS_MODE_P2P_GO ?
 					P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
-					0, 0);
+					0, 0, false);
 			} else if (response_done) {
 				wpas_p2p_group_add(wpa_s, 1, freq,
-						   0, 0, 0, 0, 0, 0);
+						   0, 0, 0, 0, 0, 0, false);
 			}
 
 			if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4578,9 +4719,11 @@
 			wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 			NULL,
 			persistent_go->mode == WPAS_MODE_P2P_GO ?
-			P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
+			P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0,
+			is_p2p_allow_6ghz(wpa_s->global->p2p));
 	} else {
-		wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0);
+		wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
+				   is_p2p_allow_6ghz(wpa_s->global->p2p));
 	}
 
 	return 1;
@@ -5186,7 +5329,8 @@
 					 wpa_s->p2p_go_max_oper_chwidth,
 					 wpa_s->p2p_go_he,
 					 wpa_s->p2p_go_edmg,
-					 NULL, 0);
+					 NULL, 0,
+					 is_p2p_allow_6ghz(wpa_s->global->p2p));
 			return;
 		}
 
@@ -5384,7 +5528,8 @@
 	if (freq > 0) {
 		freqs[0] = freq;
 		params.freqs = freqs;
-	} else if (wpa_s->conf->p2p_6ghz_disable) {
+	} else if (wpa_s->conf->p2p_6ghz_disable ||
+		   !is_p2p_allow_6ghz(wpa_s->global->p2p)) {
 		wpa_printf(MSG_DEBUG,
 			   "P2P: 6 GHz disabled - update the scan frequency list");
 		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, &params,
@@ -5421,7 +5566,7 @@
 	 * the new scan results become available.
 	 */
 	ret = wpa_drv_scan(wpa_s, &params);
-	if (wpa_s->conf->p2p_6ghz_disable && params.freqs != freqs)
+	if (params.freqs != freqs)
 		os_free(params.freqs);
 	if (!ret) {
 		os_get_reltime(&wpa_s->scan_trigger_time);
@@ -5658,7 +5803,7 @@
 				}
 				i++;
 			}
-		} else {
+		} else if (!wpa_s->conf->num_p2p_pref_chan) {
 			enum wpa_driver_if_type iface_type;
 
 			if (go)
@@ -5733,6 +5878,40 @@
 }
 
 
+static bool is_p2p_6ghz_supported(struct wpa_supplicant *wpa_s,
+				  const u8 *peer_addr)
+{
+	if (wpa_s->conf->p2p_6ghz_disable ||
+	    !get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+		      HOSTAPD_MODE_IEEE80211A, true))
+		return false;
+
+	if (!p2p_wfd_enabled(wpa_s->global->p2p))
+		return false;
+	if (peer_addr && !p2p_peer_wfd_enabled(wpa_s->global->p2p, peer_addr))
+		return false;
+
+	return true;
+}
+
+
+static int wpas_p2p_check_6ghz(struct wpa_supplicant *wpa_s,
+			       const u8 *peer_addr, bool allow_6ghz, int freq)
+{
+	if (allow_6ghz && is_p2p_6ghz_supported(wpa_s, peer_addr)) {
+		wpa_printf(MSG_DEBUG,
+			   "P2P: Allow connection on 6 GHz channels");
+		p2p_set_6ghz_dev_capab(wpa_s->global->p2p, true);
+	} else {
+		if (is_6ghz_freq(freq))
+			return -2;
+		p2p_set_6ghz_dev_capab(wpa_s->global->p2p, false);
+	}
+
+	return 0;
+}
+
+
 /**
  * wpas_p2p_connect - Request P2P Group Formation to be started
  * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
@@ -5757,6 +5936,7 @@
  *	(CHANWIDTH_*).
  * @group_ssid: Specific Group SSID for join or %NULL if not set
  * @group_ssid_len: Length of @group_ssid in octets
+ * @allow_6ghz: Allow P2P connection on 6 GHz channels
  * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
  *	failure, -2 on failure due to channel not currently available,
  *	-3 if forced channel is not supported
@@ -5767,7 +5947,8 @@
 		     int go_intent, int freq, unsigned int vht_center_freq2,
 		     int persistent_id, int pd, int ht40, int vht,
 		     unsigned int vht_chwidth, int he, int edmg,
-		     const u8 *group_ssid, size_t group_ssid_len)
+		     const u8 *group_ssid, size_t group_ssid_len,
+		     bool allow_6ghz)
 {
 	int force_freq = 0, pref_freq = 0;
 	int ret = 0, res;
@@ -5786,7 +5967,7 @@
 			return -1;
 	}
 
-	if (is_6ghz_freq(freq) && wpa_s->conf->p2p_6ghz_disable)
+	if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
 		return -2;
 
 	os_free(wpa_s->global->add_psk);
@@ -6064,6 +6245,9 @@
 
 		res = wpa_drv_get_pref_freq_list(wpa_s, WPA_IF_P2P_GO,
 						 &size, pref_freq_list);
+		if (!is_p2p_allow_6ghz(wpa_s->global->p2p))
+			size = p2p_remove_6ghz_channels(pref_freq_list, size);
+
 		if (!res && size > 0) {
 			i = 0;
 			while (i < size &&
@@ -6103,7 +6287,25 @@
 		} else {
 			if (os_get_random((u8 *) &r, sizeof(r)) < 0)
 				return -1;
-			freq = 2412 + (r % 3) * 25;
+			int possible_2g_freqs[] = {
+				/* operating class 81 */
+				2412, 2437, 2462,
+			};
+			int possible_2g_freqs_num =
+			    sizeof(possible_2g_freqs)/sizeof(possible_2g_freqs[0]);
+			int i;
+			for (i = 0; i < possible_2g_freqs_num; i++, r++) {
+				freq = possible_2g_freqs[r % possible_2g_freqs_num];
+				if (p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
+					break;
+				}
+			}
+
+			if (i >= possible_2g_freqs_num) {
+				wpa_printf(MSG_DEBUG, "P2P: Could not select "
+					   "2.4 GHz channel for P2P group");
+				return -1;
+			}
 			wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
 				   "channel: %d MHz", freq);
 		}
@@ -6119,6 +6321,14 @@
 			wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
 				   "channel: %d MHz", freq);
 		} else {
+			const int freqs[] = {
+				/* operating class 115 */
+				5180, 5200, 5220, 5240,
+				/* operating class 124 */
+				5745, 5765, 5785, 5805,
+			};
+			unsigned int i, num_freqs = ARRAY_SIZE(freqs);
+
 			if (os_get_random((u8 *) &r, sizeof(r)) < 0)
 				return -1;
 
@@ -6135,7 +6345,6 @@
 			int possible_5g_freqs_num =
 			    sizeof(possible_5g_freqs)/sizeof(possible_5g_freqs[0]);
 
-			int i;
 			for (i = 0; i < possible_5g_freqs_num; i++, r++) {
 				if (p2p_supported_freq_go(
 				    wpa_s->global->p2p,
@@ -6199,34 +6408,26 @@
 	/* try all channels in operating class 115 */
 	for (i = 0; i < 4; i++) {
 		params->freq = 5180 + i * 20;
-		if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
-		    freq_included(wpa_s, channels, params->freq) &&
-		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+		if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
 			goto out;
 	}
 
 	/* try all channels in operating class 124 */
 	for (i = 0; i < 4; i++) {
 		params->freq = 5745 + i * 20;
-		if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
-		    freq_included(wpa_s, channels, params->freq) &&
-		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+		if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
 			goto out;
 	}
 
 	/* try social channel class 180 channel 2 */
 	params->freq = 58320 + 1 * 2160;
-	if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
-	    freq_included(wpa_s, channels, params->freq) &&
-	    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+	if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
 		goto out;
 
 	/* try all channels in reg. class 180 */
 	for (i = 0; i < 4; i++) {
 		params->freq = 58320 + i * 2160;
-		if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
-		    freq_included(wpa_s, channels, params->freq) &&
-		    p2p_supported_freq(wpa_s->global->p2p, params->freq))
+		if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
 			goto out;
 	}
 
@@ -6492,14 +6693,16 @@
 			enum hostapd_hw_mode mode;
 			struct hostapd_hw_modes *hwmode;
 			u8 chan;
+			u8 op_class;
 
 			cand = wpa_s->p2p_group_common_freqs[i];
+			op_class = is_6ghz_freq(cand) ? 133 : 128;
 			mode = ieee80211_freq_to_chan(cand, &chan);
 			hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
 					  mode, is_6ghz_freq(cand));
 			if (!hwmode ||
-			    wpas_p2p_verify_channel(wpa_s, hwmode, chan,
-						    BW80) != ALLOWED)
+			    wpas_p2p_verify_channel(wpa_s, hwmode, op_class,
+						    chan, BW80) != ALLOWED)
 				continue;
 			if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
 				params->freq = cand;
@@ -6518,20 +6721,44 @@
 		for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
 			enum hostapd_hw_mode mode;
 			struct hostapd_hw_modes *hwmode;
-			u8 chan;
+			u8 chan, op_class;
+			bool is_6ghz, supported = false;
 
+			is_6ghz = is_6ghz_freq(cand);
 			cand = wpa_s->p2p_group_common_freqs[i];
 			mode = ieee80211_freq_to_chan(cand, &chan);
 			hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
-					  mode, is_6ghz_freq(cand));
+					  mode, is_6ghz);
 			if (!wpas_same_band(wpa_s->current_ssid->frequency,
 					    cand) ||
-			    !hwmode ||
-			    (wpas_p2p_verify_channel(wpa_s, hwmode, chan,
-						     BW40MINUS) != ALLOWED &&
-			     wpas_p2p_verify_channel(wpa_s, hwmode, chan,
-						     BW40PLUS) != ALLOWED))
+			    !hwmode)
 				continue;
+			if (is_6ghz &&
+			    wpas_p2p_verify_channel(wpa_s, hwmode, 132, chan,
+						    BW40) == ALLOWED)
+				supported = true;
+
+			if (!is_6ghz &&
+			    ieee80211_freq_to_channel_ext(
+				    cand, -1, CHANWIDTH_USE_HT, &op_class,
+				    &chan) != NUM_HOSTAPD_MODES &&
+			    wpas_p2p_verify_channel(
+				    wpa_s, hwmode, op_class, chan,
+				    BW40MINUS) == ALLOWED)
+				supported = true;
+
+			if (!supported && !is_6ghz &&
+			    ieee80211_freq_to_channel_ext(
+				    cand, 1, CHANWIDTH_USE_HT, &op_class,
+				    &chan) != NUM_HOSTAPD_MODES &&
+			    wpas_p2p_verify_channel(
+				    wpa_s, hwmode, op_class, chan,
+				    BW40PLUS) == ALLOWED)
+				supported = true;
+
+			if (!supported)
+				continue;
+
 			if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
 				params->freq = cand;
 				wpa_printf(MSG_DEBUG,
@@ -6635,6 +6862,11 @@
 		wpa_s->p2p_go_do_acs = 0;
 	}
 
+	if (go && wpa_s->p2p_go_allow_dfs) {
+		group_wpa_s->p2p_go_allow_dfs = wpa_s->p2p_go_allow_dfs;
+		wpa_s->p2p_go_allow_dfs = 0;
+	}
+
 	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
 		group_wpa_s->ifname);
 	group_wpa_s->p2p_first_connection_timeout = 0;
@@ -6652,6 +6884,7 @@
  * @vht:  Start GO with VHT support
  * @vht_chwidth: channel bandwidth for GO operating with VHT support
  * @edmg: Start GO with EDMG support
+ * @allow_6ghz: Allow P2P group creation on a 6 GHz channel
  * Returns: 0 on success, -1 on failure
  *
  * This function creates a new P2P group with the local end as the Group Owner,
@@ -6659,12 +6892,15 @@
  */
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq, int vht_center_freq2, int ht40, int vht,
-		       int max_oper_chwidth, int he, int edmg)
+		       int max_oper_chwidth, int he, int edmg,
+		       bool allow_6ghz)
 {
 	struct p2p_go_neg_results params;
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
+	if (wpas_p2p_check_6ghz(wpa_s, NULL, allow_6ghz, freq))
+		return -1;
 
 	os_free(wpa_s->global->add_psk);
 	wpa_s->global->add_psk = NULL;
@@ -6763,7 +6999,8 @@
 				  int vht, int max_oper_chwidth, int he,
 				  int edmg,
 				  const struct p2p_channels *channels,
-				  int connection_timeout, int force_scan)
+				  int connection_timeout, int force_scan,
+				  bool allow_6ghz)
 {
 	struct p2p_go_neg_results params;
 	int go = 0, freq;
@@ -7155,7 +7392,8 @@
 		  enum p2p_discovery_type type,
 		  unsigned int num_req_dev_types, const u8 *req_dev_types,
 		  const u8 *dev_id, unsigned int search_delay,
-		  u8 seek_cnt, const char **seek_string, int freq)
+		  u8 seek_cnt, const char **seek_string, int freq,
+		  bool include_6ghz)
 {
 	wpas_p2p_clear_pending_action_tx(wpa_s);
 	wpa_s->global->p2p_long_listen = 0;
@@ -7174,7 +7412,8 @@
 
 	return p2p_find(wpa_s->global->p2p, timeout, type,
 			num_req_dev_types, req_dev_types, dev_id,
-			search_delay, seek_cnt, seek_string, freq);
+			search_delay, seek_cnt, seek_string, freq,
+			include_6ghz);
 }
 
 
@@ -7390,7 +7629,7 @@
 int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 		    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
 		    int vht_center_freq2, int ht40, int vht, int max_chwidth,
-		    int pref_freq, int he, int edmg)
+		    int pref_freq, int he, int edmg, bool allow_6ghz)
 {
 	enum p2p_invite_role role;
 	u8 *bssid = NULL;
@@ -7399,6 +7638,9 @@
 	int no_pref_freq_given = pref_freq == 0;
 	unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
 
+	if (wpas_p2p_check_6ghz(wpa_s, NULL, allow_6ghz, freq))
+		return -1;
+
 	wpa_s->global->p2p_invite_group = NULL;
 	if (peer_addr)
 		os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
@@ -7473,7 +7715,8 @@
 
 /* Invite to join an active group */
 int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
-			  const u8 *peer_addr, const u8 *go_dev_addr)
+			  const u8 *peer_addr, const u8 *go_dev_addr,
+			  bool allow_6ghz)
 {
 	struct wpa_global *global = wpa_s->global;
 	enum p2p_invite_role role;
@@ -7536,6 +7779,8 @@
 
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
+	if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
+		return -1;
 
 	size = P2P_MAX_PREF_CHANNELS;
 	res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
@@ -8438,7 +8683,7 @@
 			 wpa_s->p2p_go_max_oper_chwidth,
 			 wpa_s->p2p_go_he,
 			 wpa_s->p2p_go_edmg,
-			 NULL, 0);
+			 NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p));
 	return ret;
 }
 
@@ -8976,7 +9221,7 @@
 				-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
 				wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
 				params->go_ssid_len ? params->go_ssid : NULL,
-				params->go_ssid_len);
+				params->go_ssid_len, false);
 }
 
 
@@ -9055,7 +9300,7 @@
 				forced_freq, wpa_s->p2p_go_vht_center_freq2,
 				-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
 				wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
-				NULL, 0);
+				NULL, 0, false);
 }
 
 
@@ -9072,7 +9317,7 @@
 			       forced_freq, wpa_s->p2p_go_vht_center_freq2,
 			       -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
 			       wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
-			       NULL, 0);
+			       NULL, 0, false);
 	if (res)
 		return res;
 
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 941198e..5a869e7 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -38,19 +38,21 @@
 		     int go_intent, int freq, unsigned int vht_center_freq2,
 		     int persistent_id, int pd, int ht40, int vht,
 		     unsigned int vht_chwidth, int he, int edmg,
-		     const u8 *group_ssid, size_t group_ssid_len);
+		     const u8 *group_ssid, size_t group_ssid_len,
+		     bool allow_6ghz);
 int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
                                           int freq, struct wpa_ssid *ssid);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq, int vht_center_freq2, int ht40, int vht,
-		       int max_oper_chwidth, int he, int edmg);
+		       int max_oper_chwidth, int he, int edmg, bool allow_6ghz);
 int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
 				  struct wpa_ssid *ssid, int addr_allocated,
 				  int force_freq, int neg_freq,
 				  int vht_center_freq2, int ht40, int vht,
 				  int max_oper_chwidth, int he, int edmg,
 				  const struct p2p_channels *channels,
-				  int connection_timeout, int force_scan);
+				  int connection_timeout, int force_scan,
+				  bool allow_6ghz);
 struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
 				       struct wpa_ssid *ssid);
 enum wpas_p2p_prov_disc_use {
@@ -73,7 +75,8 @@
 		  enum p2p_discovery_type type,
 		  unsigned int num_req_dev_types, const u8 *req_dev_types,
 		  const u8 *dev_id, unsigned int search_delay,
-		  u8 seek_cnt, const char **seek_string, int freq);
+		  u8 seek_cnt, const char **seek_string, int freq,
+		  bool include_6ghz);
 void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s);
 int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout);
 int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s, unsigned int timeout);
@@ -117,9 +120,10 @@
 int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 		    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
 		    int vht_center_freq2, int ht40, int vht, int max_chwidth,
-		    int pref_freq, int he, int edmg);
+		    int pref_freq, int he, int edmg, bool allow_6ghz);
 int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
-			  const u8 *peer_addr, const u8 *go_dev_addr);
+			  const u8 *peer_addr, const u8 *go_dev_addr,
+			  bool allow_6ghz);
 int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
 			  u32 interval1, u32 duration2, u32 interval2);
 int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
@@ -142,12 +146,15 @@
 void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
 				       const u8 *addr);
 int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s);
-int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
-			   struct hostapd_hw_modes *mode, u8 channel);
+int wpas_p2p_get_sec_channel_offset_40mhz(struct wpa_supplicant *wpa_s,
+					  struct hostapd_hw_modes *mode,
+					  u8 channel);
 int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
-			      struct hostapd_hw_modes *mode, u8 channel);
+			      struct hostapd_hw_modes *mode, u8 channel,
+			      u8 op_class);
 int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
-			       struct hostapd_hw_modes *mode, u8 channel);
+			       struct hostapd_hw_modes *mode, u8 channel,
+			       u8 op_class);
 unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s);
 void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
 			 const u8 *p2p_dev_addr,
diff --git a/wpa_supplicant/p2p_supplicant_sd.c b/wpa_supplicant/p2p_supplicant_sd.c
index fb30584..312f46b 100644
--- a/wpa_supplicant/p2p_supplicant_sd.c
+++ b/wpa_supplicant/p2p_supplicant_sd.c
@@ -835,7 +835,7 @@
 		size_t buf_len;
 		u8 svc_len;
 
-		/* Sanity check fixed length+svc_str */
+		/* Validity check fixed length+svc_str */
 		if (6 >= tlv_end - pos)
 			break;
 		svc_len = pos[6];
@@ -863,7 +863,7 @@
 		buf_len = WPA_GET_LE16(pos);
 		pos += sizeof(u16);
 
-		/* Sanity check buffer length */
+		/* Validity check buffer length */
 		if (buf_len > (unsigned int) (tlv_end - pos))
 			break;
 
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index 4f5ac58..baf4c26 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -33,9 +33,18 @@
 	int cipher;
 	u16 group;
 	int network_id;
+	struct wpabuf *comeback;
 };
 
 
+static void wpas_pasn_free_auth_work(struct wpa_pasn_auth_work *awork)
+{
+	wpabuf_free(awork->comeback);
+	awork->comeback = NULL;
+	os_free(awork);
+}
+
+
 static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -56,8 +65,30 @@
 
 
 static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
-				  int akmp, int cipher, u8 status)
+				  int akmp, int cipher, u8 status,
+				  struct wpabuf *comeback,
+				  u16 comeback_after)
 {
+	if (comeback) {
+		size_t comeback_len = wpabuf_len(comeback);
+		size_t buflen = comeback_len * 2 + 1;
+		char *comeback_txt = os_malloc(buflen);
+
+		if (comeback_txt) {
+			wpa_snprintf_hex(comeback_txt, buflen,
+					 wpabuf_head(comeback), comeback_len);
+
+			wpa_msg(wpa_s, MSG_INFO, PASN_AUTH_STATUS MACSTR
+				" akmp=%s, status=%u comeback_after=%u comeback=%s",
+				MAC2STR(bssid),
+				wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
+				status, comeback_after, comeback_txt);
+
+			os_free(comeback_txt);
+			return;
+		}
+	}
+
 	wpa_msg(wpa_s, MSG_INFO,
 		PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
 		MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
@@ -71,30 +102,17 @@
 {
 	struct wpas_pasn *pasn = &wpa_s->pasn;
 	struct wpabuf *buf = NULL;
-	const char *password = NULL;
 	int ret;
 
-	if (pasn->ssid) {
-		password = pasn->ssid->sae_password;
-		if (!password)
-			password = pasn->ssid->passphrase;
-	}
-
-	if (!password) {
-		wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
-		return NULL;
-	}
-
 	ret = sae_set_group(&pasn->sae, pasn->group);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
 		return NULL;
 	}
 
-	/* TODO: SAE H2E */
-	ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
-				 (const u8 *) password, os_strlen(password), 0,
-				 &pasn->sae);
+	ret = sae_prepare_commit_pt(&pasn->sae, pasn->ssid->pt,
+				    wpa_s->own_addr, pasn->bssid,
+				    NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
 		return NULL;
@@ -109,7 +127,7 @@
 
 	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
 	wpabuf_put_le16(buf, 1);
-	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+	wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
 
 	sae_write_commit(&pasn->sae, buf, NULL, 0);
 	pasn->sae.state = SAE_COMMITTED;
@@ -155,14 +173,14 @@
 	wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
 		   alg, seq, status);
 
-	/* TODO: SAE H2E */
-	if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+	if (alg != WLAN_AUTH_SAE || seq != 1 ||
+	    status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
 		wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
 		return -1;
 	}
 
 	res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
-			       0);
+			       1);
 	if (res != WLAN_STATUS_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
 		return -1;
@@ -240,6 +258,31 @@
 	return buf;
 }
 
+
+static int wpas_pasn_sae_setup_pt(struct wpa_supplicant *wpa_s,
+				  struct wpa_ssid *ssid, int group)
+{
+	const char *password = ssid->sae_password;
+	int groups[2] = { group, 0 };
+
+	if (!password)
+		password = ssid->passphrase;
+
+	if (!password) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
+		return -1;
+	}
+
+	if (ssid->pt)
+		return 0; /* PT already derived */
+
+	ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
+				 (const u8 *) password, os_strlen(password),
+				 ssid->sae_password_id);
+
+	return ssid->pt ? 0 : -1;
+}
+
 #endif /* CONFIG_SAE */
 
 
@@ -612,7 +655,8 @@
 }
 
 
-static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
+static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s,
+					      const struct wpabuf *comeback)
 {
 	struct wpas_pasn *pasn = &wpa_s->pasn;
 	struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
@@ -680,14 +724,14 @@
 		wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
 
 	wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
-				  pubkey, NULL, -1);
+				  pubkey, true, comeback, -1);
 
 	if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
 		goto fail;
 
 	/* Add own RNSXE */
-	/* TODO: How to handle protected TWT and SAE H2E? */
 	capab = 0;
+	capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
 	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
 	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
@@ -753,7 +797,7 @@
 		wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
 
 	wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
-				  NULL, NULL, -1);
+				  NULL, false, NULL, -1);
 
 	if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
 		goto fail;
@@ -779,6 +823,13 @@
 		goto fail;
 	}
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (wpa_s->conf->pasn_corrupt_mic) {
+		wpa_printf(MSG_DEBUG, "PASN: frame 3: Corrupt MIC");
+		mic[0] = ~mic[0];
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	os_memcpy(ptr, mic, mic_len);
 
 	pasn->trans_seq++;
@@ -821,6 +872,10 @@
 	wpabuf_free(pasn->beacon_rsne_rsnxe);
 	pasn->beacon_rsne_rsnxe = NULL;
 
+	wpabuf_free(pasn->comeback);
+	pasn->comeback = NULL;
+	pasn->comeback_after = 0;
+
 #ifdef CONFIG_SAE
 	sae_clear_data(&pasn->sae);
 #endif /* CONFIG_SAE */
@@ -939,7 +994,7 @@
 			   int akmp, int cipher, u16 group, int freq,
 			   const u8 *beacon_rsne, u8 beacon_rsne_len,
 			   const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
-			   int network_id)
+			   int network_id, struct wpabuf *comeback)
 {
 	struct wpas_pasn *pasn = &wpa_s->pasn;
 	struct wpa_ssid *ssid = NULL;
@@ -965,6 +1020,20 @@
 				   "PASN: No network profile found for SAE");
 			return -1;
 		}
+
+		if (!ieee802_11_rsnx_capab(beacon_rsnxe,
+					   WLAN_RSNX_CAPAB_SAE_H2E)) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: AP does not support SAE H2E");
+			return -1;
+		}
+
+		if (wpas_pasn_sae_setup_pt(wpa_s, ssid, group) < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: Failed to derive PT");
+			return -1;
+		}
+
 		pasn->sae.state = SAE_NOTHING;
 		pasn->sae.send_confirm = 0;
 		pasn->ssid = ssid;
@@ -1009,6 +1078,15 @@
 	pasn->cipher = cipher;
 	pasn->group = group;
 	pasn->freq = freq;
+
+	if (wpa_s->conf->force_kdk_derivation ||
+	    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF &&
+	     ieee802_11_rsnx_capab(beacon_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
+		pasn->kdk_len = WPA_KDK_MAX_LEN;
+	else
+		pasn->kdk_len = 0;
+	wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len);
+
 	os_memcpy(pasn->bssid, bssid, ETH_ALEN);
 
 	wpa_printf(MSG_DEBUG,
@@ -1016,7 +1094,7 @@
 		   MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
 		   pasn->group);
 
-	frame = wpas_pasn_build_auth_1(wpa_s);
+	frame = wpas_pasn_build_auth_1(wpa_s, comeback);
 	if (!frame) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
 		goto fail;
@@ -1098,7 +1176,8 @@
 					     wpa_s, NULL);
 			wpa_s->pasn_auth_work = NULL;
 		}
-		os_free(awork);
+
+		wpas_pasn_free_auth_work(awork);
 		return;
 	}
 
@@ -1125,24 +1204,29 @@
 	ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
 			      awork->group, bss->freq, rsne, *(rsne + 1) + 2,
 			      rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
-			      awork->network_id);
+			      awork->network_id, awork->comeback);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: Failed to start PASN authentication");
 		goto fail;
 	}
 
+	/* comeback token is no longer needed at this stage */
+	wpabuf_free(awork->comeback);
+	awork->comeback = NULL;
+
 	wpa_s->pasn_auth_work = work;
 	return;
 fail:
-	os_free(awork);
+	wpas_pasn_free_auth_work(awork);
 	work->ctx = NULL;
 	radio_work_done(work);
 }
 
 
 int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
-			 int akmp, int cipher, u16 group, int network_id)
+			 int akmp, int cipher, u16 group, int network_id,
+			 const u8 *comeback, size_t comeback_len)
 {
 	struct wpa_pasn_auth_work *awork;
 	struct wpa_bss *bss;
@@ -1188,9 +1272,17 @@
 	awork->group = group;
 	awork->network_id = network_id;
 
+	if (comeback && comeback_len) {
+		awork->comeback = wpabuf_alloc_copy(comeback, comeback_len);
+		if (!awork->comeback) {
+			wpas_pasn_free_auth_work(awork);
+			return -1;
+		}
+	}
+
 	if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
 			   wpas_pasn_auth_start_cb, awork) < 0) {
-		os_free(awork);
+		wpas_pasn_free_auth_work(awork);
 		return -1;
 	}
 
@@ -1209,12 +1301,33 @@
 	wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
 
 	wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
-			      pasn->status);
+			      pasn->status, pasn->comeback,
+			      pasn->comeback_after);
 
 	wpas_pasn_reset(wpa_s);
 }
 
 
+static int wpas_pasn_immediate_retry(struct wpa_supplicant *wpa_s,
+				     struct wpas_pasn *pasn,
+				     struct wpa_pasn_params_data *params)
+{
+	int akmp = pasn->akmp;
+	int cipher = pasn->cipher;
+	u16 group = pasn->group;
+	u8 bssid[ETH_ALEN];
+	int network_id = pasn->ssid ? pasn->ssid->id : 0;
+
+	wpa_printf(MSG_DEBUG, "PASN: Immediate retry");
+	os_memcpy(bssid, pasn->bssid, ETH_ALEN);
+	wpas_pasn_reset(wpa_s);
+
+	return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group,
+				    network_id,
+				    params->comeback, params->comeback_len);
+}
+
+
 int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
 		      const struct ieee80211_mgmt *mgmt, size_t len)
 {
@@ -1226,7 +1339,7 @@
 	u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
 	u8 mic_len;
 	u16 status;
-	int ret;
+	int ret, inc_y;
 	u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
 			      (WLAN_FC_STYPE_AUTH << 4));
 
@@ -1308,10 +1421,26 @@
 		goto fail;
 	}
 
-	/* TODO: handle comeback flow */
 	if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: Authentication temporarily rejected");
+
+		if (pasn_params.comeback && pasn_params.comeback_len) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: Comeback token available. After=%u",
+				   pasn_params.after);
+
+			if (!pasn_params.after)
+				return wpas_pasn_immediate_retry(wpa_s, pasn,
+								 &pasn_params);
+
+			pasn->comeback = wpabuf_alloc_copy(
+				pasn_params.comeback, pasn_params.comeback_len);
+			if (pasn->comeback)
+				pasn->comeback_after = pasn_params.after;
+		}
+
+		pasn->status = status;
 		goto fail;
 	}
 
@@ -1344,9 +1473,21 @@
 		goto fail;
 	}
 
-	secret = crypto_ecdh_set_peerkey(pasn->ecdh, 0,
-					 pasn_params.pubkey,
-					 pasn_params.pubkey_len);
+	if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) {
+		inc_y = 1;
+	} else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 ||
+		   pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) {
+		inc_y = 0;
+	} else {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Invalid first octet in pubkey=0x%x",
+			   pasn_params.pubkey[0]);
+		goto fail;
+	}
+
+	secret = crypto_ecdh_set_peerkey(pasn->ecdh, inc_y,
+					 pasn_params.pubkey + 1,
+					 pasn_params.pubkey_len - 1);
 
 	if (!secret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
@@ -1374,7 +1515,7 @@
 			      wpa_s->own_addr, pasn->bssid,
 			      wpabuf_head(secret), wpabuf_len(secret),
 			      &pasn->ptk, pasn->akmp, pasn->cipher,
-			      WPA_KDK_MAX_LEN);
+			      pasn->kdk_len);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
 		goto fail;
@@ -1437,7 +1578,11 @@
 	 * the frame and terminate the authentication exchange. However, better
 	 * reply to the AP with an error status.
 	 */
-	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	if (status == WLAN_STATUS_SUCCESS)
+		pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	else
+		pasn->status = status;
+
 	wpas_pasn_auth_stop(wpa_s);
 	return -1;
 }
@@ -1507,3 +1652,59 @@
 
 	return 0;
 }
+
+
+int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+	struct wpa_bss *bss;
+	struct wpabuf *buf;
+	struct ieee80211_mgmt *deauth;
+	int ret;
+
+	if (os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) == 0) {
+		wpa_printf(MSG_DEBUG,
+			   "PASN: Cannot deauthenticate from current BSS");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "PASN: deauth: Flushing all PTKSA entries for "
+		   MACSTR, MAC2STR(bssid));
+	ptksa_cache_flush(wpa_s->ptksa, bssid, WPA_CIPHER_NONE);
+
+	bss = wpa_bss_get_bssid(wpa_s, bssid);
+	if (!bss) {
+		wpa_printf(MSG_DEBUG, "PASN: deauth: BSS not found");
+		return -1;
+	}
+
+	buf = wpabuf_alloc(64);
+	if (!buf) {
+		wpa_printf(MSG_DEBUG, "PASN: deauth: Failed wpabuf allocate");
+		return -1;
+	}
+
+	deauth = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
+					  u.deauth.variable));
+
+	deauth->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+					     (WLAN_FC_STYPE_DEAUTH << 4));
+
+	os_memcpy(deauth->da, bssid, ETH_ALEN);
+	os_memcpy(deauth->sa, wpa_s->own_addr, ETH_ALEN);
+	os_memcpy(deauth->bssid, bssid, ETH_ALEN);
+	deauth->u.deauth.reason_code =
+		host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+	/*
+	 * Since we do not expect any response from the AP, implement the
+	 * Deauthentication frame transmission using direct call to the driver
+	 * without a radio work.
+	 */
+	ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
+				bss->freq, 0);
+
+	wpabuf_free(buf);
+	wpa_printf(MSG_DEBUG, "PASN: deauth: send_mlme ret=%d", ret);
+
+	return ret;
+}
diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c
index 97c16fb..31b5532 100644
--- a/wpa_supplicant/preauth_test.c
+++ b/wpa_supplicant/preauth_test.c
@@ -220,7 +220,7 @@
 }
 
 
-static struct wpa_driver_ops dummy_driver;
+static struct wpa_driver_ops stub_driver;
 
 
 static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *ifname)
@@ -228,8 +228,8 @@
 	struct l2_packet_data *l2;
 	struct wpa_sm_ctx *ctx;
 
-	os_memset(&dummy_driver, 0, sizeof(dummy_driver));
-	wpa_s->driver = &dummy_driver;
+	os_memset(&stub_driver, 0, sizeof(stub_driver));
+	wpa_s->driver = &stub_driver;
 
 	ctx = os_zalloc(sizeof(*ctx));
 	assert(ctx != NULL);
diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c
index f6da56e..6110797 100644
--- a/wpa_supplicant/robust_av.c
+++ b/wpa_supplicant/robust_av.c
@@ -8,11 +8,17 @@
 
 #include "utils/includes.h"
 #include "utils/common.h"
+#include "utils/eloop.h"
 #include "common/wpa_ctrl.h"
 #include "common/ieee802_11_common.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "bss.h"
+#include "notify.h"
+
+
+#define SCS_RESP_TIMEOUT 1
+#define DSCP_REQ_TIMEOUT 5
 
 
 void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
@@ -45,6 +51,126 @@
 }
 
 
+static int wpas_populate_type4_classifier(struct type4_params *type4_param,
+					  struct wpabuf *buf)
+{
+	/* classifier parameters */
+	wpabuf_put_u8(buf, type4_param->classifier_mask);
+	if (type4_param->ip_version == IPV4) {
+		wpabuf_put_u8(buf, IPV4); /* IP version */
+		wpabuf_put_data(buf, &type4_param->ip_params.v4.src_ip.s_addr,
+				4);
+		wpabuf_put_data(buf, &type4_param->ip_params.v4.dst_ip.s_addr,
+				4);
+		wpabuf_put_be16(buf, type4_param->ip_params.v4.src_port);
+		wpabuf_put_be16(buf, type4_param->ip_params.v4.dst_port);
+		wpabuf_put_u8(buf, type4_param->ip_params.v4.dscp);
+		wpabuf_put_u8(buf, type4_param->ip_params.v4.protocol);
+		wpabuf_put_u8(buf, 0); /* Reserved octet */
+	} else {
+		wpabuf_put_u8(buf, IPV6);
+		wpabuf_put_data(buf, &type4_param->ip_params.v6.src_ip.s6_addr,
+				16);
+		wpabuf_put_data(buf, &type4_param->ip_params.v6.dst_ip.s6_addr,
+				16);
+		wpabuf_put_be16(buf, type4_param->ip_params.v6.src_port);
+		wpabuf_put_be16(buf, type4_param->ip_params.v6.dst_port);
+		wpabuf_put_u8(buf, type4_param->ip_params.v6.dscp);
+		wpabuf_put_u8(buf, type4_param->ip_params.v6.next_header);
+		wpabuf_put_data(buf, type4_param->ip_params.v6.flow_label, 3);
+	}
+
+	return 0;
+}
+
+
+static int wpas_populate_type10_classifier(struct type10_params *type10_param,
+					   struct wpabuf *buf)
+{
+	/* classifier parameters */
+	wpabuf_put_u8(buf, type10_param->prot_instance);
+	wpabuf_put_u8(buf, type10_param->prot_number);
+	wpabuf_put_data(buf, type10_param->filter_value,
+			type10_param->filter_len);
+	wpabuf_put_data(buf, type10_param->filter_mask,
+			type10_param->filter_len);
+	return 0;
+}
+
+
+static int wpas_populate_scs_descriptor_ie(struct scs_desc_elem *desc_elem,
+					   struct wpabuf *buf)
+{
+	u8 *len, *len1;
+	struct tclas_element *tclas_elem;
+	unsigned int i;
+
+	/* SCS Descriptor element */
+	wpabuf_put_u8(buf, WLAN_EID_SCS_DESCRIPTOR);
+	len = wpabuf_put(buf, 1);
+	wpabuf_put_u8(buf, desc_elem->scs_id);
+	wpabuf_put_u8(buf, desc_elem->request_type);
+	if (desc_elem->request_type == SCS_REQ_REMOVE)
+		goto end;
+
+	if (desc_elem->intra_access_priority || desc_elem->scs_up_avail) {
+		wpabuf_put_u8(buf, WLAN_EID_INTRA_ACCESS_CATEGORY_PRIORITY);
+		wpabuf_put_u8(buf, 1);
+		wpabuf_put_u8(buf, desc_elem->intra_access_priority);
+	}
+
+	tclas_elem = desc_elem->tclas_elems;
+
+	if (!tclas_elem)
+		return -1;
+
+	for (i = 0; i < desc_elem->num_tclas_elem; i++, tclas_elem++) {
+		int ret;
+
+		/* TCLAS element */
+		wpabuf_put_u8(buf, WLAN_EID_TCLAS);
+		len1 = wpabuf_put(buf, 1);
+		wpabuf_put_u8(buf, 255); /* User Priority: not compared */
+		/* Frame Classifier */
+		wpabuf_put_u8(buf, tclas_elem->classifier_type);
+		/* Frame classifier parameters */
+		switch (tclas_elem->classifier_type) {
+		case 4:
+			ret = wpas_populate_type4_classifier(
+				&tclas_elem->frame_classifier.type4_param,
+				buf);
+			break;
+		case 10:
+			ret = wpas_populate_type10_classifier(
+				&tclas_elem->frame_classifier.type10_param,
+				buf);
+			break;
+		default:
+			return -1;
+		}
+
+		if (ret == -1) {
+			wpa_printf(MSG_ERROR,
+				   "Failed to populate frame classifier");
+			return -1;
+		}
+
+		*len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1;
+	}
+
+	if (desc_elem->num_tclas_elem > 1) {
+		/* TCLAS Processing element */
+		wpabuf_put_u8(buf, WLAN_EID_TCLAS_PROCESSING);
+		wpabuf_put_u8(buf, 1);
+		wpabuf_put_u8(buf, desc_elem->tclas_processing);
+	}
+
+end:
+	*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
+	return 0;
+}
+
+
 int wpas_send_mscs_req(struct wpa_supplicant *wpa_s)
 {
 	struct wpabuf *buf;
@@ -101,6 +227,277 @@
 }
 
 
+static size_t tclas_elem_len(const struct tclas_element *elem)
+{
+	size_t buf_len = 0;
+
+	buf_len += 2 +	/* TCLAS element header */
+		1 +	/* User Priority */
+		1 ;	/* Classifier Type */
+
+	if (elem->classifier_type == 4) {
+		enum ip_version ip_ver;
+
+		buf_len += 1 +	/* Classifier mask */
+			1 +	/* IP version */
+			1 +	/* user priority */
+			2 +	/* src_port */
+			2 +	/* dst_port */
+			1 ;	/* dscp */
+		ip_ver = elem->frame_classifier.type4_param.ip_version;
+		if (ip_ver == IPV4) {
+			buf_len += 4 +  /* src_ip */
+				4 +	/* dst_ip */
+				1 +	/* protocol */
+				1 ;  /* Reserved */
+		} else if (ip_ver == IPV6) {
+			buf_len += 16 +  /* src_ip */
+				16 +  /* dst_ip */
+				1  +  /* next_header */
+				3  ;  /* flow_label */
+		} else {
+			wpa_printf(MSG_ERROR, "%s: Incorrect IP version %d",
+				   __func__, ip_ver);
+			return 0;
+		}
+	} else if (elem->classifier_type == 10) {
+		buf_len += 1 +	/* protocol instance */
+			1 +	/* protocol number */
+			2 * elem->frame_classifier.type10_param.filter_len;
+	} else {
+		wpa_printf(MSG_ERROR, "%s: Incorrect classifier type %u",
+			   __func__, elem->classifier_type);
+		return 0;
+	}
+
+	return buf_len;
+}
+
+
+static struct wpabuf * allocate_scs_buf(struct scs_desc_elem *desc_elem,
+					unsigned int num_scs_desc)
+{
+	struct wpabuf *buf;
+	size_t buf_len = 0;
+	unsigned int i, j;
+
+	buf_len = 3; /* Action frame header */
+
+	for (i = 0; i < num_scs_desc; i++, desc_elem++) {
+		struct tclas_element *tclas_elem;
+
+		buf_len += 2 +	/* SCS descriptor IE header */
+			   1 +	/* SCSID */
+			   1 ;	/* Request type */
+
+		if (desc_elem->request_type == SCS_REQ_REMOVE)
+			continue;
+
+		if (desc_elem->intra_access_priority || desc_elem->scs_up_avail)
+			buf_len += 3;
+
+		tclas_elem = desc_elem->tclas_elems;
+		if (!tclas_elem) {
+			wpa_printf(MSG_ERROR, "%s: TCLAS element null",
+				   __func__);
+			return NULL;
+		}
+
+		for (j = 0; j < desc_elem->num_tclas_elem; j++, tclas_elem++) {
+			size_t elen;
+
+			elen = tclas_elem_len(tclas_elem);
+			if (elen == 0)
+				return NULL;
+			buf_len += elen;
+		}
+
+		if (desc_elem->num_tclas_elem > 1) {
+			buf_len += 1 +	/* TCLAS Processing eid */
+				   1 +	/* length */
+				   1 ;	/* processing */
+		}
+	}
+
+	buf = wpabuf_alloc(buf_len);
+	if (!buf) {
+		wpa_printf(MSG_ERROR, "Failed to allocate SCS req");
+		return NULL;
+	}
+
+	return buf;
+}
+
+
+static void scs_request_timer(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	struct active_scs_elem *scs_desc, *prev;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
+		return;
+
+	/* Once timeout is over, remove all SCS descriptors with no response */
+	dl_list_for_each_safe(scs_desc, prev, &wpa_s->active_scs_ids,
+			      struct active_scs_elem, list) {
+		u8 bssid[ETH_ALEN] = { 0 };
+		const u8 *src;
+
+		if (scs_desc->status == SCS_DESC_SUCCESS)
+			continue;
+
+		if (wpa_s->current_bss)
+			src = wpa_s->current_bss->bssid;
+		else
+			src = bssid;
+
+		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCS_RESULT "bssid=" MACSTR
+			" SCSID=%u status_code=timedout", MAC2STR(src),
+			scs_desc->scs_id);
+
+		dl_list_del(&scs_desc->list);
+		wpa_printf(MSG_INFO, "%s: SCSID %d removed after timeout",
+			   __func__, scs_desc->scs_id);
+		os_free(scs_desc);
+	}
+
+	eloop_cancel_timeout(scs_request_timer, wpa_s, NULL);
+	wpa_s->ongoing_scs_req = false;
+}
+
+
+int wpas_send_scs_req(struct wpa_supplicant *wpa_s)
+{
+	struct wpabuf *buf = NULL;
+	struct scs_desc_elem *desc_elem = NULL;
+	int ret = -1;
+	unsigned int i;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
+		return -1;
+
+	if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_SCS)) {
+		wpa_dbg(wpa_s, MSG_INFO,
+			"AP does not support SCS - could not send SCS Request");
+		return -1;
+	}
+
+	desc_elem = wpa_s->scs_robust_av_req.scs_desc_elems;
+	if (!desc_elem)
+		return -1;
+
+	buf = allocate_scs_buf(desc_elem,
+			       wpa_s->scs_robust_av_req.num_scs_desc);
+	if (!buf)
+		return -1;
+
+	wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING);
+	wpabuf_put_u8(buf, ROBUST_AV_SCS_REQ);
+	wpa_s->scs_dialog_token++;
+	if (wpa_s->scs_dialog_token == 0)
+		wpa_s->scs_dialog_token++;
+	wpabuf_put_u8(buf, wpa_s->scs_dialog_token);
+
+	for (i = 0; i < wpa_s->scs_robust_av_req.num_scs_desc;
+	     i++, desc_elem++) {
+		/* SCS Descriptor element */
+		if (wpas_populate_scs_descriptor_ie(desc_elem, buf) < 0)
+			goto end;
+	}
+
+	wpa_hexdump_buf(MSG_DEBUG, "SCS Request", buf);
+	ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				  wpa_s->own_addr, wpa_s->bssid,
+				  wpabuf_head(buf), wpabuf_len(buf), 0);
+	if (ret < 0) {
+		wpa_dbg(wpa_s, MSG_ERROR, "SCS: Failed to send SCS Request");
+		wpa_s->scs_dialog_token--;
+		goto end;
+	}
+
+	desc_elem = wpa_s->scs_robust_av_req.scs_desc_elems;
+	for (i = 0; i < wpa_s->scs_robust_av_req.num_scs_desc;
+	     i++, desc_elem++) {
+		struct active_scs_elem *active_scs_elem;
+
+		if (desc_elem->request_type != SCS_REQ_ADD)
+			continue;
+
+		active_scs_elem = os_malloc(sizeof(struct active_scs_elem));
+		if (!active_scs_elem)
+			break;
+		active_scs_elem->scs_id = desc_elem->scs_id;
+		active_scs_elem->status = SCS_DESC_SENT;
+		dl_list_add(&wpa_s->active_scs_ids, &active_scs_elem->list);
+	}
+
+	/*
+	 * Register a timeout after which this request will be removed from
+	 * the cache.
+	 */
+	eloop_register_timeout(SCS_RESP_TIMEOUT, 0, scs_request_timer, wpa_s,
+			       NULL);
+	wpa_s->ongoing_scs_req = true;
+
+end:
+	wpabuf_free(buf);
+	free_up_scs_desc(&wpa_s->scs_robust_av_req);
+
+	return ret;
+}
+
+
+void free_up_tclas_elem(struct scs_desc_elem *elem)
+{
+	struct tclas_element *tclas_elems = elem->tclas_elems;
+	unsigned int num_tclas_elem = elem->num_tclas_elem;
+	struct tclas_element *tclas_data;
+	unsigned int j;
+
+	elem->tclas_elems = NULL;
+	elem->num_tclas_elem = 0;
+
+	if (!tclas_elems)
+		return;
+
+	tclas_data = tclas_elems;
+	for (j = 0; j < num_tclas_elem; j++, tclas_data++) {
+		if (tclas_data->classifier_type != 10)
+			continue;
+
+		os_free(tclas_data->frame_classifier.type10_param.filter_value);
+		os_free(tclas_data->frame_classifier.type10_param.filter_mask);
+	}
+
+	os_free(tclas_elems);
+}
+
+
+void free_up_scs_desc(struct scs_robust_av_data *data)
+{
+	struct scs_desc_elem *desc_elems = data->scs_desc_elems;
+	unsigned int num_scs_desc = data->num_scs_desc;
+	struct scs_desc_elem *desc_data;
+	unsigned int i;
+
+	data->scs_desc_elems = NULL;
+	data->num_scs_desc = 0;
+
+	if (!desc_elems)
+		return;
+
+	desc_data = desc_elems;
+	for (i = 0; i < num_scs_desc; i++, desc_data++) {
+		if (desc_data->request_type == SCS_REQ_REMOVE ||
+		    !desc_data->tclas_elems)
+			continue;
+
+		free_up_tclas_elem(desc_data);
+	}
+	os_free(desc_elems);
+}
+
+
 void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
 				       const u8 *src, const u8 *buf, size_t len)
 {
@@ -118,7 +515,7 @@
 		return;
 	}
 
-	status_code = *buf;
+	status_code = WPA_GET_LE16(buf);
 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
 		" status_code=%u", MAC2STR(src), status_code);
 	wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
@@ -153,3 +550,952 @@
 		" status_code=%u", MAC2STR(bssid), status);
 	wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS;
 }
+
+
+static void wpas_wait_for_dscp_req_timer(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+
+	/* Once timeout is over, reset wait flag and allow sending DSCP query */
+	wpa_printf(MSG_DEBUG,
+		   "QM: Wait time over for sending DSCP request - allow DSCP query");
+	wpa_s->wait_for_dscp_req = 0;
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait end");
+}
+
+
+void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
+				     const u8 *ies, size_t ies_len)
+{
+	const u8 *wfa_capa;
+
+	wpa_s->connection_dscp = 0;
+	if (wpa_s->wait_for_dscp_req)
+		eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
+
+	if (!ies || ies_len == 0 || !wpa_s->enable_dscp_policy_capa)
+		return;
+
+	wfa_capa = get_vendor_ie(ies, ies_len, WFA_CAPA_IE_VENDOR_TYPE);
+	if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
+	    !(wfa_capa[7] & WFA_CAPA_QM_DSCP_POLICY))
+		return; /* AP does not enable QM DSCP Policy */
+
+	wpa_s->connection_dscp = 1;
+	wpa_s->wait_for_dscp_req = !!(wfa_capa[7] &
+				      WFA_CAPA_QM_UNSOLIC_DSCP);
+	if (!wpa_s->wait_for_dscp_req)
+		return;
+
+	/* Register a timeout after which dscp query can be sent to AP. */
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait start");
+	eloop_register_timeout(DSCP_REQ_TIMEOUT, 0,
+			       wpas_wait_for_dscp_req_timer, wpa_s, NULL);
+}
+
+
+void wpas_handle_robust_av_scs_recv_action(struct wpa_supplicant *wpa_s,
+					   const u8 *src, const u8 *buf,
+					   size_t len)
+{
+	u8 dialog_token;
+	unsigned int i, count;
+	struct active_scs_elem *scs_desc, *prev;
+
+	if (len < 2)
+		return;
+	if (!wpa_s->ongoing_scs_req) {
+		wpa_printf(MSG_INFO,
+			   "SCS: Drop received response due to no ongoing request");
+		return;
+	}
+
+	dialog_token = *buf++;
+	len--;
+	if (dialog_token != wpa_s->scs_dialog_token) {
+		wpa_printf(MSG_INFO,
+			   "SCS: Drop received frame due to dialog token mismatch: received:%u expected:%u",
+			   dialog_token, wpa_s->scs_dialog_token);
+		return;
+	}
+
+	/* This Count field does not exist in the IEEE Std 802.11-2020
+	 * definition of the SCS Response frame. However, it was accepted to
+	 * be added into REVme per REVme/D0.0 CC35 CID 49 (edits in document
+	 * 11-21-0688-07). */
+	count = *buf++;
+	len--;
+	if (count == 0 || count * 3 > len) {
+		wpa_printf(MSG_INFO,
+			   "SCS: Drop received frame due to invalid count: %u (remaining %zu octets)",
+			   count, len);
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+		u8 id;
+		u16 status;
+		bool scs_desc_found = false;
+
+		id = *buf++;
+		status = WPA_GET_LE16(buf);
+		buf += 2;
+		len -= 3;
+
+		dl_list_for_each(scs_desc, &wpa_s->active_scs_ids,
+				 struct active_scs_elem, list) {
+			if (id == scs_desc->scs_id) {
+				scs_desc_found = true;
+				break;
+			}
+		}
+
+		if (!scs_desc_found) {
+			wpa_printf(MSG_INFO, "SCS: SCS ID invalid %u", id);
+			continue;
+		}
+
+		if (status != WLAN_STATUS_SUCCESS) {
+			dl_list_del(&scs_desc->list);
+			os_free(scs_desc);
+		} else if (status == WLAN_STATUS_SUCCESS) {
+			scs_desc->status = SCS_DESC_SUCCESS;
+		}
+
+		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCS_RESULT "bssid=" MACSTR
+			" SCSID=%u status_code=%u", MAC2STR(src), id, status);
+	}
+
+	eloop_cancel_timeout(scs_request_timer, wpa_s, NULL);
+	wpa_s->ongoing_scs_req = false;
+
+	dl_list_for_each_safe(scs_desc, prev, &wpa_s->active_scs_ids,
+			      struct active_scs_elem, list) {
+		if (scs_desc->status != SCS_DESC_SUCCESS) {
+			wpa_msg(wpa_s, MSG_INFO,
+				WPA_EVENT_SCS_RESULT "bssid=" MACSTR
+				" SCSID=%u status_code=response_not_received",
+				MAC2STR(src), scs_desc->scs_id);
+			dl_list_del(&scs_desc->list);
+			os_free(scs_desc);
+		}
+	}
+}
+
+
+static void wpas_clear_active_scs_ids(struct wpa_supplicant *wpa_s)
+{
+	struct active_scs_elem *scs_elem;
+
+	while ((scs_elem = dl_list_first(&wpa_s->active_scs_ids,
+					 struct active_scs_elem, list))) {
+		dl_list_del(&scs_elem->list);
+		os_free(scs_elem);
+	}
+}
+
+
+void wpas_scs_deinit(struct wpa_supplicant *wpa_s)
+{
+	free_up_scs_desc(&wpa_s->scs_robust_av_req);
+	wpa_s->scs_dialog_token = 0;
+	wpas_clear_active_scs_ids(wpa_s);
+	eloop_cancel_timeout(scs_request_timer, wpa_s, NULL);
+	wpa_s->ongoing_scs_req = false;
+}
+
+
+static int write_ipv4_info(char *pos, int total_len,
+			   const struct ipv4_params *v4)
+{
+	int res, rem_len;
+	char addr[INET_ADDRSTRLEN];
+
+	rem_len = total_len;
+
+	if (v4->param_mask & BIT(1)) {
+		if (!inet_ntop(AF_INET, &v4->src_ip, addr, INET_ADDRSTRLEN)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to set IPv4 source address");
+			return -1;
+		}
+
+		res = os_snprintf(pos, rem_len, " src_ip=%s", addr);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v4->param_mask & BIT(2)) {
+		if (!inet_ntop(AF_INET, &v4->dst_ip, addr, INET_ADDRSTRLEN)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to set IPv4 destination address");
+			return -1;
+		}
+
+		res = os_snprintf(pos, rem_len, " dst_ip=%s", addr);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v4->param_mask & BIT(3)) {
+		res = os_snprintf(pos, rem_len, " src_port=%d", v4->src_port);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v4->param_mask & BIT(4)) {
+		res = os_snprintf(pos, rem_len, " dst_port=%d", v4->dst_port);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v4->param_mask & BIT(6)) {
+		res = os_snprintf(pos, rem_len, " protocol=%d", v4->protocol);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	return total_len - rem_len;
+}
+
+
+static int write_ipv6_info(char *pos, int total_len,
+			   const struct ipv6_params *v6)
+{
+	int res, rem_len;
+	char addr[INET6_ADDRSTRLEN];
+
+	rem_len = total_len;
+
+	if (v6->param_mask & BIT(1)) {
+		if (!inet_ntop(AF_INET6, &v6->src_ip, addr, INET6_ADDRSTRLEN)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to set IPv6 source addr");
+			return -1;
+		}
+
+		res = os_snprintf(pos, rem_len, " src_ip=%s", addr);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v6->param_mask & BIT(2)) {
+		if (!inet_ntop(AF_INET6, &v6->dst_ip, addr, INET6_ADDRSTRLEN)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to set IPv6 destination addr");
+			return -1;
+		}
+
+		res = os_snprintf(pos, rem_len, " dst_ip=%s", addr);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v6->param_mask & BIT(3)) {
+		res = os_snprintf(pos, rem_len, " src_port=%d", v6->src_port);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v6->param_mask & BIT(4)) {
+		res = os_snprintf(pos, rem_len, " dst_port=%d", v6->dst_port);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	if (v6->param_mask & BIT(6)) {
+		res = os_snprintf(pos, rem_len, " protocol=%d",
+				  v6->next_header);
+		if (os_snprintf_error(rem_len, res))
+			return -1;
+
+		pos += res;
+		rem_len -= res;
+	}
+
+	return total_len - rem_len;
+}
+
+
+static int set_frame_classifier_type4_ipv4(struct dscp_policy_data *policy)
+{
+	u8 classifier_mask;
+	const u8 *frame_classifier = policy->frame_classifier;
+	struct type4_params *type4_param = &policy->type4_param;
+
+	if (policy->frame_classifier_len < 18) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Received IPv4 frame classifier with insufficient length %d",
+			   policy->frame_classifier_len);
+		return -1;
+	}
+
+	classifier_mask = frame_classifier[1];
+
+	/* Classifier Mask - bit 1 = Source IP Address */
+	if (classifier_mask & BIT(1)) {
+		type4_param->ip_params.v4.param_mask |= BIT(1);
+		os_memcpy(&type4_param->ip_params.v4.src_ip,
+			  &frame_classifier[3], 4);
+	}
+
+	/* Classifier Mask - bit 2 = Destination IP Address */
+	if (classifier_mask & BIT(2)) {
+		if (policy->domain_name) {
+			wpa_printf(MSG_ERROR,
+				   "QM: IPv4: Both domain name and destination IP address not expected");
+			return -1;
+		}
+
+		type4_param->ip_params.v4.param_mask |= BIT(2);
+		os_memcpy(&type4_param->ip_params.v4.dst_ip,
+			  &frame_classifier[7], 4);
+	}
+
+	/* Classifier Mask - bit 3 = Source Port */
+	if (classifier_mask & BIT(3)) {
+		type4_param->ip_params.v4.param_mask |= BIT(3);
+		type4_param->ip_params.v4.src_port =
+			WPA_GET_BE16(&frame_classifier[11]);
+	}
+
+	/* Classifier Mask - bit 4 = Destination Port */
+	if (classifier_mask & BIT(4)) {
+		if (policy->port_range_info) {
+			wpa_printf(MSG_ERROR,
+				   "QM: IPv4: Both port range and destination port not expected");
+			return -1;
+		}
+
+		type4_param->ip_params.v4.param_mask |= BIT(4);
+		type4_param->ip_params.v4.dst_port =
+			WPA_GET_BE16(&frame_classifier[13]);
+	}
+
+	/* Classifier Mask - bit 5 = DSCP (ignored) */
+
+	/* Classifier Mask - bit 6 = Protocol */
+	if (classifier_mask & BIT(6)) {
+		type4_param->ip_params.v4.param_mask |= BIT(6);
+		type4_param->ip_params.v4.protocol = frame_classifier[16];
+	}
+
+	return 0;
+}
+
+
+static int set_frame_classifier_type4_ipv6(struct dscp_policy_data *policy)
+{
+	u8 classifier_mask;
+	const u8 *frame_classifier = policy->frame_classifier;
+	struct type4_params *type4_param = &policy->type4_param;
+
+	if (policy->frame_classifier_len < 44) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Received IPv6 frame classifier with insufficient length %d",
+			   policy->frame_classifier_len);
+		return -1;
+	}
+
+	classifier_mask = frame_classifier[1];
+
+	/* Classifier Mask - bit 1 = Source IP Address */
+	if (classifier_mask & BIT(1)) {
+		type4_param->ip_params.v6.param_mask |= BIT(1);
+		os_memcpy(&type4_param->ip_params.v6.src_ip,
+			  &frame_classifier[3], 16);
+	}
+
+	/* Classifier Mask - bit 2 = Destination IP Address */
+	if (classifier_mask & BIT(2)) {
+		if (policy->domain_name) {
+			wpa_printf(MSG_ERROR,
+				   "QM: IPv6: Both domain name and destination IP address not expected");
+			return -1;
+		}
+		type4_param->ip_params.v6.param_mask |= BIT(2);
+		os_memcpy(&type4_param->ip_params.v6.dst_ip,
+			  &frame_classifier[19], 16);
+	}
+
+	/* Classifier Mask - bit 3 = Source Port */
+	if (classifier_mask & BIT(3)) {
+		type4_param->ip_params.v6.param_mask |= BIT(3);
+		type4_param->ip_params.v6.src_port =
+				WPA_GET_BE16(&frame_classifier[35]);
+	}
+
+	/* Classifier Mask - bit 4 = Destination Port */
+	if (classifier_mask & BIT(4)) {
+		if (policy->port_range_info) {
+			wpa_printf(MSG_ERROR,
+				   "IPv6: Both port range and destination port not expected");
+			return -1;
+		}
+
+		type4_param->ip_params.v6.param_mask |= BIT(4);
+		type4_param->ip_params.v6.dst_port =
+				WPA_GET_BE16(&frame_classifier[37]);
+	}
+
+	/* Classifier Mask - bit 5 = DSCP (ignored) */
+
+	/* Classifier Mask - bit 6 = Next Header */
+	if (classifier_mask & BIT(6)) {
+		type4_param->ip_params.v6.param_mask |= BIT(6);
+		type4_param->ip_params.v6.next_header = frame_classifier[40];
+	}
+
+	return 0;
+}
+
+
+static int wpas_set_frame_classifier_params(struct dscp_policy_data *policy)
+{
+	const u8 *frame_classifier = policy->frame_classifier;
+	u8 frame_classifier_len = policy->frame_classifier_len;
+
+	if (frame_classifier_len < 3) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Received frame classifier with insufficient length %d",
+			   frame_classifier_len);
+		return -1;
+	}
+
+	/* Only allowed Classifier Type: IP and higher layer parameters (4) */
+	if (frame_classifier[0] != 4) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Received frame classifier with invalid classifier type %d",
+			   frame_classifier[0]);
+		return -1;
+	}
+
+	/* Classifier Mask - bit 0 = Version */
+	if (!(frame_classifier[1] & BIT(0))) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Received frame classifier without IP version");
+		return -1;
+	}
+
+	/* Version (4 or 6) */
+	if (frame_classifier[2] == 4) {
+		if (set_frame_classifier_type4_ipv4(policy)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to set IPv4 parameters");
+			return -1;
+		}
+
+		policy->type4_param.ip_version = IPV4;
+	} else if (frame_classifier[2] == 6) {
+		if (set_frame_classifier_type4_ipv6(policy)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to set IPv6 parameters");
+			return -1;
+		}
+
+		policy->type4_param.ip_version = IPV6;
+	} else {
+		wpa_printf(MSG_ERROR,
+			   "QM: Received unknown IP version %d",
+			   frame_classifier[2]);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static bool dscp_valid_domain_name(const char *str)
+{
+	if (!str[0])
+		return false;
+
+	while (*str) {
+		if (is_ctrl_char(*str) || *str == ' ' || *str == '=')
+			return false;
+		str++;
+	}
+
+	return true;
+}
+
+
+static int  wpas_add_dscp_policy(struct wpa_supplicant *wpa_s,
+				 struct dscp_policy_data *policy)
+{
+	int ip_ver = 0, res;
+	char policy_str[1000], *pos;
+	int len;
+
+	if (!policy->frame_classifier && !policy->domain_name &&
+	    !policy->port_range_info) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Invalid DSCP policy - no attributes present");
+		goto fail;
+	}
+
+	policy_str[0] = '\0';
+	pos = policy_str;
+	len = sizeof(policy_str);
+
+	if (policy->frame_classifier) {
+		struct type4_params *type4 = &policy->type4_param;
+
+		if (wpas_set_frame_classifier_params(policy)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to set frame classifier parameters");
+			goto fail;
+		}
+
+		if (type4->ip_version == IPV4)
+			res = write_ipv4_info(pos, len, &type4->ip_params.v4);
+		else
+			res = write_ipv6_info(pos, len, &type4->ip_params.v6);
+
+		if (res <= 0) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to write IP parameters");
+			goto fail;
+		}
+
+		ip_ver = type4->ip_version;
+
+		pos += res;
+		len -= res;
+	}
+
+	if (policy->port_range_info) {
+		res = os_snprintf(pos, len, " start_port=%u end_port=%u",
+				  policy->start_port, policy->end_port);
+		if (os_snprintf_error(len, res)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to write port range attributes for policy id = %d",
+				   policy->policy_id);
+			goto fail;
+		}
+
+		pos += res;
+		len -= res;
+	}
+
+	if (policy->domain_name) {
+		char domain_name_str[250];
+
+		if (policy->domain_name_len >= sizeof(domain_name_str)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Domain name length higher than max expected");
+			goto fail;
+		}
+		os_memcpy(domain_name_str, policy->domain_name,
+			  policy->domain_name_len);
+		domain_name_str[policy->domain_name_len] = '\0';
+		if (!dscp_valid_domain_name(domain_name_str)) {
+			wpa_printf(MSG_ERROR, "QM: Invalid domain name string");
+			goto fail;
+		}
+		res = os_snprintf(pos, len, " domain_name=%s", domain_name_str);
+		if (os_snprintf_error(len, res)) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Failed to write domain name attribute for policy id = %d",
+				   policy->policy_id);
+			goto fail;
+		}
+	}
+
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY
+		"add policy_id=%u dscp=%u ip_version=%d%s",
+		policy->policy_id, policy->dscp, ip_ver, policy_str);
+	return 0;
+fail:
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "reject policy_id=%u",
+		policy->policy_id);
+	return -1;
+}
+
+
+void wpas_dscp_deinit(struct wpa_supplicant *wpa_s)
+{
+	wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies");
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all");
+	wpa_s->dscp_req_dialog_token = 0;
+	wpa_s->dscp_query_dialog_token = 0;
+	wpa_s->connection_dscp = 0;
+	if (wpa_s->wait_for_dscp_req) {
+		wpa_s->wait_for_dscp_req = 0;
+		eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
+	}
+}
+
+
+static void wpas_fill_dscp_policy(struct dscp_policy_data *policy, u8 attr_id,
+				  u8 attr_len, const u8 *attr_data)
+{
+	switch (attr_id) {
+	case QM_ATTR_PORT_RANGE:
+		if (attr_len < 4) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Received Port Range attribute with insufficient length %d",
+				    attr_len);
+			break;
+		}
+		policy->start_port = WPA_GET_BE16(attr_data);
+		policy->end_port = WPA_GET_BE16(attr_data + 2);
+		policy->port_range_info = true;
+		break;
+	case QM_ATTR_DSCP_POLICY:
+		if (attr_len < 3) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Received DSCP Policy attribute with insufficient length %d",
+				   attr_len);
+			return;
+		}
+		policy->policy_id = attr_data[0];
+		policy->req_type = attr_data[1];
+		policy->dscp = attr_data[2];
+		policy->dscp_info = true;
+		break;
+	case QM_ATTR_TCLAS:
+		if (attr_len < 1) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Received TCLAS attribute with insufficient length %d",
+				   attr_len);
+			return;
+		}
+		policy->frame_classifier = attr_data;
+		policy->frame_classifier_len = attr_len;
+		break;
+	case QM_ATTR_DOMAIN_NAME:
+		if (attr_len < 1) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Received domain name attribute with insufficient length %d",
+				   attr_len);
+			return;
+		}
+		policy->domain_name = attr_data;
+		policy->domain_name_len = attr_len;
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "QM: Received invalid QoS attribute %d",
+			   attr_id);
+		break;
+	}
+}
+
+
+void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s,
+				      const u8 *src,
+				      const u8 *buf, size_t len)
+{
+	int rem_len;
+	const u8 *qos_ie, *attr;
+	int more, reset;
+
+        struct dscp_policy_data *policies = NULL, *policies_temp;
+        int num_dscp_policies = 0;
+
+	if (!wpa_s->enable_dscp_policy_capa) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Ignore DSCP Policy frame since the capability is not enabled");
+		return;
+	}
+
+	if (!pmf_in_use(wpa_s, src)) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Ignore DSCP Policy frame since PMF is not in use");
+		return;
+	}
+
+	if (!wpa_s->connection_dscp) {
+		 wpa_printf(MSG_DEBUG,
+			    "QM: DSCP Policy capability not enabled for the current association - ignore QoS Management Action frames");
+		return;
+	}
+
+	if (len < 1)
+		return;
+
+	/* Handle only DSCP Policy Request frame */
+	if (buf[0] != QM_DSCP_POLICY_REQ) {
+		wpa_printf(MSG_ERROR, "QM: Received unexpected QoS action frame %d",
+			   buf[0]);
+		return;
+	}
+
+	if (len < 3) {
+		wpa_printf(MSG_ERROR,
+			   "Received QoS Management DSCP Policy Request frame with invalid length %zu",
+			   len);
+		return;
+	}
+
+	/* Clear wait_for_dscp_req on receiving first DSCP request from AP */
+	if (wpa_s->wait_for_dscp_req) {
+		wpa_s->wait_for_dscp_req = 0;
+		eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
+	}
+
+	wpa_s->dscp_req_dialog_token = buf[1];
+	more = buf[2] & DSCP_POLICY_CTRL_MORE;
+	reset = buf[2] & DSCP_POLICY_CTRL_RESET;
+
+        if (reset)
+                wpas_notify_qos_policy_reset(wpa_s);
+
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_start%s%s",
+		reset ? " clear_all" : "", more ? " more" : "");
+
+	qos_ie = buf + 3;
+	rem_len = len - 3;
+	while (rem_len > 2) {
+		struct dscp_policy_data policy;
+		int res = 0;
+		int rem_attrs_len, ie_len;
+
+		ie_len = 2 + qos_ie[1];
+		if (rem_len < ie_len)
+			break;
+
+		if (rem_len < 6 || qos_ie[0] != WLAN_EID_VENDOR_SPECIFIC ||
+		    qos_ie[1] < 4 ||
+		    WPA_GET_BE32(&qos_ie[2]) != QM_IE_VENDOR_TYPE) {
+			rem_len -= ie_len;
+			qos_ie += ie_len;
+			continue;
+		}
+
+		os_memset(&policy, 0, sizeof(struct dscp_policy_data));
+		attr = qos_ie + 6;
+		rem_attrs_len = qos_ie[1] - 4;
+
+		while (rem_attrs_len > 2 && rem_attrs_len >= 2 + attr[1]) {
+			wpas_fill_dscp_policy(&policy, attr[0], attr[1],
+					      &attr[2]);
+			rem_attrs_len -= 2 + attr[1];
+			attr += 2 + attr[1];
+		}
+
+		rem_len -= ie_len;
+		qos_ie += ie_len;
+
+		if (!policy.dscp_info) {
+			wpa_printf(MSG_ERROR,
+				   "QM: Received QoS IE without DSCP Policy attribute");
+			continue;
+		}
+
+		if (policy.req_type == DSCP_POLICY_REQ_ADD)
+			res = wpas_add_dscp_policy(wpa_s, &policy);
+		else if (policy.req_type == DSCP_POLICY_REQ_REMOVE)
+			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY
+				"remove policy_id=%u", policy.policy_id);
+		else {
+			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY
+				"reject policy_id=%u", policy.policy_id);
+			res = -1;
+		}
+
+		if (res)
+			continue;
+
+		policies_temp = os_realloc(policies,
+					   (num_dscp_policies + 1)  *
+					   sizeof(struct dscp_policy_data));
+		if (!policies_temp)
+			goto fail;
+
+		policies = policies_temp;
+		policies[num_dscp_policies] = policy;
+		num_dscp_policies++;
+	}
+
+	wpas_notify_qos_policy_request(wpa_s, policies, num_dscp_policies);
+
+	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_end");
+
+fail:
+        os_free(policies);
+        return;
+}
+
+
+int wpas_send_dscp_response(struct wpa_supplicant *wpa_s,
+			    struct dscp_resp_data *resp_data)
+{
+	struct wpabuf *buf = NULL;
+	size_t buf_len;
+	int ret = -1, i;
+	u8 resp_control = 0;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Failed to send DSCP response - not connected to AP");
+		return -1;
+	}
+
+	if (resp_data->solicited && !wpa_s->dscp_req_dialog_token) {
+		wpa_printf(MSG_ERROR, "QM: No ongoing DSCP request");
+		return -1;
+	}
+
+	if (!wpa_s->connection_dscp) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Failed to send DSCP response - DSCP capability not enabled for the current association");
+		return -1;
+
+	}
+
+	buf_len = 1 +	/* Category */
+		  3 +	/* OUI */
+		  1 +	/* OUI Type */
+		  1 +	/* OUI Subtype */
+		  1 +	/* Dialog Token */
+		  1 +	/* Response Control */
+		  1 +	/* Count */
+		  2 * resp_data->num_policies;  /* Status list */
+	buf = wpabuf_alloc(buf_len);
+	if (!buf) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Failed to allocate DSCP policy response");
+		return -1;
+	}
+
+	wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED);
+	wpabuf_put_be24(buf, OUI_WFA);
+	wpabuf_put_u8(buf, QM_ACTION_OUI_TYPE);
+	wpabuf_put_u8(buf, QM_DSCP_POLICY_RESP);
+
+	wpabuf_put_u8(buf, resp_data->solicited ?
+		      wpa_s->dscp_req_dialog_token : 0);
+
+	if (resp_data->more)
+		resp_control |= DSCP_POLICY_CTRL_MORE;
+	if (resp_data->reset)
+		resp_control |= DSCP_POLICY_CTRL_RESET;
+	wpabuf_put_u8(buf, resp_control);
+
+	wpabuf_put_u8(buf, resp_data->num_policies);
+	for (i = 0; i < resp_data->num_policies; i++) {
+		wpabuf_put_u8(buf, resp_data->policy[i].id);
+		wpabuf_put_u8(buf, resp_data->policy[i].status);
+	}
+
+	wpa_hexdump_buf(MSG_MSGDUMP, "DSCP response frame: ", buf);
+	ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				  wpa_s->own_addr, wpa_s->bssid,
+				  wpabuf_head(buf), wpabuf_len(buf), 0);
+	if (ret < 0) {
+		wpa_msg(wpa_s, MSG_INFO, "QM: Failed to send DSCP response");
+		goto fail;
+	}
+
+	/*
+	 * Mark DSCP request complete whether response sent is solicited or
+	 * unsolicited
+	 */
+	wpa_s->dscp_req_dialog_token = 0;
+
+fail:
+	wpabuf_free(buf);
+	return ret;
+}
+
+
+int wpas_send_dscp_query(struct wpa_supplicant *wpa_s, const char *domain_name,
+			 size_t domain_name_length)
+{
+	struct wpabuf *buf = NULL;
+	int ret, dscp_query_size;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
+		return -1;
+
+	if (!wpa_s->connection_dscp) {
+		wpa_printf(MSG_ERROR,
+			   "QM: Failed to send DSCP query - DSCP capability not enabled for the current association");
+		return -1;
+	}
+
+	if (wpa_s->wait_for_dscp_req) {
+		wpa_printf(MSG_INFO, "QM: Wait until AP sends a DSCP request");
+		return -1;
+	}
+
+#define DOMAIN_NAME_OFFSET (4 /* OUI */ + 1 /* Attr Id */ + 1 /* Attr len */)
+
+	if (domain_name_length > 255 - DOMAIN_NAME_OFFSET) {
+		wpa_printf(MSG_ERROR, "QM: Too long domain name");
+		return -1;
+	}
+
+	dscp_query_size = 1 + /* Category */
+			  4 + /* OUI Type */
+			  1 + /* OUI subtype */
+			  1; /* Dialog Token */
+	if (domain_name && domain_name_length)
+		dscp_query_size += 1 + /* Element ID */
+			1 + /* IE Length */
+			DOMAIN_NAME_OFFSET + domain_name_length;
+
+	buf = wpabuf_alloc(dscp_query_size);
+	if (!buf) {
+		wpa_printf(MSG_ERROR, "QM: Failed to allocate DSCP query");
+		return -1;
+	}
+
+	wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED);
+	wpabuf_put_be32(buf, QM_ACTION_VENDOR_TYPE);
+	wpabuf_put_u8(buf, QM_DSCP_POLICY_QUERY);
+	wpa_s->dscp_query_dialog_token++;
+	if (wpa_s->dscp_query_dialog_token == 0)
+		wpa_s->dscp_query_dialog_token++;
+	wpabuf_put_u8(buf, wpa_s->dscp_query_dialog_token);
+
+	if (domain_name && domain_name_length) {
+		/* Domain Name attribute */
+		wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+		wpabuf_put_u8(buf, DOMAIN_NAME_OFFSET + domain_name_length);
+		wpabuf_put_be32(buf, QM_IE_VENDOR_TYPE);
+		wpabuf_put_u8(buf, QM_ATTR_DOMAIN_NAME);
+		wpabuf_put_u8(buf, domain_name_length);
+		wpabuf_put_data(buf, domain_name, domain_name_length);
+	}
+#undef DOMAIN_NAME_OFFSET
+
+	ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				  wpa_s->own_addr, wpa_s->bssid,
+				  wpabuf_head(buf), wpabuf_len(buf), 0);
+	if (ret < 0) {
+		wpa_dbg(wpa_s, MSG_ERROR, "QM: Failed to send DSCP query");
+		wpa_s->dscp_query_dialog_token--;
+	}
+
+	wpabuf_free(buf);
+	return ret;
+}
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 24d06c0..dde2f44 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -392,6 +392,29 @@
 }
 
 
+#ifdef CONFIG_P2P
+static bool is_6ghz_supported(struct wpa_supplicant *wpa_s)
+{
+	struct hostapd_channel_data *chnl;
+	int i, j;
+
+	for (i = 0; i < wpa_s->hw.num_modes; i++) {
+		if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A) {
+			chnl = wpa_s->hw.modes[i].channels;
+			for (j = 0; j < wpa_s->hw.modes[i].num_channels; j++) {
+				if (chnl[j].flag & HOSTAPD_CHAN_DISABLED)
+					continue;
+				if (is_6ghz_freq(chnl[j].freq))
+					return true;
+			}
+		}
+	}
+
+	return false;
+}
+#endif /* CONFIG_P2P */
+
+
 static void wpa_supplicant_optimize_freqs(
 	struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params)
 {
@@ -729,13 +752,13 @@
 
 	if (wpa_s->setband_mask & WPA_SETBAND_5G)
 		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
-					0);
+					false);
 	if (wpa_s->setband_mask & WPA_SETBAND_2G)
 		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
-					0);
+					false);
 	if (wpa_s->setband_mask & WPA_SETBAND_6G)
 		wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
-					1);
+					true);
 }
 
 
@@ -1350,6 +1373,34 @@
 			}
 		}
 	}
+
+	if (!params.freqs &&
+	    (wpa_s->p2p_in_invitation || wpa_s->p2p_in_provisioning) &&
+	    !is_p2p_allow_6ghz(wpa_s->global->p2p) &&
+	    is_6ghz_supported(wpa_s)) {
+		int i;
+
+		/* Exclude 5 GHz channels from the full scan for P2P connection
+		 * since the 6 GHz band is disabled for P2P uses. */
+		wpa_printf(MSG_DEBUG,
+			   "P2P: 6 GHz disabled - update the scan frequency list");
+		for (i = 0; i < wpa_s->hw.num_modes; i++) {
+			if (wpa_s->hw.modes[i].num_channels == 0)
+				continue;
+			if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211G)
+				wpa_add_scan_freqs_list(
+					wpa_s, HOSTAPD_MODE_IEEE80211G,
+					&params, false);
+			if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211A)
+				wpa_add_scan_freqs_list(
+					wpa_s, HOSTAPD_MODE_IEEE80211A,
+					&params, false);
+			if (wpa_s->hw.modes[i].mode == HOSTAPD_MODE_IEEE80211AD)
+				wpa_add_scan_freqs_list(
+					wpa_s, HOSTAPD_MODE_IEEE80211AD,
+					&params, false);
+		}
+	}
 #endif /* CONFIG_P2P */
 
 	ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
@@ -2052,14 +2103,22 @@
 		snr_b = snr_b_full = wb->level;
 	}
 
-	/* if SNR is close, decide by max rate or frequency band */
-	if (snr_a && snr_b && abs(snr_b - snr_a) < 7) {
+	/* If SNR is close, decide by max rate or frequency band. For cases
+	 * involving the 6 GHz band, use the throughput estimate irrespective
+	 * of the SNR difference since the LPI/VLP rules may result in
+	 * significant differences in SNR for cases where the estimated
+	 * throughput can be considerably higher with the lower SNR. */
+	if (snr_a && snr_b && (abs(snr_b - snr_a) < 7 ||
+			       is_6ghz_freq(wa->freq) ||
+			       is_6ghz_freq(wb->freq))) {
 		if (wa->est_throughput != wb->est_throughput)
 			return (int) wb->est_throughput -
 				(int) wa->est_throughput;
 	}
 	if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) ||
 	    (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
+		if (is_6ghz_freq(wa->freq) ^ is_6ghz_freq(wb->freq))
+			return is_6ghz_freq(wa->freq) ? -1 : 1;
 		if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq))
 			return IS_5GHZ(wa->freq) ? -1 : 1;
 	}
@@ -2220,9 +2279,10 @@
 void scan_snr(struct wpa_scan_res *res)
 {
 	if (res->flags & WPA_SCAN_NOISE_INVALID) {
-		res->noise = IS_5GHZ(res->freq) ?
-			DEFAULT_NOISE_FLOOR_5GHZ :
-			DEFAULT_NOISE_FLOOR_2GHZ;
+		res->noise = is_6ghz_freq(res->freq) ?
+			DEFAULT_NOISE_FLOOR_6GHZ :
+			(IS_5GHZ(res->freq) ?
+			 DEFAULT_NOISE_FLOOR_5GHZ : DEFAULT_NOISE_FLOOR_2GHZ);
 	}
 
 	if (res->flags & WPA_SCAN_LEVEL_DBM) {
@@ -2289,6 +2349,92 @@
 };
 
 
+static const struct minsnr_bitrate_entry vht160_table[] = {
+	{ 0, 0 },
+	{ 11, 58500 },  /* VHT160 MCS0 */
+	{ 14, 117000 }, /* VHT160 MCS1 */
+	{ 18, 175500 }, /* VHT160 MCS2 */
+	{ 20, 234000 }, /* VHT160 MCS3 */
+	{ 24, 351000 }, /* VHT160 MCS4 */
+	{ 27, 468000 }, /* VHT160 MCS5 */
+	{ 29, 526500 }, /* VHT160 MCS6 */
+	{ 34, 585000 }, /* VHT160 MCS7 */
+	{ 38, 702000 }, /* VHT160 MCS8 */
+	{ 40, 780000 }, /* VHT160 MCS9 */
+	{ -1, 780000 }  /* SNR > 37 */
+};
+
+
+static const struct minsnr_bitrate_entry he20_table[] = {
+	{ 0, 0 },
+	{ 2, 8600 },    /* HE20 MCS0 */
+	{ 5, 17200 },   /* HE20 MCS1 */
+	{ 9, 25800 },   /* HE20 MCS2 */
+	{ 11, 34400 },  /* HE20 MCS3 */
+	{ 15, 51600 },  /* HE20 MCS4 */
+	{ 18, 68800 },  /* HE20 MCS5 */
+	{ 20, 77400 },  /* HE20 MCS6 */
+	{ 25, 86000 },  /* HE20 MCS7 */
+	{ 29, 103200 }, /* HE20 MCS8 */
+	{ 31, 114700 }, /* HE20 MCS9 */
+	{ 34, 129000 }, /* HE20 MCS10 */
+	{ 36, 143400 }, /* HE20 MCS11 */
+	{ -1, 143400 }  /* SNR > 29 */
+};
+
+static const struct minsnr_bitrate_entry he40_table[] = {
+	{ 0, 0 },
+	{ 5, 17200 },   /* HE40 MCS0 */
+	{ 8, 34400 },   /* HE40 MCS1 */
+	{ 12, 51600 },  /* HE40 MCS2 */
+	{ 14, 68800 },  /* HE40 MCS3 */
+	{ 18, 103200 }, /* HE40 MCS4 */
+	{ 21, 137600 }, /* HE40 MCS5 */
+	{ 23, 154900 }, /* HE40 MCS6 */
+	{ 28, 172100 }, /* HE40 MCS7 */
+	{ 32, 206500 }, /* HE40 MCS8 */
+	{ 34, 229400 }, /* HE40 MCS9 */
+	{ 37, 258100 }, /* HE40 MCS10 */
+	{ 39, 286800 }, /* HE40 MCS11 */
+	{ -1, 286800 }  /* SNR > 34 */
+};
+
+static const struct minsnr_bitrate_entry he80_table[] = {
+	{ 0, 0 },
+	{ 8, 36000 },   /* HE80 MCS0 */
+	{ 11, 72100 },  /* HE80 MCS1 */
+	{ 15, 108100 }, /* HE80 MCS2 */
+	{ 17, 144100 }, /* HE80 MCS3 */
+	{ 21, 216200 }, /* HE80 MCS4 */
+	{ 24, 288200 }, /* HE80 MCS5 */
+	{ 26, 324300 }, /* HE80 MCS6 */
+	{ 31, 360300 }, /* HE80 MCS7 */
+	{ 35, 432400 }, /* HE80 MCS8 */
+	{ 37, 480400 }, /* HE80 MCS9 */
+	{ 40, 540400 }, /* HE80 MCS10 */
+	{ 42, 600500 }, /* HE80 MCS11 */
+	{ -1, 600500 }  /* SNR > 37 */
+};
+
+
+static const struct minsnr_bitrate_entry he160_table[] = {
+	{ 0, 0 },
+	{ 11, 72100 },   /* HE160 MCS0 */
+	{ 14, 144100 },  /* HE160 MCS1 */
+	{ 18, 216200 },  /* HE160 MCS2 */
+	{ 20, 288200 },  /* HE160 MCS3 */
+	{ 24, 432400 },  /* HE160 MCS4 */
+	{ 27, 576500 },  /* HE160 MCS5 */
+	{ 29, 648500 },  /* HE160 MCS6 */
+	{ 34, 720600 },  /* HE160 MCS7 */
+	{ 38, 864700 },  /* HE160 MCS8 */
+	{ 40, 960800 },  /* HE160 MCS9 */
+	{ 43, 1080900 }, /* HE160 MCS10 */
+	{ 45, 1201000 }, /* HE160 MCS11 */
+	{ -1, 1201000 }  /* SNR > 37 */
+};
+
+
 static unsigned int interpolate_rate(int snr, int snr0, int snr1,
 				     int rate0, int rate1)
 {
@@ -2333,11 +2479,34 @@
 }
 
 
+static unsigned int max_vht160_rate(int snr)
+{
+	return max_rate(vht160_table, snr, 1);
+}
+
+
+static unsigned int max_he_rate(const struct minsnr_bitrate_entry table[],
+				int snr)
+{
+	const struct minsnr_bitrate_entry *prev, *entry = table;
+
+	while (entry->minsnr != -1 && snr >= entry->minsnr)
+		entry++;
+	if (entry == table)
+		return 0;
+	prev = entry - 1;
+	if (entry->minsnr == -1)
+		return prev->bitrate;
+	return interpolate_rate(snr, prev->minsnr, entry->minsnr,
+				prev->bitrate, entry->bitrate);
+}
+
+
 unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			      const u8 *ies, size_t ies_len, int rate,
-			      int snr)
+			      int snr, int freq)
 {
-	enum local_hw_capab capab = wpa_s->hw_capab;
+	struct hostapd_hw_modes *hw_mode;
 	unsigned int est, tmp;
 	const u8 *ie;
 
@@ -2382,7 +2551,10 @@
 		rate = 54 * 2;
 	est = rate * 500;
 
-	if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) {
+	hw_mode = get_mode_with_freq(wpa_s->hw.modes, wpa_s->hw.num_modes,
+				     freq);
+
+	if (hw_mode && hw_mode->ht_capab) {
 		ie = get_ie(ies, ies_len, WLAN_EID_HT_CAP);
 		if (ie) {
 			tmp = max_ht20_rate(snr, false);
@@ -2391,7 +2563,8 @@
 		}
 	}
 
-	if (capab == CAPAB_HT40 || capab == CAPAB_VHT) {
+	if (hw_mode &&
+	    (hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
 		ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION);
 		if (ie && ie[1] >= 2 &&
 		    (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) {
@@ -2401,10 +2574,12 @@
 		}
 	}
 
-	if (capab == CAPAB_VHT) {
+	if (hw_mode && hw_mode->vht_capab) {
 		/* Use +1 to assume VHT is always faster than HT */
 		ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP);
 		if (ie) {
+			bool vht80 = false, vht160 = false;
+
 			tmp = max_ht20_rate(snr, true) + 1;
 			if (tmp > est)
 				est = tmp;
@@ -2418,13 +2593,82 @@
 					est = tmp;
 			}
 
+			/* Determine VHT BSS bandwidth based on IEEE Std
+			 * 802.11-2020, Table 11-23 (VHT BSs bandwidth) */
 			ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION);
-			if (ie && ie[1] >= 1 &&
-			    (ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK)) {
+			if (ie && ie[1] >= 3) {
+				u8 cw = ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK;
+				u8 seg0 = ie[3];
+				u8 seg1 = ie[4];
+
+				if (cw)
+					vht80 = true;
+				if (cw == 2 ||
+				    (cw == 3 &&
+				     (seg1 > 0 && abs(seg1 - seg0) == 16)))
+					vht160 = true;
+				if (cw == 1 &&
+				    ((seg1 > 0 && abs(seg1 - seg0) == 8) ||
+				     (seg1 > 0 && abs(seg1 - seg0) == 16)))
+					vht160 = true;
+			}
+
+			if (vht80) {
 				tmp = max_vht80_rate(snr) + 1;
 				if (tmp > est)
 					est = tmp;
 			}
+
+			if (vht160 &&
+			    (hw_mode->vht_capab &
+			     (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+			      VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
+				tmp = max_vht160_rate(snr) + 1;
+				if (tmp > est)
+					est = tmp;
+			}
+		}
+	}
+
+	if (hw_mode && hw_mode->he_capab[IEEE80211_MODE_INFRA].he_supported) {
+		/* Use +2 to assume HE is always faster than HT/VHT */
+		struct ieee80211_he_capabilities *he;
+		struct he_capabilities *own_he;
+		u8 cw;
+
+		ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_HE_CAPABILITIES);
+		if (!ie || (ie[1] < 1 + IEEE80211_HE_CAPAB_MIN_LEN))
+			return est;
+		he = (struct ieee80211_he_capabilities *) &ie[3];
+		own_he = &hw_mode->he_capab[IEEE80211_MODE_INFRA];
+
+		tmp = max_he_rate(he20_table, snr) + 2;
+		if (tmp > est)
+			est = tmp;
+
+		cw = he->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+			own_he->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
+		if (cw &
+		    (IS_2P4GHZ(freq) ? HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G :
+		     HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
+			tmp = max_he_rate(he40_table, snr) + 2;
+			if (tmp > est)
+				est = tmp;
+		}
+
+		if (!IS_2P4GHZ(freq) &&
+		    (cw & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) {
+			tmp = max_he_rate(he80_table, snr) + 2;
+			if (tmp > est)
+				est = tmp;
+		}
+
+		if (!IS_2P4GHZ(freq) &&
+		    (cw & (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
+			   HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G))) {
+			tmp = max_he_rate(he160_table, snr) + 2;
+			if (tmp > est)
+				est = tmp;
 		}
 	}
 
@@ -2449,7 +2693,7 @@
 	if (!ie_len)
 		ie_len = res->beacon_ie_len;
 	res->est_throughput =
-		wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr);
+		wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr, res->freq);
 
 	/* TODO: channel utilization and AP load (e.g., from AP Beacon) */
 }
@@ -2670,6 +2914,7 @@
 	params->relative_rssi = src->relative_rssi;
 	params->relative_adjust_band = src->relative_adjust_band;
 	params->relative_adjust_rssi = src->relative_adjust_rssi;
+	params->p2p_include_6ghz = src->p2p_include_6ghz;
 	return params;
 
 failed:
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index 8eb5c73..d1780eb 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -16,6 +16,7 @@
  */
 #define DEFAULT_NOISE_FLOOR_2GHZ (-89)
 #define DEFAULT_NOISE_FLOOR_5GHZ (-92)
+#define DEFAULT_NOISE_FLOOR_6GHZ (-92)
 
 /*
  * Channels with a great SNR can operate at full rate. What is a great SNR?
@@ -29,7 +30,8 @@
  */
 #define GREAT_SNR 25
 
-#define IS_5GHZ(n) (n > 4000)
+#define IS_2P4GHZ(n) (n >= 2412 && n <= 2484)
+#define IS_5GHZ(n) (n > 4000 && n < 5895)
 
 int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec);
@@ -84,7 +86,7 @@
 			 struct wpa_scan_res *res);
 unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 			      const u8 *ies, size_t ies_len, int rate,
-			      int snr);
+			      int snr, int freq);
 void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
 int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
 			    enum hostapd_hw_mode band,
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 36f4d3c..0b02f75 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -13,7 +13,6 @@
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/ocv.h"
-#include "common/hw_features_common.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "common/wpa_common.h"
 #include "common/sae.h"
@@ -138,6 +137,12 @@
 	}
 
 	bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+	if (!bss) {
+		wpa_printf(MSG_DEBUG,
+			   "SAE: BSS not available, update scan result to get BSS");
+		wpa_supplicant_update_scan_results(wpa_s);
+		bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+	}
 	if (bss) {
 		const u8 *rsnxe;
 
@@ -186,7 +191,6 @@
 	if (!use_pt &&
 	    sae_prepare_commit(wpa_s->own_addr, bssid,
 			       (u8 *) password, os_strlen(password),
-			       ssid->sae_password_id,
 			       &wpa_s->sme.sae) < 0) {
 		wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
 		return NULL;
@@ -663,7 +667,11 @@
 	}
 
 #ifdef CONFIG_HS20
-	if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
+	if (is_hs20_network(wpa_s, ssid, bss)
+#ifndef ANDROID /* Android does not use the native HS 2.0 config */
+			&& is_hs20_config(wpa_s)
+#endif /* ANDROID */
+	) {
 		struct wpabuf *hs20;
 
 		hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
@@ -941,6 +949,11 @@
 	struct wpa_connect_work *cwork = work->ctx;
 	struct wpa_supplicant *wpa_s = work->wpa_s;
 
+	wpa_s->roam_in_progress = false;
+#ifdef CONFIG_WNM
+	wpa_s->bss_trans_mgmt_in_progress = false;
+#endif /* CONFIG_WNM */
+
 	if (deinit) {
 		if (work->started)
 			wpa_s->connect_work = NULL;
@@ -981,6 +994,18 @@
 		return;
 	}
 
+	if (wpa_s->roam_in_progress) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"SME: Reject sme_authenticate() in favor of explicit roam request");
+		return;
+	}
+#ifdef CONFIG_WNM
+	if (wpa_s->bss_trans_mgmt_in_progress) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"SME: Reject sme_authenticate() in favor of BSS transition management request");
+		return;
+	}
+#endif /* CONFIG_WNM */
 	if (radio_work_pending(wpa_s, "sme-connect")) {
 		/*
 		 * The previous sme-connect work might no longer be valid due to
@@ -1334,8 +1359,15 @@
 
 	if (status_code != WLAN_STATUS_SUCCESS &&
 	    status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
-	    status_code != WLAN_STATUS_SAE_PK)
+	    status_code != WLAN_STATUS_SAE_PK) {
+		const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
+
+		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
+			" auth_type=%u auth_transaction=%u status_code=%u",
+			MAC2STR(bssid), WLAN_AUTH_SAE,
+			auth_transaction, status_code);
 		return -1;
+	}
 
 	if (auth_transaction == 1) {
 		u16 res;
@@ -1536,7 +1568,7 @@
 		int res;
 		res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
 				   data->auth.status_code, data->auth.ies,
-				   data->auth.ies_len, 0, NULL);
+				   data->auth.ies_len, 0, data->auth.peer);
 		if (res < 0) {
 			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
@@ -2367,14 +2399,13 @@
 }
 
 
-int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
-		       struct wpa_scan_results *scan_res)
+int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
 {
+	struct wpa_bss *bss;
 	const u8 *ie;
+	u16 ht_cap;
 	u8 chan_list[P2P_MAX_CHANNELS], channel;
 	u8 num_channels = 0, num_intol = 0, i;
-	size_t j;
-	int pri_freq, sec_freq;
 
 	if (!wpa_s->sme.sched_obss_scan)
 		return 0;
@@ -2402,36 +2433,22 @@
 
 	os_memset(chan_list, 0, sizeof(chan_list));
 
-	pri_freq = wpa_s->assoc_freq;
-
-	switch (wpa_s->sme.ht_sec_chan) {
-	case HT_SEC_CHAN_ABOVE:
-		sec_freq = pri_freq + 20;
-		break;
-	case HT_SEC_CHAN_BELOW:
-		sec_freq = pri_freq - 20;
-		break;
-	case HT_SEC_CHAN_UNKNOWN:
-	default:
-		wpa_msg(wpa_s, MSG_WARNING,
-			"Undefined secondary channel: drop OBSS scan results");
-		return 1;
-	}
-
-	for (j = 0; j < scan_res->num; j++) {
-		struct wpa_scan_res *bss = scan_res->res[j];
-		enum hostapd_hw_mode mode;
-		int res;
-
+	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
 		/* Skip other band bss */
+		enum hostapd_hw_mode mode;
 		mode = ieee80211_freq_to_chan(bss->freq, &channel);
 		if (mode != HOSTAPD_MODE_IEEE80211G &&
 		    mode != HOSTAPD_MODE_IEEE80211B)
 			continue;
 
-		res = check_bss_coex_40mhz(bss, pri_freq, sec_freq);
-		if (res) {
-			if (res == 2)
+		ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
+		ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
+		wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
+			   " freq=%u chan=%u ht_cap=0x%x",
+			   MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
+
+		if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
+			if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
 				num_intol++;
 
 			/* Check whether the channel is already considered */
@@ -2570,6 +2587,12 @@
 	    ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
 		return;
 
+#ifdef CONFIG_HT_OVERRIDES
+	/* No need for OBSS scan if HT40 is explicitly disabled */
+	if (ssid->disable_ht40)
+		return;
+#endif /* CONFIG_HT_OVERRIDES */
+
 	if (!wpa_s->hw.modes)
 		return;
 
@@ -2883,11 +2906,17 @@
 }
 
 
-void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
+void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
 		     const u8 *data, size_t len)
 {
 	if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
 		return;
+	if (is_multicast_ether_addr(da)) {
+		wpa_printf(MSG_DEBUG,
+			   "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
+			   MAC2STR(da), MAC2STR(sa));
+		return;
+	}
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
 		MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index 42d5a83..c797d2e 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -29,7 +29,7 @@
 void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
 				 const u8 *da, u16 reason_code);
 void sme_event_ch_switch(struct wpa_supplicant *wpa_s);
-void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
+void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
 		     const u8 *data, size_t len);
 void sme_state_changed(struct wpa_supplicant *wpa_s);
 void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
@@ -37,8 +37,7 @@
 void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s);
 void sme_deinit(struct wpa_supplicant *wpa_s);
 
-int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
-		       struct wpa_scan_results *scan_res);
+int sme_proc_obss_scan(struct wpa_supplicant *wpa_s);
 void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable);
 void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
 			       union wpa_event_data *data);
@@ -113,8 +112,7 @@
 {
 }
 
-static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
-				     struct wpa_scan_results *scan_res)
+static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
 {
 	return 0;
 }
diff --git a/wpa_supplicant/systemd/wpa_supplicant.service.in b/wpa_supplicant/systemd/wpa_supplicant.service.in
index 75a37a8..58a6228 100644
--- a/wpa_supplicant/systemd/wpa_supplicant.service.in
+++ b/wpa_supplicant/systemd/wpa_supplicant.service.in
@@ -1,6 +1,7 @@
 [Unit]
 Description=WPA supplicant
 Before=network.target
+After=dbus.service
 Wants=network.target
 
 [Service]
diff --git a/wpa_supplicant/twt.c b/wpa_supplicant/twt.c
new file mode 100644
index 0000000..8ec2c85
--- /dev/null
+++ b/wpa_supplicant/twt.c
@@ -0,0 +1,142 @@
+/*
+ * wpa_supplicant - TWT
+ * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "utils/common.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+
+/**
+ * wpas_twt_send_setup - Send TWT Setup frame (Request) to our AP
+ * @wpa_s: Pointer to wpa_supplicant
+ * @dtok: Dialog token
+ * @exponent: Wake-interval exponent
+ * @mantissa: Wake-interval mantissa
+ * @min_twt: Minimum TWT wake duration in units of 256 usec
+ * @setup_cmd: 0 == request, 1 == suggest, etc.  Table 9-297
+ * Returns: 0 in case of success, negative error code otherwise
+ *
+ */
+int wpas_twt_send_setup(struct wpa_supplicant *wpa_s, u8 dtok, int exponent,
+			int mantissa, u8 min_twt, int setup_cmd, u64 twt,
+			bool requestor, bool trigger, bool implicit,
+			bool flow_type, u8 flow_id, bool protection,
+			u8 twt_channel, u8 control)
+{
+	struct wpabuf *buf;
+	u16 req_type = 0;
+	int ret = 0;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
+		wpa_printf(MSG_DEBUG,
+			   "TWT: No connection - cannot send TWT Setup frame");
+		return -ENOTCONN;
+	}
+
+	/* 3 = Action category + Action code + Dialog token */
+	/* 17 = TWT element */
+	buf = wpabuf_alloc(3 + 17);
+	if (!buf) {
+		wpa_printf(MSG_DEBUG,
+			   "TWT: Failed to allocate TWT Setup frame (Request)");
+		return -ENOMEM;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "TWT: Setup request, dtok: %d  exponent: %d  mantissa: %d  min-twt: %d",
+		   dtok, exponent, mantissa, min_twt);
+
+	wpabuf_put_u8(buf, WLAN_ACTION_S1G);
+	wpabuf_put_u8(buf, S1G_ACT_TWT_SETUP);
+	wpabuf_put_u8(buf, dtok);
+
+	wpabuf_put_u8(buf, WLAN_EID_TWT);
+	wpabuf_put_u8(buf, 15); /* len */
+
+	wpabuf_put_u8(buf, control);
+
+	if (requestor)
+		req_type |= BIT(0); /* This STA is a TWT Requesting STA */
+	/* TWT Setup Command field */
+	req_type |= (setup_cmd & 0x7) << 1;
+	if (trigger)
+		req_type |= BIT(4); /* TWT SP includes trigger frames */
+	if (implicit)
+		req_type |= BIT(5); /* Implicit TWT */
+	if (flow_type)
+		req_type |= BIT(6); /* Flow Type: Unannounced TWT */
+	req_type |= (flow_id & 0x7) << 7;
+	req_type |= (exponent & 0x1f) << 10; /* TWT Wake Interval Exponent */
+	if (protection)
+		req_type |= BIT(15);
+	wpabuf_put_le16(buf, req_type);
+	wpabuf_put_le64(buf, twt);
+	wpabuf_put_u8(buf, min_twt); /* Nominal Minimum TWT Wake Duration */
+	wpabuf_put_le16(buf, mantissa); /* TWT Wake Interval Mantissa */
+	wpabuf_put_u8(buf, twt_channel); /* TWT Channel */
+
+	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				wpa_s->own_addr, wpa_s->bssid,
+				wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
+		wpa_printf(MSG_DEBUG, "TWT: Failed to send TWT Setup Request");
+		ret = -ECANCELED;
+	}
+
+	wpabuf_free(buf);
+	return ret;
+}
+
+
+/**
+ * wpas_twt_send_teardown - Send TWT teardown request to our AP
+ * @wpa_s: Pointer to wpa_supplicant
+ * @flags: The byte that goes inside the TWT Teardown element
+ * Returns: 0 in case of success, negative error code otherwise
+ *
+ */
+int wpas_twt_send_teardown(struct wpa_supplicant *wpa_s, u8 flags)
+{
+	struct wpabuf *buf;
+	int ret = 0;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
+		wpa_printf(MSG_DEBUG,
+			   "TWT: No connection - cannot send TWT Teardown frame");
+		return -ENOTCONN;
+	}
+
+	/* 3 = Action category + Action code + flags */
+	buf = wpabuf_alloc(3);
+	if (!buf) {
+		wpa_printf(MSG_DEBUG,
+			   "TWT: Failed to allocate TWT Teardown frame");
+		return -ENOMEM;
+	}
+
+	wpa_printf(MSG_DEBUG, "TWT: Teardown request, flags: 0x%x", flags);
+
+	wpabuf_put_u8(buf, WLAN_ACTION_S1G);
+	wpabuf_put_u8(buf, S1G_ACT_TWT_TEARDOWN);
+	wpabuf_put_u8(buf, flags);
+
+	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+				wpa_s->own_addr, wpa_s->bssid,
+				wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
+		wpa_printf(MSG_DEBUG, "TWT: Failed to send TWT Teardown frame");
+		ret = -ECANCELED;
+	}
+
+	wpabuf_free(buf);
+	return ret;
+}
+
+#endif /* CONFIG_TESTING_OPTIONS */
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 155e8f4..4c7e6dc 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -1097,6 +1097,8 @@
 			       struct wpa_bss *bss, struct wpa_ssid *ssid,
 			       int after_new_scan)
 {
+	struct wpa_radio_work *already_connecting;
+
 	wpa_dbg(wpa_s, MSG_DEBUG,
 		"WNM: Transition to BSS " MACSTR
 		" based on BSS Transition Management Request (old BSSID "
@@ -1121,9 +1123,18 @@
 		return;
 	}
 
+	already_connecting = radio_work_pending(wpa_s, "sme-connect");
 	wpa_s->reassociate = 1;
 	wpa_printf(MSG_DEBUG, "WNM: Issuing connect");
 	wpa_supplicant_connect(wpa_s, bss, ssid);
+
+	/*
+	 * Indicate that a BSS transition is in progress so scan results that
+	 * come in before the 'sme-connect' radio work gets executed do not
+	 * override the original connection attempt.
+	 */
+	if (!already_connecting && radio_work_pending(wpa_s, "sme-connect"))
+		wpa_s->bss_trans_mgmt_in_progress = true;
 	wnm_deallocate_memory(wpa_s);
 }
 
@@ -1343,11 +1354,11 @@
 				continue;
 			bss = wpa_s->current_bss;
 			ssid_ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
-			if (bss && ssid_ie &&
+			if (bss && ssid_ie && ssid_ie[1] &&
 			    (bss->ssid_len != ssid_ie[1] ||
 			     os_memcmp(bss->ssid, ssid_ie + 2,
 				       bss->ssid_len) != 0))
-				continue;
+				continue; /* Skip entries for other ESSs */
 
 			/* Potential candidate found */
 			found = 1;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index b98a833..033589f 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -29,7 +29,7 @@
 
 static const char *const wpa_cli_version =
 "wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi> and contributors";
 
 #define VENDOR_ELEM_FRAME_ID \
 	"  0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
@@ -499,6 +499,7 @@
 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
 		"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
 		"reassoc_same_bss_optim", "wps_priority",
+		"ap_assocresp_elements",
 #ifdef CONFIG_TESTING_OPTIONS
 		"ignore_auth_resp",
 #endif /* CONFIG_TESTING_OPTIONS */
@@ -1590,6 +1591,7 @@
 	"min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load",
 	"req_conn_capab", "ocsp", "sim_num", "realm", "username", "password",
 	"ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi",
+	"ca_cert_id", "cert_id", "key_id", "engine_id", "engine",
 	"milenage", "domain_suffix_match", "domain", "phase1", "phase2",
 	"roaming_consortium", "required_roaming_consortium", "excluded_ssid",
 	"roaming_partner", "provisioning_sp"
@@ -2037,6 +2039,13 @@
 	return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
 }
 
+
+static int wpa_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "UPDATE_BEACON");
+}
+
 #endif /* CONFIG_AP */
 
 
@@ -2926,6 +2935,20 @@
 }
 
 
+static int wpa_cli_cmd_twt_setup(struct wpa_ctrl *ctrl, int argc,
+				 char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "TWT_SETUP", 0, argc, argv);
+}
+
+
+static int wpa_cli_cmd_twt_teardown(struct wpa_ctrl *ctrl, int argc,
+				    char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "TWT_TEARDOWN", 0, argc, argv);
+}
+
+
 static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "ERP_FLUSH");
@@ -3196,9 +3219,40 @@
 	return wpa_cli_cmd(ctrl, "PTKSA_CACHE_LIST", 0, argc, argv);
 }
 
+
+static int wpa_cli_cmd_pasn_deauth(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "PASN_DEAUTH", 1, argc, argv);
+}
+
 #endif /* CONFIG_PASN */
 
 
+static int wpa_cli_cmd_mscs(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "MSCS", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_scs(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "SCS", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dscp_resp(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "DSCP_RESP", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dscp_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "DSCP_QUERY", 1, argc, argv);
+}
+
+
 enum wpa_cli_cmd_flags {
 	cli_cmd_flag_none		= 0x00,
 	cli_cmd_flag_sensitive		= 0x01
@@ -3542,6 +3596,9 @@
 	  "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
 	  " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
 	  " = CSA parameters" },
+	{ "update_beacon", wpa_cli_cmd_update_beacon, NULL,
+	  cli_cmd_flag_none,
+	  "= update Beacon frame contents"},
 #endif /* CONFIG_AP */
 	{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
 	  "= notification of suspend/hibernate" },
@@ -3805,6 +3862,14 @@
 	  wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
 	  "[ssid=<SSID>] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)"
 	},
+	{ "twt_setup",
+	  wpa_cli_cmd_twt_setup, NULL, cli_cmd_flag_none,
+	  "[dialog=<token>] [exponent=<exponent>] [mantissa=<mantissa>] [min_twt=<Min TWT>] [setup_cmd=<setup-cmd>] [twt=<u64>] [requestor=0|1] [trigger=0|1] [implicit=0|1] [flow_type=0|1] [flow_id=<3-bit-id>] [protection=0|1] [twt_channel=<twt chanel id>] [control=<control-u8>] = Send TWT Setup frame"
+	},
+	{ "twt_teardown",
+	  wpa_cli_cmd_twt_teardown, NULL, cli_cmd_flag_none,
+	  "[flags=<value>] = Send TWT Teardown frame"
+	},
 	{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
 	  "= flush ERP keys" },
 	{ "mac_rand_scan",
@@ -3891,7 +3956,22 @@
 	{ "ptksa_cache_list", wpa_cli_cmd_ptksa_cache_list, NULL,
 	  cli_cmd_flag_none,
 	  "= Get the PTKSA Cache" },
+	{ "pasn_deauth", wpa_cli_cmd_pasn_deauth, NULL,
+	  cli_cmd_flag_none,
+	  "bssid=<BSSID> = Remove PASN PTKSA state" },
 #endif /* CONFIG_PASN */
+	{ "mscs", wpa_cli_cmd_mscs, NULL,
+	  cli_cmd_flag_none,
+	  "<add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>] [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>] = Configure MSCS request" },
+	{ "scs", wpa_cli_cmd_scs, NULL,
+	  cli_cmd_flag_none,
+	  "[scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>] [classifier_type=<4|10>] [classifier params based on classifier type] [tclas_processing=<0|1>] [scs_id=<decimal number>] ... = Send SCS request" },
+	{ "dscp_resp", wpa_cli_cmd_dscp_resp, NULL,
+	  cli_cmd_flag_none,
+	  "<[reset]>/<[solicited] [policy_id=1 status=0...]> [more] = Send DSCP response" },
+	{ "dscp_query", wpa_cli_cmd_dscp_query, NULL,
+	  cli_cmd_flag_none,
+	  "wildcard/domain_name=<string> = Send DSCP Query" },
 	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
 };
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 3471b99..99af85e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant
- * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -71,7 +71,7 @@
 
 const char *const wpa_supplicant_version =
 "wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
 
 const char *const wpa_supplicant_license =
 "This software may be distributed under the terms of the BSD license.\n"
@@ -462,16 +462,22 @@
 }
 
 
+static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
+					    struct wpa_bss_tmp_disallowed *bss)
+{
+	eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
+	dl_list_del(&bss->list);
+	os_free(bss);
+}
+
+
 void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_bss_tmp_disallowed *bss, *prev;
 
 	dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
-			      struct wpa_bss_tmp_disallowed, list) {
-		eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
-		dl_list_del(&bss->list);
-		os_free(bss);
-	}
+			      struct wpa_bss_tmp_disallowed, list)
+		remove_bss_tmp_disallowed_entry(wpa_s, bss);
 }
 
 
@@ -738,6 +744,8 @@
 #ifdef CONFIG_PASN
 	wpas_pasn_auth_stop(wpa_s);
 #endif /* CONFIG_PASN */
+	wpas_scs_deinit(wpa_s);
+	wpas_dscp_deinit(wpa_s);
 }
 
 
@@ -1293,6 +1301,47 @@
 }
 
 
+void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
+				struct wpa_ssid *ssid, struct wpa_ie_data *ie)
+{
+	int sel;
+
+	sel = ie->mgmt_group_cipher;
+	if (ssid->group_mgmt_cipher)
+		sel &= ssid->group_mgmt_cipher;
+	if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
+	    !(ie->capabilities & WPA_CAPABILITY_MFPC))
+		sel = 0;
+	wpa_dbg(wpa_s, MSG_DEBUG,
+		"WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
+		ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
+	if (sel & WPA_CIPHER_AES_128_CMAC) {
+		wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WPA: using MGMT group cipher AES-128-CMAC");
+	} else if (sel & WPA_CIPHER_BIP_GMAC_128) {
+		wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WPA: using MGMT group cipher BIP-GMAC-128");
+	} else if (sel & WPA_CIPHER_BIP_GMAC_256) {
+		wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WPA: using MGMT group cipher BIP-GMAC-256");
+	} else if (sel & WPA_CIPHER_BIP_CMAC_256) {
+		wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"WPA: using MGMT group cipher BIP-CMAC-256");
+	} else {
+		wpa_s->mgmt_group_cipher = 0;
+		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
+	}
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
+			 wpa_s->mgmt_group_cipher);
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
+			 wpas_get_ssid_pmf(wpa_s, ssid));
+}
+
+
 /**
  * wpa_supplicant_set_suites - Set authentication and encryption parameters
  * @wpa_s: Pointer to wpa_supplicant data
@@ -1626,39 +1675,7 @@
 		return -1;
 	}
 
-	sel = ie.mgmt_group_cipher;
-	if (ssid->group_mgmt_cipher)
-		sel &= ssid->group_mgmt_cipher;
-	if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
-	    !(ie.capabilities & WPA_CAPABILITY_MFPC))
-		sel = 0;
-	wpa_dbg(wpa_s, MSG_DEBUG,
-		"WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
-		ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
-	if (sel & WPA_CIPHER_AES_128_CMAC) {
-		wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
-		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-			"AES-128-CMAC");
-	} else if (sel & WPA_CIPHER_BIP_GMAC_128) {
-		wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
-		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-			"BIP-GMAC-128");
-	} else if (sel & WPA_CIPHER_BIP_GMAC_256) {
-		wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
-		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-			"BIP-GMAC-256");
-	} else if (sel & WPA_CIPHER_BIP_CMAC_256) {
-		wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
-		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-			"BIP-CMAC-256");
-	} else {
-		wpa_s->mgmt_group_cipher = 0;
-		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
-	}
-	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
-			 wpa_s->mgmt_group_cipher);
-	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
-			 wpas_get_ssid_pmf(wpa_s, ssid));
+	wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
 #ifdef CONFIG_OCV
 	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
 	    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
@@ -1874,12 +1891,23 @@
 		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
 	}
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
+	    IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt)) {
+		wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
+		wpa_dbg(wpa_s, MSG_INFO,
+			"WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
+	}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
 	return 0;
 }
 
 
 static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
 {
+	bool scs = true, mscs = true;
+
 	*pos = 0x00;
 
 	switch (idx) {
@@ -1923,6 +1951,12 @@
 #endif /* CONFIG_MBO */
 		break;
 	case 6: /* Bits 48-55 */
+#ifdef CONFIG_TESTING_OPTIONS
+		if (wpa_s->disable_scs_support)
+			scs = false;
+#endif /* CONFIG_TESTING_OPTIONS */
+		if (scs)
+			*pos |= 0x40; /* Bit 54 - SCS */
 		break;
 	case 7: /* Bits 56-63 */
 		break;
@@ -1939,7 +1973,12 @@
 #endif /* CONFIG_FILS */
 		break;
 	case 10: /* Bits 80-87 */
-		*pos |= 0x20; /* Bit 85 - Mirrored SCS */
+#ifdef CONFIG_TESTING_OPTIONS
+		if (wpa_s->disable_mscs_support)
+			mscs = false;
+#endif /* CONFIG_TESTING_OPTIONS */
+		if (mscs)
+			*pos |= 0x20; /* Bit 85 - Mirrored SCS */
 		break;
 	}
 }
@@ -2228,9 +2267,11 @@
 	} else {
 #ifdef CONFIG_SAE
 		wpa_s_clear_sae_rejected(wpa_s);
-		wpa_s_setup_sae_pt(wpa_s->conf, ssid);
 #endif /* CONFIG_SAE */
 	}
+#ifdef CONFIG_SAE
+	wpa_s_setup_sae_pt(wpa_s->conf, ssid);
+#endif /* CONFIG_SAE */
 
 	if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
 		if (wpas_update_random_addr(wpa_s, rand_style) < 0)
@@ -2391,6 +2432,23 @@
 }
 
 
+static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
+{
+	int i;
+
+	for (i = channel; i < channel + 16; i += 4) {
+		struct hostapd_channel_data *chan;
+
+		chan = hw_get_channel_chan(mode, i, NULL);
+		if (!chan ||
+		    chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
+			return false;
+	}
+
+	return true;
+}
+
+
 void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
 			  const struct wpa_ssid *ssid,
 			  struct hostapd_freq_params *freq)
@@ -2400,7 +2458,10 @@
 	struct hostapd_hw_modes *mode = NULL;
 	int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
 			   184, 192 };
-	int vht80[] = { 36, 52, 100, 116, 132, 149 };
+	int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
+		       6035, 6115, 6195, 6275, 6355, 6435, 6515,
+		       6595, 6675, 6755, 6835, 6915, 6995 };
+	int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
 	struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
 	u8 channel;
 	int i, chan_idx, ht40 = -1, res, obss_scan = 1;
@@ -2408,7 +2469,7 @@
 	struct hostapd_freq_params vht_freq;
 	int chwidth, seg0, seg1;
 	u32 vht_caps = 0;
-	int is_24ghz;
+	bool is_24ghz, is_6ghz;
 
 	freq->freq = ssid->frequency;
 
@@ -2465,6 +2526,13 @@
 	is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
 		hw_mode == HOSTAPD_MODE_IEEE80211B;
 
+	/* HT/VHT and corresponding overrides are not applicable to 6 GHz.
+	 * However, HE is mandatory for 6 GHz.
+	 */
+	is_6ghz = is_6ghz_freq(freq->freq);
+	if (is_6ghz)
+		goto skip_to_6ghz;
+
 #ifdef CONFIG_HT_OVERRIDES
 	if (ssid->disable_ht) {
 		freq->ht_enabled = 0;
@@ -2592,8 +2660,6 @@
 	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
 		return;
 
-	vht_freq = *freq;
-
 #ifdef CONFIG_VHT_OVERRIDES
 	if (ssid->disable_vht) {
 		freq->vht_enabled = 0;
@@ -2601,46 +2667,67 @@
 	}
 #endif /* CONFIG_VHT_OVERRIDES */
 
+skip_to_6ghz:
+	vht_freq = *freq;
+
+	/* 6 GHz does not have VHT enabled, so allow that exception here. */
 	vht_freq.vht_enabled = vht_supported(mode);
-	if (!vht_freq.vht_enabled)
+	if (!vht_freq.vht_enabled && !is_6ghz)
 		return;
 
 	/* Enable HE with VHT for 5 GHz */
 	freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
 
 	/* setup center_freq1, bandwidth */
-	for (j = 0; j < ARRAY_SIZE(vht80); j++) {
-		if (freq->channel >= vht80[j] &&
-		    freq->channel < vht80[j] + 16)
+	for (j = 0; j < ARRAY_SIZE(bw80); j++) {
+		if (freq->freq >= bw80[j] &&
+		    freq->freq < bw80[j] + 80)
 			break;
 	}
 
-	if (j == ARRAY_SIZE(vht80))
+	if (j == ARRAY_SIZE(bw80) ||
+	    ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
 		return;
 
-	for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
-		struct hostapd_channel_data *chan;
-
-		chan = hw_get_channel_chan(mode, i, NULL);
-		if (!chan)
-			return;
-
-		/* Back to HT configuration if channel not usable */
-		if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
-			return;
-	}
+	/* Back to HT configuration if channel not usable */
+	if (!ibss_mesh_is_80mhz_avail(channel, mode))
+		return;
 
 	chwidth = CHANWIDTH_80MHZ;
-	seg0 = vht80[j] + 6;
+	seg0 = channel + 6;
 	seg1 = 0;
 
+	if ((mode->he_capab[ieee80211_mode].phy_cap[
+		     HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+	     HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
+		/* In 160 MHz, the initial four 20 MHz channels were validated
+		 * above; check the remaining four 20 MHz channels for the total
+		 * of 160 MHz bandwidth.
+		 */
+		if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
+			return;
+
+		for (j = 0; j < ARRAY_SIZE(bw160); j++) {
+			if (freq->freq == bw160[j]) {
+				chwidth = CHANWIDTH_160MHZ;
+				seg0 = channel + 14;
+				break;
+			}
+		}
+	}
+
 	if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
 		/* setup center_freq2, bandwidth */
-		for (k = 0; k < ARRAY_SIZE(vht80); k++) {
+		for (k = 0; k < ARRAY_SIZE(bw80); k++) {
 			/* Only accept 80 MHz segments separated by a gap */
-			if (j == k || abs(vht80[j] - vht80[k]) == 16)
+			if (j == k || abs(bw80[j] - bw80[k]) == 80)
 				continue;
-			for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
+
+			if (ieee80211_freq_to_chan(bw80[k], &channel) ==
+			    NUM_HOSTAPD_MODES)
+				return;
+
+			for (i = channel; i < channel + 16; i += 4) {
 				struct hostapd_channel_data *chan;
 
 				chan = hw_get_channel_chan(mode, i, NULL);
@@ -2654,9 +2741,10 @@
 
 				/* Found a suitable second segment for 80+80 */
 				chwidth = CHANWIDTH_80P80MHZ;
-				vht_caps |=
-					VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
-				seg1 = vht80[k] + 6;
+				if (!is_6ghz)
+					vht_caps |=
+						VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+				seg1 = channel + 6;
 			}
 
 			if (chwidth == CHANWIDTH_80P80MHZ)
@@ -2674,7 +2762,7 @@
 		}
 	} else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
 		chwidth = CHANWIDTH_USE_HT;
-		seg0 = vht80[j] + 2;
+		seg0 = channel + 2;
 #ifdef CONFIG_HT_OVERRIDES
 		if (ssid->disable_ht40)
 			seg0 = 0;
@@ -2794,6 +2882,54 @@
 #endif /* CONFIG_FILS */
 
 
+static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
+				  struct wpa_bss *bss,
+				  u8 *wpa_ie, size_t wpa_ie_len,
+				  size_t max_wpa_ie_len)
+{
+	struct wpabuf *wfa_ie = NULL;
+	u8 wfa_capa[1];
+	size_t wfa_ie_len, buf_len;
+
+	os_memset(wfa_capa, 0, sizeof(wfa_capa));
+	if (wpa_s->enable_dscp_policy_capa)
+		wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
+
+	if (!wfa_capa[0])
+		return wpa_ie_len;
+
+	/* Wi-Fi Alliance element */
+	buf_len = 1 +	/* Element ID */
+		  1 +	/* Length */
+		  3 +	/* OUI */
+		  1 +	/* OUI Type */
+		  1 +	/* Capabilities Length */
+		  sizeof(wfa_capa);	/* Capabilities */
+	wfa_ie = wpabuf_alloc(buf_len);
+	if (!wfa_ie)
+		return wpa_ie_len;
+
+	wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
+	wpabuf_put_u8(wfa_ie, buf_len - 2);
+	wpabuf_put_be24(wfa_ie, OUI_WFA);
+	wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
+	wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
+	wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
+
+	wfa_ie_len = wpabuf_len(wfa_ie);
+	if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
+		wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
+				wfa_ie);
+		os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
+			  wfa_ie_len);
+		wpa_ie_len += wfa_ie_len;
+	}
+
+	wpabuf_free(wfa_ie);
+	return wpa_ie_len;
+}
+
+
 static u8 * wpas_populate_assoc_ies(
 	struct wpa_supplicant *wpa_s,
 	struct wpa_bss *bss, struct wpa_ssid *ssid,
@@ -3046,7 +3182,11 @@
 	}
 
 #ifdef CONFIG_HS20
-	if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
+	if (is_hs20_network(wpa_s, ssid, bss)
+#ifndef ANDROID /* Android does not use the native HS 2.0 config */
+			&& is_hs20_config(wpa_s)
+#endif /* ANDROID */
+	) {
 		struct wpabuf *hs20;
 
 		hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
@@ -3235,6 +3375,10 @@
 		wpa_ie_len += wpa_s->rsnxe_len;
 	}
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (wpa_s->disable_mscs_support)
+		goto mscs_end;
+#endif /* CONFIG_TESTING_OPTIONS */
 	if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
 	    wpa_s->robust_av.valid_config) {
 		struct wpabuf *mscs_ie;
@@ -3250,7 +3394,7 @@
 		if (!mscs_ie) {
 			wpa_printf(MSG_INFO,
 				   "MSCS: Failed to allocate MSCS IE");
-			goto mscs_fail;
+			goto mscs_end;
 		}
 
 		wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
@@ -3264,7 +3408,10 @@
 
 		wpabuf_free(mscs_ie);
 	}
-mscs_fail:
+mscs_end:
+
+	wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
+					    max_wpa_ie_len);
 
 	if (ssid->multi_ap_backhaul_sta) {
 		size_t multi_ap_ie_len;
@@ -3325,13 +3472,11 @@
 	if (!wpa_ie)
 		return;
 
-	if (params.auth_alg != WPA_AUTH_ALG_FILS) {
-		os_free(wpa_ie);
-		return;
+	if (params.auth_alg == WPA_AUTH_ALG_FILS) {
+		wpa_s->auth_alg = params.auth_alg;
+		wpa_drv_update_connect_params(wpa_s, &params, mask);
 	}
 
-	wpa_s->auth_alg = params.auth_alg;
-	wpa_drv_update_connect_params(wpa_s, &params, mask);
 	os_free(wpa_ie);
 }
 #endif /* CONFIG_FILS && IEEE8021X_EAPOL */
@@ -3502,6 +3647,11 @@
        struct ieee80211_vht_capabilities vhtcaps_mask;
 #endif /* CONFIG_VHT_OVERRIDES */
 
+	wpa_s->roam_in_progress = false;
+#ifdef CONFIG_WNM
+	wpa_s->bss_trans_mgmt_in_progress = false;
+#endif /* CONFIG_WNM */
+
 	if (deinit) {
 		if (work->started) {
 			wpa_s->connect_work = NULL;
@@ -3574,6 +3724,7 @@
 		wpa_s->scan_req = MANUAL_SCAN_REQ;
 		wpa_s->reassociate = 1;
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
+		os_free(wpa_ie);
 		return;
 #endif /* CONFIG_WPS */
 	} else {
@@ -3762,7 +3913,12 @@
 #endif /* CONFIG_WEP */
 
 	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
-	    (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+	    (
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	     (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
+#else
+	     params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 	     params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
 		params.passphrase = ssid->passphrase;
 		if (ssid->psk_set)
@@ -3787,7 +3943,12 @@
 		else
 			params.req_key_mgmt_offload = 1;
 
-		if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+		if ((
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+		     (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
+#else
+		     params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 		     params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
 		     params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
 		    ssid->psk_set)
@@ -3876,7 +4037,7 @@
 	if (ret < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
 			"failed");
-		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
+		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
 			/*
 			 * The driver is known to mean what is saying, so we
 			 * can stop right here; the association will not
@@ -3971,6 +4132,9 @@
 	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
 	if (old_ssid != wpa_s->current_ssid)
 		wpas_notify_network_changed(wpa_s);
+
+	wpas_scs_deinit(wpa_s);
+	wpas_dscp_deinit(wpa_s);
 	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
 }
 
@@ -4392,6 +4556,82 @@
 
 
 /**
+ * wpas_remove_cred - Remove the specified credential and all the network
+ * entries created based on the removed credential
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @cred: The credential to remove
+ * Returns: 0 on success, -1 on failure
+ */
+int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
+{
+	struct wpa_ssid *ssid, *next;
+	int id;
+
+	if (!cred) {
+		wpa_printf(MSG_DEBUG, "Could not find cred");
+		return -1;
+	}
+
+	id = cred->id;
+	if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
+		wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
+		return -1;
+	}
+
+	wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
+
+	/* Remove any network entry created based on the removed credential */
+	ssid = wpa_s->conf->ssid;
+	while (ssid) {
+		next = ssid->next;
+
+		if (ssid->parent_cred == cred) {
+			wpa_printf(MSG_DEBUG,
+				   "Remove network id %d since it used the removed credential",
+				   ssid->id);
+			if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
+			    -1) {
+				wpa_printf(MSG_DEBUG,
+					   "Could not find network id=%d",
+					   ssid->id);
+			}
+		}
+
+		ssid = next;
+	}
+
+	return 0;
+}
+
+
+/**
+ * wpas_remove_cred - Remove all the Interworking credentials
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: 0 on success, -1 on failure
+ */
+int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
+{
+	int res, ret = 0;
+	struct wpa_cred *cred, *prev;
+
+	cred = wpa_s->conf->cred;
+	while (cred) {
+		prev = cred;
+		cred = cred->next;
+		res = wpas_remove_cred(wpa_s, prev);
+		if (res < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "Removal of all credentials failed - failed to remove credential id=%d",
+				   prev->id);
+			ret = -1;
+		}
+	}
+
+	return ret;
+}
+
+
+/**
  * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
  * @wpa_s: wpa_supplicant structure for a network interface
  * @pkcs11_engine_path: PKCS #11 engine path or NULL
@@ -4738,8 +4978,13 @@
 	}
 
 	if (name == NULL) {
-		/* default to first driver in the list */
-		return select_driver(wpa_s, 0);
+		/* Default to first successful driver in the list */
+		for (i = 0; wpa_drivers[i]; i++) {
+			if (select_driver(wpa_s, i) == 0)
+				return 0;
+		}
+		/* Drivers have each reported failure, so no wpa_msg() here. */
+		return -1;
 	}
 
 	do {
@@ -4789,7 +5034,15 @@
 	wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
 	wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
 
+	if (wpa_s->own_disconnect_req) {
+		wpa_printf(MSG_DEBUG,
+			   "Drop received EAPOL frame as we are disconnecting");
+		return;
+	}
+
 #ifdef CONFIG_TESTING_OPTIONS
+	wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
+		     MAC2STR(src_addr), len);
 	if (wpa_s->ignore_auth_resp) {
 		wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
 		return;
@@ -5161,6 +5414,7 @@
 #ifdef CONFIG_TESTING_OPTIONS
 	dl_list_init(&wpa_s->drv_signal_override);
 #endif /* CONFIG_TESTING_OPTIONS */
+	dl_list_init(&wpa_s->active_scs_ids);
 
 	return wpa_s;
 }
@@ -7546,6 +7800,46 @@
 
 
 #ifdef CONFIG_FILS
+
+void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	const u8 *realm, *username, *rrk;
+	size_t realm_len, username_len, rrk_len;
+	u16 next_seq_num;
+
+	/* Clear the PMKSA cache entry if FILS authentication was rejected.
+	 * Check for ERP keys existing to limit when this can be done since
+	 * the rejection response is not protected and such triggers should
+	 * really not allow internal state to be modified unless required to
+	 * avoid significant issues in functionality. In addition, drop
+	 * externally configure PMKSA entries even without ERP keys since it
+	 * is possible for an external component to add PMKSA entries for FILS
+	 * authentication without restoring previously generated ERP keys.
+	 *
+	 * In this case, this is needed to allow recovery from cases where the
+	 * AP or authentication server has dropped PMKSAs and ERP keys. */
+	if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
+		return;
+
+	if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
+				  &username, &username_len,
+				  &realm, &realm_len, &next_seq_num,
+				  &rrk, &rrk_len) != 0 ||
+	    !realm) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"FILS: Drop external PMKSA cache entry");
+		wpa_sm_aborted_external_cached(wpa_s->wpa);
+		wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
+		return;
+	}
+
+	wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
+	wpa_sm_aborted_cached(wpa_s->wpa);
+	wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+}
+
+
 void fils_connection_failure(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
@@ -7581,7 +7875,7 @@
 }
 
 
-#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
+#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
 int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
 					      struct wpa_ssid *ssid,
 					      const char *field,
@@ -7711,7 +8005,7 @@
 	return -1;
 #endif /* IEEE8021X_EAPOL */
 }
-#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
+#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
 
 
 int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
@@ -7793,6 +8087,16 @@
 }
 
 
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+	if (wpa_s->current_ssid == NULL ||
+	    wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
+	    os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
+		return 0;
+	return wpa_sm_pmf_enabled(wpa_s->wpa);
+}
+
+
 int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
 {
 	if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
@@ -7860,6 +8164,17 @@
 		"id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
 		ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
 		ssid->auth_failures, dur, reason);
+
+	char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
+	int msg_len = snprintf(NULL, 0, format_str,
+		ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+		ssid->auth_failures, dur, reason) + 1;
+	char *msg = os_malloc(msg_len);
+	snprintf(msg, msg_len, format_str,
+		ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+		ssid->auth_failures, dur, reason);
+	wpas_notify_ssid_temp_disabled(wpa_s, msg);
+	os_free(msg);
 }
 
 
@@ -7961,6 +8276,10 @@
 	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
 	radio_remove_works(wpa_s, "connect", 0);
 	radio_remove_works(wpa_s, "sme-connect", 0);
+	wpa_s->roam_in_progress = false;
+#ifdef CONFIG_WNM
+	wpa_s->bss_trans_mgmt_in_progress = false;
+#endif /* CONFIG_WNM */
 }
 
 
@@ -8107,7 +8426,7 @@
 	}
 
 #ifdef CONFIG_P2P
-	if (wpa_s->parent == wpa_s &&
+	if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
 	    wpa_s->global->p2p &&
 	    !wpa_s->global->p2p_disabled)
 		p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
@@ -8150,6 +8469,9 @@
 {
 	u16 i;
 
+	if (!modes)
+		return NULL;
+
 	for (i = 0; i < num_modes; i++) {
 		if (modes[i].mode != mode ||
 		    !modes[i].num_channels || !modes[i].channels)
@@ -8163,6 +8485,22 @@
 }
 
 
+struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
+					     u16 num_modes, int freq)
+{
+	int i, j;
+
+	for (i = 0; i < num_modes; i++) {
+		for (j = 0; j < modes[i].num_channels; j++) {
+			if (freq == modes[i].channels[j].freq)
+				return &modes[i];
+		}
+	}
+
+	return NULL;
+}
+
+
 static struct
 wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
 						 const u8 *bssid)
@@ -8210,8 +8548,7 @@
 	dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
 			 struct wpa_bss_tmp_disallowed, list) {
 		if (bss == tmp) {
-			dl_list_del(&tmp->list);
-			os_free(tmp);
+			remove_bss_tmp_disallowed_entry(wpa_s, tmp);
 			wpa_set_driver_tmp_disallow_list(wpa_s);
 			break;
 		}
@@ -8264,8 +8601,11 @@
 		return 0;
 
 	if (disallowed->rssi_threshold != 0 &&
-	    bss->level > disallowed->rssi_threshold)
+	    bss->level > disallowed->rssi_threshold) {
+		remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
+		wpa_set_driver_tmp_disallow_list(wpa_s);
 		return 0;
+	}
 
 	return 1;
 }
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 11d1885..9376b03 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -150,6 +150,9 @@
 # This timeout value is used in mesh STA to clean up inactive stations.
 #mesh_max_inactivity=300
 
+# Enable 802.11s layer-2 routing and forwarding (dot11MeshForwarding)
+#mesh_fwding=1
+
 # cert_in_cb - Whether to include a peer certificate dump in events
 # This controls whether peer certificates for authentication server and
 # its certificate chain are included in EAP peer certificate events. This is
@@ -988,7 +991,7 @@
 # WPA3-Personal-only mode: ieee80211w=2 and key_mgmt=SAE
 #
 # ocv: whether operating channel validation is enabled
-# This is a countermeasure against multi-channel man-in-the-middle attacks.
+# This is a countermeasure against multi-channel on-path attacks.
 # Enabling this automatically also enables ieee80211w, if not yet enabled.
 # 0 = disabled (default)
 # 1 = enabled if wpa_supplicant's SME in use. Otherwise enabled only when the
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 9ce3233..1d2c3e2 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -19,6 +19,8 @@
 #include "wps/wps_defs.h"
 #include "config_ssid.h"
 #include "wmm_ac.h"
+#include <netinet/in.h>
+#include <netinet/in6.h>
 
 extern const char *const wpa_supplicant_version;
 extern const char *const wpa_supplicant_license;
@@ -38,6 +40,7 @@
 struct wpa_scan_results;
 struct hostapd_hw_modes;
 struct wpa_driver_associate_params;
+struct wpa_cred;
 
 /*
  * Forward declarations of private structures used within the ctrl_iface
@@ -47,7 +50,7 @@
 struct ctrl_iface_priv;
 struct ctrl_iface_global_priv;
 struct wpas_dbus_priv;
-struct wpas_hidl_priv;
+struct wpas_aidl_priv;
 
 /**
  * struct wpa_interface - Parameters for wpa_supplicant_add_iface()
@@ -280,7 +283,7 @@
 	struct wpa_params params;
 	struct ctrl_iface_global_priv *ctrl_iface;
 	struct wpas_dbus_priv *dbus;
-	struct wpas_hidl_priv *hidl;
+	struct wpas_aidl_priv *aidl;
 	void **drv_priv;
 	size_t drv_count;
 	struct os_time suspend_time;
@@ -525,6 +528,19 @@
 	bool valid_config;
 };
 
+struct dscp_policy_status {
+	u8 id;
+	u8 status;
+};
+
+struct dscp_resp_data {
+	bool more;
+	bool reset;
+	bool solicited;
+	struct dscp_policy_status *policy;
+	int num_policies;
+};
+
 #ifdef CONFIG_PASN
 
 struct pasn_fils {
@@ -540,6 +556,7 @@
 	int cipher;
 	u16 group;
 	int freq;
+	size_t kdk_len;
 
 	u8 trans_seq;
 	u8 status;
@@ -555,6 +572,9 @@
 	struct wpa_ptk ptk;
 	struct crypto_ecdh *ecdh;
 
+	struct wpabuf *comeback;
+	u16 comeback_after;
+
 #ifdef CONFIG_SAE
 	struct sae_data sae;
 #endif /* CONFIG_SAE */
@@ -573,6 +593,110 @@
 };
 #endif /* CONFIG_PASN */
 
+
+enum ip_version {
+	IPV4 = 4,
+	IPV6 = 6,
+};
+
+
+struct ipv4_params {
+	struct in_addr src_ip;
+	struct in_addr dst_ip;
+	u16 src_port;
+	u16 dst_port;
+	u8 dscp;
+	u8 protocol;
+	u8 param_mask;
+};
+
+
+struct ipv6_params {
+	struct in6_addr src_ip;
+	struct in6_addr dst_ip;
+	u16 src_port;
+	u16 dst_port;
+	u8 dscp;
+	u8 next_header;
+	u8 flow_label[3];
+	u8 param_mask;
+};
+
+
+struct type4_params {
+	u8 classifier_mask;
+	enum ip_version ip_version;
+	union {
+		struct ipv4_params v4;
+		struct ipv6_params v6;
+	} ip_params;
+};
+
+
+struct type10_params {
+	u8 prot_instance;
+	u8 prot_number;
+	u8 *filter_value;
+	u8 *filter_mask;
+	size_t filter_len;
+};
+
+
+struct tclas_element {
+	u8 user_priority;
+	u8 classifier_type;
+	union {
+		struct type4_params type4_param;
+		struct type10_params type10_param;
+	} frame_classifier;
+};
+
+
+struct scs_desc_elem {
+	u8 scs_id;
+	enum scs_request_type request_type;
+	u8 intra_access_priority;
+	bool scs_up_avail;
+	struct tclas_element *tclas_elems;
+	unsigned int num_tclas_elem;
+	u8 tclas_processing;
+};
+
+
+struct scs_robust_av_data {
+	struct scs_desc_elem *scs_desc_elems;
+	unsigned int num_scs_desc;
+};
+
+
+enum scs_response_status {
+	SCS_DESC_SENT = 0,
+	SCS_DESC_SUCCESS = 1,
+};
+
+
+struct active_scs_elem {
+	struct dl_list list;
+	u8 scs_id;
+	enum scs_response_status status;
+};
+
+struct dscp_policy_data {
+	u8 policy_id;
+	u8 req_type;
+	u8 dscp;
+	bool dscp_info;
+	const u8 *frame_classifier;
+	u8 frame_classifier_len;
+	struct type4_params type4_param;
+	const u8 *domain_name;
+	u8 domain_name_len;
+	u16 start_port;
+	u16 end_port;
+	bool port_range_info;
+};
+
+
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -607,9 +731,9 @@
 	char *preq_notify_peer;
 #endif /* CONFIG_AP */
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
-#ifdef CONFIG_CTRL_IFACE_HIDL
-	const void *hidl_object_key;
-#endif /* CONFIG_CTRL_IFACE_HIDL */
+#ifdef CONFIG_CTRL_IFACE_AIDL
+	const void *aidl_object_key;
+#endif /* CONFIG_CTRL_IFACE_AIDL */
 	char bridge_ifname[16];
 
 	char *confname;
@@ -622,6 +746,7 @@
 	u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
 				     * field contains the target BSSID. */
 	int reassociate; /* reassociation requested */
+	bool roam_in_progress; /* roam in progress */
 	unsigned int reassoc_same_bss:1; /* reassociating to the same BSS */
 	unsigned int reassoc_same_ess:1; /* reassociating to the same ESS */
 	int disconnected; /* all connections disabled; i.e., do no reassociate
@@ -1038,6 +1163,7 @@
 	unsigned int p2p_disable_ip_addr_req:1;
 	unsigned int p2ps_method_config_any:1;
 	unsigned int p2p_cli_probe:1;
+	unsigned int p2p_go_allow_dfs:1;
 	enum hostapd_hw_mode p2p_go_acs_band;
 	int p2p_persistent_go_freq;
 	int p2p_persistent_id;
@@ -1182,6 +1308,7 @@
 	struct os_reltime wnm_cand_valid_until;
 	u8 wnm_cand_from_bss[ETH_ALEN];
 	enum bss_trans_mgmt_status_code bss_tm_status;
+	bool bss_trans_mgmt_in_progress;
 	struct wpabuf *coloc_intf_elems;
 	u8 coloc_intf_dialog_token;
 	u8 coloc_intf_auto_report;
@@ -1348,6 +1475,7 @@
 	int dpp_auth_ok_on_ack;
 	int dpp_in_response_listen;
 	int dpp_gas_client;
+	int dpp_gas_server;
 	int dpp_gas_dialog_token;
 	u8 dpp_intro_bssid[ETH_ALEN];
 	void *dpp_intro_network;
@@ -1407,6 +1535,19 @@
 	struct wpas_pasn pasn;
 	struct wpa_radio_work *pasn_auth_work;
 #endif /* CONFIG_PASN */
+	struct scs_robust_av_data scs_robust_av_req;
+	u8 scs_dialog_token;
+#ifdef CONFIG_TESTING_OPTIONS
+	unsigned int disable_scs_support:1;
+	unsigned int disable_mscs_support:1;
+#endif /* CONFIG_TESTING_OPTIONS */
+	struct dl_list active_scs_ids;
+	bool ongoing_scs_req;
+	u8 dscp_req_dialog_token;
+	u8 dscp_query_dialog_token;
+	unsigned int enable_dscp_policy_capa:1;
+	unsigned int connection_dscp:1;
+	unsigned int wait_for_dscp_req:1;
 };
 
 
@@ -1432,6 +1573,8 @@
 int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
 					const char *bridge_ifname);
+void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
+				struct wpa_ssid *ssid, struct wpa_ie_data *ie);
 int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 			      struct wpa_bss *bss, struct wpa_ssid *ssid,
 			      u8 *wpa_ie, size_t *wpa_ie_len);
@@ -1465,6 +1608,8 @@
 				    struct wpa_ssid *ssid);
 void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
 				   struct wpa_ssid *ssid);
+int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred);
+int wpas_remove_all_creds(struct wpa_supplicant *wpa_s);
 int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
 					   const char *pkcs11_engine_path,
 					   const char *pkcs11_module_path);
@@ -1506,6 +1651,7 @@
 void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s);
 void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
 void fils_connection_failure(struct wpa_supplicant *wpa_s);
+void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
 int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s);
 int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s);
 void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason);
@@ -1523,6 +1669,14 @@
 
 int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
 			 u8 *op_class, u8 *chan, u8 *phy_type);
+
+int wpas_twt_send_setup(struct wpa_supplicant *wpa_s, u8 dtok, int exponent,
+			int mantissa, u8 min_twt, int setup_cmd, u64 twt,
+			bool requestor, bool trigger, bool implicit,
+			bool flow_type, u8 flow_id, bool protection,
+			u8 twt_channel, u8 control);
+int wpas_twt_send_teardown(struct wpa_supplicant *wpa_s, u8 flags);
+
 void wpas_rrm_reset(struct wpa_supplicant *wpa_s);
 void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
 				   const u8 *report, size_t report_len);
@@ -1576,7 +1730,7 @@
 
 /* op_classes.c */
 enum chan_allowed {
-	NOT_ALLOWED, NO_IR, ALLOWED
+	NOT_ALLOWED, NO_IR, RADAR, ALLOWED
 };
 
 enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
@@ -1676,6 +1830,7 @@
 
 int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
 int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr);
 
 int wpas_init_ext_pw(struct wpa_supplicant *wpa_s);
 
@@ -1711,6 +1866,8 @@
 struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
 				   u16 num_modes, enum hostapd_hw_mode mode,
 				   bool is_6ghz);
+struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
+					     u16 num_modes, int freq);
 
 void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			  unsigned int sec, int rssi_threshold);
@@ -1741,10 +1898,28 @@
 				       size_t len);
 void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
 				 const u8 *ies, size_t ies_len);
+int wpas_send_scs_req(struct wpa_supplicant *wpa_s);
+void free_up_tclas_elem(struct scs_desc_elem *elem);
+void free_up_scs_desc(struct scs_robust_av_data *data);
+void wpas_handle_robust_av_scs_recv_action(struct wpa_supplicant *wpa_s,
+					   const u8 *src, const u8 *buf,
+					   size_t len);
+void wpas_scs_deinit(struct wpa_supplicant *wpa_s);
+void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s,
+				      const u8 *src,
+				      const u8 *buf, size_t len);
+void wpas_dscp_deinit(struct wpa_supplicant *wpa_s);
+int wpas_send_dscp_response(struct wpa_supplicant *wpa_s,
+			    struct dscp_resp_data *resp_data);
+void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
+				     const u8 *ies, size_t ies_len);
+int wpas_send_dscp_query(struct wpa_supplicant *wpa_s, const char *domain_name,
+			 size_t domain_name_length);
 
 int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
 			 const u8 *bssid, int akmp, int cipher,
-			 u16 group, int network_id);
+			 u16 group, int network_id,
+			 const u8 *comeback, size_t comeback_len);
 void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
 int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
 			     const u8 *data, size_t data_len, u8 acked);
@@ -1752,4 +1927,6 @@
 		      const struct ieee80211_mgmt *mgmt, size_t len);
 int disabled_freq(struct wpa_supplicant *wpa_s, int freq);
 
+int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *bssid);
+
 #endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 95dad95..008ec08 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -95,8 +95,8 @@
  * @len: Frame payload length
  * Returns: >=0 on success, <0 on failure
  */
-static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
-			  u16 proto, const u8 *buf, size_t len)
+int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
+		   u16 proto, const u8 *buf, size_t len)
 {
 #ifdef CONFIG_TESTING_OPTIONS
 	if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) {
@@ -788,6 +788,9 @@
 	const u8 *supp_rates, size_t supp_rates_len,
 	const struct ieee80211_ht_capabilities *ht_capab,
 	const struct ieee80211_vht_capabilities *vht_capab,
+	const struct ieee80211_he_capabilities *he_capab,
+	size_t he_capab_len,
+	const struct ieee80211_he_6ghz_band_cap *he_6ghz_he_capab,
 	u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len,
 	const u8 *supp_channels, size_t supp_channels_len,
 	const u8 *supp_oper_classes, size_t supp_oper_classes_len)
@@ -811,6 +814,9 @@
 
 	params.ht_capabilities = ht_capab;
 	params.vht_capabilities = vht_capab;
+	params.he_capab = he_capab;
+	params.he_capab_len = he_capab_len;
+	params.he_6ghz_capab = he_6ghz_he_capab;
 	params.qosinfo = qosinfo;
 	params.listen_interval = 0;
 	params.supp_rates = supp_rates;
@@ -1153,6 +1159,22 @@
 		}
 	}
 }
+
+static void wpa_supplicant_eap_method_selected_cb(void *ctx,
+						const char* reason_string)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	wpas_notify_eap_method_selected(wpa_s, reason_string);
+}
+
+static void wpa_supplicant_open_ssl_failure_cb(void *ctx,
+						const char* reason_string)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	wpas_notify_open_ssl_failure(wpa_s, reason_string);
+}
 #endif /* IEEE8021X_EAPOL */
 
 
@@ -1199,6 +1221,8 @@
 	ctx->eap_error_cb = wpa_supplicant_eap_error_cb;
 	ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb;
 	ctx->set_anon_id = wpa_supplicant_set_anon_id;
+	ctx->eap_method_selected_cb = wpa_supplicant_eap_method_selected_cb;
+	ctx->open_ssl_failure_cb = wpa_supplicant_open_ssl_failure_cb;
 	ctx->cb_ctx = wpa_s;
 	wpa_s->eapol = eapol_sm_init(ctx);
 	if (wpa_s->eapol == NULL) {
@@ -1342,6 +1366,17 @@
 		changed = 1;
 	}
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	/* driver call for transition disable */
+	{
+		struct wpa_driver_associate_params params;
+
+		os_memset(&params, 0, sizeof(params));
+		params.td_policy = bitmap;
+		wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_TD_POLICY);
+	}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
 	wpas_notify_transition_disable(wpa_s, ssid, bitmap);
 
 	if (!changed)
diff --git a/wpa_supplicant/wpas_glue.h b/wpa_supplicant/wpas_glue.h
index 5585e56..338af4e 100644
--- a/wpa_supplicant/wpas_glue.h
+++ b/wpa_supplicant/wpas_glue.h
@@ -15,6 +15,8 @@
 int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
 					struct wpa_ssid *ssid);
+int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
+		   u16 proto, const u8 *buf, size_t len);
 
 const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
 					       const char *default_txt,
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 1dd3d82..1ba360e 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -372,6 +372,7 @@
 #ifdef CONFIG_WPS_REG_DISABLE_OPEN
 	int registrar = 0;
 #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
+	bool add_sae;
 
 	if ((wpa_s->conf->wps_cred_processing == 1 ||
 	     wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
@@ -534,8 +535,12 @@
 	case WPS_AUTH_WPA2PSK:
 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
 		ssid->key_mgmt = WPA_KEY_MGMT_PSK;
-		if (wpa_s->conf->wps_cred_add_sae &&
-		    cred->key_len != 2 * PMK_LEN) {
+		add_sae = wpa_s->conf->wps_cred_add_sae;
+#ifdef CONFIG_P2P
+		if (ssid->p2p_group && is_p2p_6ghz_capable(wpa_s->global->p2p))
+			add_sae = true;
+#endif /* CONFIG_P2P */
+		if (add_sae && cred->key_len != 2 * PMK_LEN) {
 			ssid->auth_alg = 0;
 			ssid->key_mgmt |= WPA_KEY_MGMT_SAE;
 			ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;