From 2a15bc6ab25cfd2d2e64bbf58357c53adc5c76e7 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Thu, 31 Dec 2020 18:29:29 +0400 Subject: [PATCH] SSL: Workaround to remove SNI from ClientHello --- Source/Core/Core/IOS/Network/SSL.cpp | 37 +++++++++++++++++-- Source/Core/Core/IOS/Network/SSL.h | 4 +- Source/Core/Core/IOS/Network/Socket.cpp | 20 +++++----- .../Core/DolphinQt/Debugger/NetworkWidget.cpp | 6 +-- 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/Source/Core/Core/IOS/Network/SSL.cpp b/Source/Core/Core/IOS/Network/SSL.cpp index 30d8286c0f..11498fced6 100644 --- a/Source/Core/Core/IOS/Network/SSL.cpp +++ b/Source/Core/Core/IOS/Network/SSL.cpp @@ -35,6 +35,39 @@ static constexpr mbedtls_x509_crt_profile mbedtls_x509_crt_profile_wii = { 0, /* No RSA min key size */ }; +namespace +{ +// Dirty workaround to disable SNI which isn't supported by the Wii. +// +// This SSL extension can ONLY be disabled by undefining +// MBEDTLS_SSL_SERVER_NAME_INDICATION and recompiling the library. When +// enabled and if the hostname is set, it uses the SNI extension which is sent +// with the Client Hello message. +// +// This workaround doesn't require recompiling the library. It does so by +// deferring mbedtls_ssl_set_hostname after the Client Hello message. The send +// callback is used as it's the (only?) hook called at the beginning of +// each step of the handshake by the mbedtls_ssl_flush_output function. +// +// The hostname still needs to be set as it is checked against the Common Name +// field during the certificate verification process. +int SSLSendWithoutSNI(void* ctx, const unsigned char* buf, size_t len) +{ + auto* ssl = static_cast(ctx); + + if (ssl->ctx.state == MBEDTLS_SSL_SERVER_HELLO) + mbedtls_ssl_set_hostname(&ssl->ctx, ssl->hostname.c_str()); + return mbedtls_net_send(&ssl->hostfd, buf, len); +} + +int SSLRecv(void* ctx, unsigned char* buf, size_t len) +{ + auto* ssl = static_cast(ctx); + + return mbedtls_net_recv(&ssl->hostfd, buf, len); +} +} // namespace + NetSSL::NetSSL(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { for (WII_SSL& ssl : _SSL) @@ -223,8 +256,6 @@ IPCCommandResult NetSSL::IOCtlV(const IOCtlVRequest& request) mbedtls_ssl_conf_renegotiation(&ssl->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED); ssl->hostname = hostname; - mbedtls_ssl_set_hostname(&ssl->ctx, ssl->hostname.c_str()); - ssl->active = true; WriteReturnValue(freeSSL, BufferIn); } @@ -445,7 +476,7 @@ IPCCommandResult NetSSL::IOCtlV(const IOCtlVRequest& request) WiiSockMan& sm = WiiSockMan::GetInstance(); ssl->hostfd = sm.GetHostSocket(ssl->sockfd); INFO_LOG_FMT(IOS_SSL, "IOCTLV_NET_SSL_CONNECT socket = {}", ssl->sockfd); - mbedtls_ssl_set_bio(&ssl->ctx, &ssl->hostfd, mbedtls_net_send, mbedtls_net_recv, nullptr); + mbedtls_ssl_set_bio(&ssl->ctx, ssl, SSLSendWithoutSNI, SSLRecv, nullptr); WriteReturnValue(SSL_OK, BufferIn); } else diff --git a/Source/Core/Core/IOS/Network/SSL.h b/Source/Core/Core/IOS/Network/SSL.h index d1a29f253e..d3f4e45e05 100644 --- a/Source/Core/Core/IOS/Network/SSL.h +++ b/Source/Core/Core/IOS/Network/SSL.h @@ -74,8 +74,8 @@ struct WII_SSL mbedtls_x509_crt cacert; mbedtls_x509_crt clicert; mbedtls_pk_context pk; - int sockfd; - int hostfd; + int sockfd = -1; + int hostfd = -1; std::string hostname; bool active; }; diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp index 321e8c1efe..3cf193cb57 100644 --- a/Source/Core/Core/IOS/Network/Socket.cpp +++ b/Source/Core/Core/IOS/Network/Socket.cpp @@ -457,14 +457,14 @@ void WiiSocket::Update(bool read, bool write, bool except) } case IOCTLV_NET_SSL_WRITE: { - int ret = mbedtls_ssl_write(&Device::NetSSL::_SSL[sslID].ctx, - Memory::GetPointer(BufferOut2), BufferOutSize2); + WII_SSL* ssl = &Device::NetSSL::_SSL[sslID]; + const int ret = + mbedtls_ssl_write(&ssl->ctx, Memory::GetPointer(BufferOut2), BufferOutSize2); if (ret >= 0) { - PowerPC::debug_interface.NetworkLogger()->LogSSLWrite( - Memory::GetPointer(BufferOut2), ret, - static_cast(Device::NetSSL::_SSL[sslID].ctx.p_bio)->fd); + PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(Memory::GetPointer(BufferOut2), + ret, ssl->hostfd); // Return bytes written or SSL_ERR_ZERO if none WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } @@ -491,14 +491,14 @@ void WiiSocket::Update(bool read, bool write, bool except) } case IOCTLV_NET_SSL_READ: { - int ret = mbedtls_ssl_read(&Device::NetSSL::_SSL[sslID].ctx, - Memory::GetPointer(BufferIn2), BufferInSize2); + WII_SSL* ssl = &Device::NetSSL::_SSL[sslID]; + const int ret = + mbedtls_ssl_read(&ssl->ctx, Memory::GetPointer(BufferIn2), BufferInSize2); if (ret >= 0) { - PowerPC::debug_interface.NetworkLogger()->LogSSLRead( - Memory::GetPointer(BufferIn2), ret, - static_cast(Device::NetSSL::_SSL[sslID].ctx.p_bio)->fd); + PowerPC::debug_interface.NetworkLogger()->LogSSLRead(Memory::GetPointer(BufferIn2), + ret, ssl->hostfd); // Return bytes read or SSL_ERR_ZERO if none WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } diff --git a/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp index f93b529d54..68cf9c5dbf 100644 --- a/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp @@ -241,11 +241,9 @@ void NetworkWidget::Update() { m_ssl_table->insertRow(ssl_id); s32 host_fd = -1; - if (IOS::HLE::Device::IsSSLIDValid(ssl_id) && - IOS::HLE::Device::NetSSL::_SSL[ssl_id].ctx.p_bio != nullptr) + if (IOS::HLE::Device::IsSSLIDValid(ssl_id)) { - host_fd = - static_cast(IOS::HLE::Device::NetSSL::_SSL[ssl_id].ctx.p_bio)->fd; + host_fd = IOS::HLE::Device::NetSSL::_SSL[ssl_id].hostfd; } m_ssl_table->setItem(ssl_id, 0, new QTableWidgetItem(QString::number(ssl_id))); m_ssl_table->setItem(ssl_id, 1, GetSocketDomain(host_fd));