Merge pull request #9408 from sepalani/sni

SSL: Workaround to remove SNI from ClientHello
This commit is contained in:
Léo Lam 2021-02-11 21:38:41 +01:00 committed by GitHub
commit 3ce72d4005
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 19 deletions

View File

@ -35,6 +35,39 @@ static constexpr mbedtls_x509_crt_profile mbedtls_x509_crt_profile_wii = {
0, /* No RSA min key size */ 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<IOS::HLE::WII_SSL*>(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<IOS::HLE::WII_SSL*>(ctx);
return mbedtls_net_recv(&ssl->hostfd, buf, len);
}
} // namespace
NetSSL::NetSSL(Kernel& ios, const std::string& device_name) : Device(ios, device_name) NetSSL::NetSSL(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{ {
for (WII_SSL& ssl : _SSL) 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); mbedtls_ssl_conf_renegotiation(&ssl->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED);
ssl->hostname = hostname; ssl->hostname = hostname;
mbedtls_ssl_set_hostname(&ssl->ctx, ssl->hostname.c_str());
ssl->active = true; ssl->active = true;
WriteReturnValue(freeSSL, BufferIn); WriteReturnValue(freeSSL, BufferIn);
} }
@ -445,7 +476,7 @@ IPCCommandResult NetSSL::IOCtlV(const IOCtlVRequest& request)
WiiSockMan& sm = WiiSockMan::GetInstance(); WiiSockMan& sm = WiiSockMan::GetInstance();
ssl->hostfd = sm.GetHostSocket(ssl->sockfd); ssl->hostfd = sm.GetHostSocket(ssl->sockfd);
INFO_LOG_FMT(IOS_SSL, "IOCTLV_NET_SSL_CONNECT socket = {}", 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); WriteReturnValue(SSL_OK, BufferIn);
} }
else else

View File

@ -74,8 +74,8 @@ struct WII_SSL
mbedtls_x509_crt cacert; mbedtls_x509_crt cacert;
mbedtls_x509_crt clicert; mbedtls_x509_crt clicert;
mbedtls_pk_context pk; mbedtls_pk_context pk;
int sockfd; int sockfd = -1;
int hostfd; int hostfd = -1;
std::string hostname; std::string hostname;
bool active; bool active;
}; };

View File

@ -457,14 +457,14 @@ void WiiSocket::Update(bool read, bool write, bool except)
} }
case IOCTLV_NET_SSL_WRITE: case IOCTLV_NET_SSL_WRITE:
{ {
int ret = mbedtls_ssl_write(&Device::NetSSL::_SSL[sslID].ctx, WII_SSL* ssl = &Device::NetSSL::_SSL[sslID];
Memory::GetPointer(BufferOut2), BufferOutSize2); const int ret =
mbedtls_ssl_write(&ssl->ctx, Memory::GetPointer(BufferOut2), BufferOutSize2);
if (ret >= 0) if (ret >= 0)
{ {
PowerPC::debug_interface.NetworkLogger()->LogSSLWrite( PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(Memory::GetPointer(BufferOut2),
Memory::GetPointer(BufferOut2), ret, ret, ssl->hostfd);
static_cast<mbedtls_net_context*>(Device::NetSSL::_SSL[sslID].ctx.p_bio)->fd);
// Return bytes written or SSL_ERR_ZERO if none // Return bytes written or SSL_ERR_ZERO if none
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); 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: case IOCTLV_NET_SSL_READ:
{ {
int ret = mbedtls_ssl_read(&Device::NetSSL::_SSL[sslID].ctx, WII_SSL* ssl = &Device::NetSSL::_SSL[sslID];
Memory::GetPointer(BufferIn2), BufferInSize2); const int ret =
mbedtls_ssl_read(&ssl->ctx, Memory::GetPointer(BufferIn2), BufferInSize2);
if (ret >= 0) if (ret >= 0)
{ {
PowerPC::debug_interface.NetworkLogger()->LogSSLRead( PowerPC::debug_interface.NetworkLogger()->LogSSLRead(Memory::GetPointer(BufferIn2),
Memory::GetPointer(BufferIn2), ret, ret, ssl->hostfd);
static_cast<mbedtls_net_context*>(Device::NetSSL::_SSL[sslID].ctx.p_bio)->fd);
// Return bytes read or SSL_ERR_ZERO if none // Return bytes read or SSL_ERR_ZERO if none
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
} }

View File

@ -241,11 +241,9 @@ void NetworkWidget::Update()
{ {
m_ssl_table->insertRow(ssl_id); m_ssl_table->insertRow(ssl_id);
s32 host_fd = -1; s32 host_fd = -1;
if (IOS::HLE::Device::IsSSLIDValid(ssl_id) && if (IOS::HLE::Device::IsSSLIDValid(ssl_id))
IOS::HLE::Device::NetSSL::_SSL[ssl_id].ctx.p_bio != nullptr)
{ {
host_fd = host_fd = IOS::HLE::Device::NetSSL::_SSL[ssl_id].hostfd;
static_cast<mbedtls_net_context*>(IOS::HLE::Device::NetSSL::_SSL[ssl_id].ctx.p_bio)->fd;
} }
m_ssl_table->setItem(ssl_id, 0, new QTableWidgetItem(QString::number(ssl_id))); m_ssl_table->setItem(ssl_id, 0, new QTableWidgetItem(QString::number(ssl_id)));
m_ssl_table->setItem(ssl_id, 1, GetSocketDomain(host_fd)); m_ssl_table->setItem(ssl_id, 1, GetSocketDomain(host_fd));