Merge "P2P: Use specific go_bssid field instead of generic bssid field"
diff --git a/hostapd/main.c b/hostapd/main.c
index eb1e861..18b2dd9 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -448,6 +448,13 @@
 		}
 	}
 
+#ifdef CONFIG_CTRL_IFACE_AIDL
+	if (hostapd_aidl_init(ifaces)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize AIDL interface");
+		return -1;
+	}
+#endif /* CONFIG_CTRL_IFACE_AIDL */
+
 	eloop_run();
 
 	return 0;
@@ -898,12 +905,6 @@
 			goto out;
 	}
 
-#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_AIDL */
 	hostapd_global_ctrl_iface_init(&interfaces);
 
 	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index e0e10fd..29f0d18 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -3271,7 +3271,11 @@
 		EC_KEY_free(ecdh);
 #endif
 	}
-	if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
+	if ((flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH))
+#ifdef EAP_TLSV1_3
+			&& (flags & TLS_CONN_DISABLE_TLSv1_3)
+#endif
+												 ) {
 #ifdef OPENSSL_IS_BORINGSSL
 		uint16_t sigalgs[1] = { SSL_SIGN_RSA_PKCS1_SHA384 };
 
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
index e2523d4..5c36301 100644
--- a/wpa_supplicant/aidl/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -364,6 +364,12 @@
 	return byteArrToVec(mac_addr, ETH_ALEN);
 }
 
+inline std::array<uint8_t, ETH_ALEN> macAddrToArray(const uint8_t* mac_addr) {
+	std::array<uint8_t, ETH_ALEN> arr;
+	std::copy(mac_addr, mac_addr + ETH_ALEN, std::begin(arr));
+	return arr;
+}
+
 // Raw pointer to the global structure maintained by the core.
 // Declared here to be accessible to onDeath()
 struct wpa_global *wpa_global_;
@@ -669,14 +675,14 @@
 		wpa_printf(MSG_INFO, "assoc key_mgmt 0x%x network key_mgmt 0x%x",
 			wpa_s->key_mgmt, wpa_s->current_ssid->key_mgmt);
 	}
-	std::vector<uint8_t> aidl_bssid;
+	std::array<uint8_t, ETH_ALEN> aidl_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) {
-		aidl_bssid = macAddrToVec(wpa_s->pending_bssid);
+		aidl_bssid = macAddrToArray(wpa_s->pending_bssid);
 	} else {
-		aidl_bssid = macAddrToVec(wpa_s->bssid);
+		aidl_bssid = macAddrToArray(wpa_s->bssid);
 	}
 	aidl_state_change_data.bssid = aidl_bssid;
 
@@ -1391,9 +1397,9 @@
 	params.psk = aidl_psk;
 	params.passphrase = misc_utils::charBufToString(ssid->passphrase);
 	params.isPersistent = aidl_is_persistent;
-	params.goDeviceAddress = macAddrToVec(wpa_group_s->go_dev_addr);
-	params.goInterfaceAddress = aidl_is_go ? macAddrToVec(wpa_group_s->own_addr) :
-			macAddrToVec(wpa_group_s->current_bss->bssid);
+	params.goDeviceAddress = macAddrToArray(wpa_group_s->go_dev_addr);
+	params.goInterfaceAddress = aidl_is_go ? macAddrToArray(wpa_group_s->own_addr) :
+			macAddrToArray(wpa_group_s->current_bss->bssid);
 	if (NULL != ip && !aidl_is_go) {
 		params.isP2pClientEapolIpAddressInfoPresent = true;
 		os_memcpy(&params.p2pClientIpInfo.ipAddressClient, &ip[0], 4);
@@ -1791,7 +1797,7 @@
 	std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
 
 	PmkSaCacheData aidl_pmksa_data = {};
-	aidl_pmksa_data.bssid = macAddrToVec(pmksa_entry->aa);
+	aidl_pmksa_data.bssid = macAddrToArray(pmksa_entry->aa);
 	// Serialize PmkCacheEntry into blob.
 	std::stringstream ss(
 		std::stringstream::in | std::stringstream::out | std::stringstream::binary);
diff --git a/wpa_supplicant/aidl/sta_iface.cpp b/wpa_supplicant/aidl/sta_iface.cpp
index 029b99a..674b30c 100644
--- a/wpa_supplicant/aidl/sta_iface.cpp
+++ b/wpa_supplicant/aidl/sta_iface.cpp
@@ -290,6 +290,12 @@
 	WPA_ASSERT(false);
 }
 
