Force EAP-TLSv1.2 for WPA3-Enterprise 192-bit RSA networks
Implement a 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.
If the configuration is explictly setting TLSv1.3, then use it
anyway, but removed the invalid signature algorithm configuration
from the flow.
Bug: 271643008
Test: m
Test: Connect to WPA3-Enterprise 192-bit mode setup with RSA 3K.
Test: Connect to WPA3-Enterprise 192-bit mode setup with ECDSA.
Test: Connect to WPA3-Enterprise mode setup with RSA 3K.
Test: Verify correct TLS configuration settings from the logs.
Change-Id: I78f6b66ab2327a5a4e0da5c851c7a760f15b0bba
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/sta_network.cpp b/wpa_supplicant/aidl/sta_network.cpp
index e431a6d..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();
}
@@ -2651,33 +2660,100 @@
// no restriction
return ndk::ScopedAStatus::ok();
}
- 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_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");
+ tlsFlags |= TLS_CONN_DISABLE_TLSv1_0;
FALLTHROUGH_INTENDED;
default:
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);
};