+inline std::array<uint8_t, ETH_ALEN> macAddrToArray(const uint8_t* mac_addr) {
+	std::array<uint8_t, ETH_ALEN> arr;
+	std::copy(mac_addr, mac_addr + ETH_ALEN, std::begin(arr));
+	return arr;
+}
+
 }  // namespace
 
 namespace aidl {
@@ -837,14 +843,6 @@
 	    &StaIface::removeQosPolicyForScsInternal, _aidl_return, in_scsPolicyIds);
 }
 
-::ndk::ScopedAStatus StaIface::removeAllQosPoliciesForScs(
-		std::vector<QosPolicyScsRequestStatus>* _aidl_return)
-{
-	return validateAndCall(
-	    this, SupplicantStatusCode::FAILURE_UNKNOWN,
-	    &StaIface::removeAllQosPoliciesForScsInternal, _aidl_return);
-}
-
 std::pair<std::string, ndk::ScopedAStatus> StaIface::getNameInternal()
 {
 	return {ifname_, ndk::ScopedAStatus::ok()};
@@ -2014,8 +2012,7 @@
 	MloLinksInfo linksInfo;
 	MloLink link;
 
-	linksInfo.apMldMacAddress->assign(
-	    wpa_s->ap_mld_addr, wpa_s->ap_mld_addr + ETH_ALEN);
+	linksInfo.apMldMacAddress = macAddrToArray(wpa_s->ap_mld_addr);
 	if (!wpa_s->valid_links)
 		 return {linksInfo, ndk::ScopedAStatus::ok()};
 
@@ -2031,8 +2028,7 @@
 		link.linkId = i;
 		link.staLinkMacAddress.assign(
 		    wpa_s->links[i].addr, wpa_s->links[i].addr + ETH_ALEN);
-		link.apLinkMacAddress->assign(
-		    wpa_s->links[i].bssid, wpa_s->links[i].bssid + ETH_ALEN);
+		link.apLinkMacAddress = macAddrToArray(wpa_s->links[i].bssid);
 		link.frequencyMHz = wpa_s->links[i].freq;
 		// TODO (b/259710591): Once supplicant implements TID-to-link
 		// mapping, copy it here. Mapping can be changed in two
@@ -2104,13 +2100,6 @@
 		createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED)};
 }
 
-std::pair<std::vector<QosPolicyScsRequestStatus>, ndk::ScopedAStatus>
-StaIface::removeAllQosPoliciesForScsInternal()
-{
-	return {std::vector<QosPolicyScsRequestStatus>(),
-		createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED)};
-}
-
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/aidl/sta_iface.h b/wpa_supplicant/aidl/sta_iface.h
index 88c6e45..db91445 100644
--- a/wpa_supplicant/aidl/sta_iface.h
+++ b/wpa_supplicant/aidl/sta_iface.h
@@ -165,8 +165,6 @@
 	::ndk::ScopedAStatus removeQosPolicyForScs(
 		const std::vector<uint8_t>& in_scsPolicyIds,
 		std::vector<QosPolicyScsRequestStatus>* _aidl_return) override;
-	::ndk::ScopedAStatus removeAllQosPoliciesForScs(
-		std::vector<QosPolicyScsRequestStatus>* _aidl_return) override;
 
 private:
 	// Corresponding worker functions for the AIDL methods.
@@ -279,8 +277,6 @@
 	std::pair<std::vector<QosPolicyScsRequestStatus>, ndk::ScopedAStatus>
 		removeQosPolicyForScsInternal(
 		const std::vector<uint8_t>& scsPolicyIds);
-	std::pair<std::vector<QosPolicyScsRequestStatus>, ndk::ScopedAStatus>
-		removeAllQosPoliciesForScsInternal();
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/aidl/sta_network.cpp b/wpa_supplicant/aidl/sta_network.cpp
index 4d816e4..e245247 100644
--- a/wpa_supplicant/aidl/sta_network.cpp
+++ b/wpa_supplicant/aidl/sta_network.cpp
@@ -14,6 +14,7 @@
 extern "C"
 {
 #include "wps_supplicant.h"
+#include "crypto/tls.h"
 }
 
 namespace {
@@ -121,7 +122,9 @@
 	  ifname_(ifname),
 	  network_id_(network_id),
 	  is_valid_(true)
-{}
+{
+	tlsFlags = 0;
+}
 
 void StaNetwork::invalidate() { is_valid_ = false; }
 bool StaNetwork::isValid()
@@ -2029,6 +2032,11 @@
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
 	int val = enable == true ? 1 : 0;
+	if (enable) {
+		setTlsFlagsFor192BitMode(true /*rsaMode */);
+	} else {
+		tlsFlags &= ~TLS_CONN_SUITEB;
+	}
 	std::string phase1_params("tls_suiteb=" + std::to_string(val));
 	if (wpa_ssid->eap.phase1 != NULL) {
 		phase1_params.append(wpa_ssid->eap.phase1);
@@ -2051,6 +2059,7 @@
 		"openssl_ciphers")) {
 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
 	}
+	setTlsFlagsFor192BitMode(false /*rsaMode */);
 	return ndk::ScopedAStatus::ok();
 }
 
@@ -2644,39 +2653,107 @@
 
 ndk::ScopedAStatus StaNetwork::setMinimumTlsVersionEapPhase1ParamInternal(TlsVersion tlsVersion)
 {
-	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	std::string phase1_params;
-	if (wpa_ssid->eap.phase1 != NULL) {
-		phase1_params.append(wpa_ssid->eap.phase1);
-	}
-	if (tlsVersion < TlsVersion::TLS_V1_0) {
+	if (tlsVersion < TlsVersion::TLS_V1_0 || tlsVersion > TlsVersion::TLS_V1_3) {
 		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
 	}
+	if (tlsVersion == TlsVersion::TLS_V1_0) {
+		// no restriction
+		return ndk::ScopedAStatus::ok();
+	}
+
+	if (tlsVersion < TlsVersion::TLS_V1_3 && (tlsFlags & TLS_CONN_SUITEB)) {
+		// TLS configuration already set up for WPA3-Enterprise 192-bit mode
+		return ndk::ScopedAStatus::ok();
+	}
+
+	tlsFlags &= ~(TLS_CONN_DISABLE_TLSv1_3 | TLS_CONN_DISABLE_TLSv1_2 \
+			| TLS_CONN_DISABLE_TLSv1_1 | TLS_CONN_DISABLE_TLSv1_0);
+
 	// Fallback to disable lower version TLS cascadingly.
 	switch (tlsVersion) {
+#ifdef EAP_TLSV1_3
 		case TlsVersion::TLS_V1_3:
-			phase1_params.append("tls_disable_tlsv1_2=1");
+			tlsFlags |= TLS_CONN_DISABLE_TLSv1_2;
 			FALLTHROUGH_INTENDED;
+#endif
 		case TlsVersion::TLS_V1_2:
-			phase1_params.append("tls_disable_tlsv1_1=1");
+			tlsFlags |= TLS_CONN_DISABLE_TLSv1_1;
 			FALLTHROUGH_INTENDED;
 		case TlsVersion::TLS_V1_1:
-			phase1_params.append("tls_disable_tlsv1_0=1");
-			FALLTHROUGH_INTENDED;
-		case TlsVersion::TLS_V1_0:
+			tlsFlags |= TLS_CONN_DISABLE_TLSv1_0;
 			FALLTHROUGH_INTENDED;
 		default:
-			// no restriction
 			break;
 	}
 
-	if (setStringKeyFieldAndResetState(
-		phase1_params.c_str(), &(wpa_ssid->eap.phase1), "phase1")) {
-		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
-	}
+	generateTlsParams();
 	return ndk::ScopedAStatus::ok();
 }
 
+/**
+ * WPA3-Enterprise 192-bit mode workaround to force the connection to EAP-TLSv1.2 due to
+ * interoperability issues in TLSv1.3 which disables the SSL_SIGN_RSA_PKCS1_SHA384
+ * signature algorithm, and has its own set of incompatible cipher suites which the
+ * current WPA3 specification doesn't specify. The only specified cipher suites in the
+ * WPA3 specifications are:
+ * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, and
+ * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384.
+ * See boringssl/include/openssl/tls1.h for TLSv1.3 cipher suites.
+ */
+void StaNetwork::setTlsFlagsFor192BitMode(bool rsaMode) {
+	// Disable TLSv1.0 and TLSv1.1 by default for 192-bit mode
+	int flags = TLS_CONN_DISABLE_TLSv1_1 \
+			| TLS_CONN_DISABLE_TLSv1_0;
+	if (rsaMode) {
+		// Check if flags not set or already set to use EAP-TLSv1.3
+		if (tlsFlags == 0 || !(tlsFlags & TLS_CONN_DISABLE_TLSv1_2)) {
+			// Set up EAP-TLSv1.2 by default for maximum compatibility
+			tlsFlags |= TLS_CONN_DISABLE_TLSv1_3;
+			tlsFlags &= ~TLS_CONN_DISABLE_TLSv1_2;
+		}
+		tlsFlags |= TLS_CONN_SUITEB;
+	}
+
+	tlsFlags |= flags;
+	generateTlsParams();
+}
+
+void StaNetwork::generateTlsParams() {
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid->eap.phase1 != NULL) {
+		os_free(wpa_ssid->eap.phase1);
+		wpa_ssid->eap.phase1 = NULL;
+	}
+	std::string tlsConfig;
+
+	if (tlsFlags & TLS_CONN_DISABLE_TLSv1_3) {
+		tlsConfig.append("tls_disable_tlsv1_3=1");
+	} else {
+		tlsConfig.append("tls_disable_tlsv1_3=0");
+	}
+	if (tlsFlags & TLS_CONN_DISABLE_TLSv1_2) {
+		tlsConfig.append("tls_disable_tlsv1_2=1");
+	} else {
+		tlsConfig.append("tls_disable_tlsv1_2=0");
+	}
+	if (tlsFlags & TLS_CONN_DISABLE_TLSv1_1) {
+		tlsConfig.append("tls_disable_tlsv1_1=1");
+	} else {
+		tlsConfig.append("tls_disable_tlsv1_1=0");
+	}
+	if (tlsFlags & TLS_CONN_DISABLE_TLSv1_0) {
+		tlsConfig.append("tls_disable_tlsv1_0=1");
+	} else {
+		tlsConfig.append("tls_disable_tlsv1_0=0");
+	}
+	if (tlsFlags & TLS_CONN_SUITEB) {
+		tlsConfig.append("tls_suiteb=1");
+	}
+
+	wpa_printf(MSG_DEBUG, "TLS configuration: %s", tlsConfig.c_str());
+	setStringKeyFieldAndResetState(
+			tlsConfig.c_str(), &(wpa_ssid->eap.phase1), "phase1");
+}
 }  // namespace supplicant
 }  // namespace wifi
 }  // namespace hardware
diff --git a/wpa_supplicant/aidl/sta_network.h b/wpa_supplicant/aidl/sta_network.h
index f794844..1c24702 100644
--- a/wpa_supplicant/aidl/sta_network.h
+++ b/wpa_supplicant/aidl/sta_network.h
@@ -339,6 +339,8 @@
 		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);
+	void setTlsFlagsFor192BitMode(bool);
+	void generateTlsParams();
 
 	// Reference to the global wpa_struct. This is assumed to be valid
 	// for the lifetime of the process.
@@ -348,6 +350,7 @@
 	// Id of the network this aidl object controls.
 	const int network_id_;
 	bool is_valid_;
+	int tlsFlags;
 
 	DISALLOW_COPY_AND_ASSIGN(StaNetwork);
 };