From b652f1974f27b181f206d264831fc4685c984e1c Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Wed, 24 Apr 2013 00:32:44 +1200 Subject: [PATCH] Completed port to gnutls for linux. --- CMakeLists.txt | 3 +- CMakeTests/FindGnuTLS.cmake | 51 +++ Source/Core/Core/CMakeLists.txt | 10 + .../IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp | 432 ++++++++++-------- .../Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h | 33 +- 5 files changed, 324 insertions(+), 205 deletions(-) create mode 100644 CMakeTests/FindGnuTLS.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index fe68099213..8ab8026eb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ if (APPLE) endif() endif() project(dolphin-emu) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/CMakeTests) +set(CMAKE_MODULE_PATH ${dCMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/CMakeTests) set(DOLPHIN_IS_STABLE FALSE) # Set up paths @@ -418,7 +418,6 @@ if(NOT ANDROID) endif() endif() endif() -include(FindOpenSSL REQUIRED) ######################################## # Setup include directories (and make sure they are preferred over the Externals) diff --git a/CMakeTests/FindGnuTLS.cmake b/CMakeTests/FindGnuTLS.cmake new file mode 100644 index 0000000000..cf0b76ecff --- /dev/null +++ b/CMakeTests/FindGnuTLS.cmake @@ -0,0 +1,51 @@ +# - Try to find GNUTLS +# Find GNUTLS headers, libraries and the answer to all questions. +# +# GNUTLS_FOUND True if gnutls got found +# GNUTLS_INCLUDE_DIRS Location of gnutls headers +# GNUTLS_LIBRARIES List of libaries to use gnutls +# +# Copyright (c) 2007 Bjoern Ricks +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + +INCLUDE( FindPkgConfig ) + +IF ( GNUTLS_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "REQUIRED" ) +ELSE( GNUTLS_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "" ) +ENDIF ( GNUTLS_FIND_REQUIRED ) + +IF ( GNUTLS_MIN_VERSION ) + PKG_SEARCH_MODULE( GNUTLS ${_pkgconfig_REQUIRED} gnutls>=${GNUTLS_MIN_VERSION} ) +ELSE ( GNUTLS_MIN_VERSION ) + PKG_SEARCH_MODULE( GNUTLS ${_pkgconfig_REQUIRED} gnutls ) +ENDIF ( GNUTLS_MIN_VERSION ) + + +IF( NOT GNUTLS_FOUND AND NOT PKG_CONFIG_FOUND ) + FIND_PATH( GNUTLS_INCLUDE_DIRS gnutls/gnutls.h ) + FIND_LIBRARY( GNUTLS_LIBRARIES gnutls) + + # Report results + IF ( GNUTLS_LIBRARIES AND GNUTLS_INCLUDE_DIRS ) + SET( GNUTLS_FOUND 1 ) + IF ( NOT GNUTLS_FIND_QUIETLY ) + MESSAGE( STATUS "Found gnutls: ${GNUTLS_LIBRARIES}" ) + ENDIF ( NOT GNUTLS_FIND_QUIETLY ) + ELSE ( GNUTLS_LIBRARIES AND GNUTLS_INCLUDE_DIRS ) + IF ( GNUTLS_FIND_REQUIRED ) + MESSAGE( SEND_ERROR "Could NOT find gnutls" ) + ELSE ( GNUTLS_FIND_REQUIRED ) + IF ( NOT GNUTLS_FIND_QUIETLY ) + MESSAGE( STATUS "Could NOT find gnutls" ) + ENDIF ( NOT GNUTLS_FIND_QUIETLY ) + ENDIF ( GNUTLS_FIND_REQUIRED ) + ENDIF ( GNUTLS_LIBRARIES AND GNUTLS_INCLUDE_DIRS ) +ENDIF( NOT GNUTLS_FOUND AND NOT PKG_CONFIG_FOUND ) + +MARK_AS_ADVANCED( GNUTLS_LIBRARIES GNUTLS_INCLUDE_DIRS ) diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 1ba78fa442..18ceea45c6 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -230,6 +230,16 @@ if(LIBUSB_FOUND) set(SRCS ${SRCS} Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp) endif(LIBUSB_FOUND) +set(GNUTLS_MIN_VERSION "3.1.9") +set(GNUTLS_FIND_REQUIRED 1) +find_package(GnuTLS) +set(LIBS ${LIBS} ${GNUTLS_LIBRARIES}) + + +if(NOT GNUTLS_FOUND) + message(FATAL_ERROR "GnuTLS not found") +endif(NOT GNUTLS_FOUND) + if(WIN32) set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Win32.cpp Src/stdafx.cpp Src/HW/WiimoteReal/IOWin.cpp) diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp index ef58a42d81..1ba785497c 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp @@ -20,30 +20,34 @@ #pragma optimize("",off) #endif -#include #include "FileUtil.h" #include "WII_IPC_HLE_Device_net_ssl.h" #include "../Debugger/Debugger_SymbolMap.h" + + CWII_IPC_HLE_Device_net_ssl::CWII_IPC_HLE_Device_net_ssl(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) { - SSL_library_init(); - sslfds[0] = NULL; - sslfds[1] = NULL; - sslfds[2] = NULL; - sslfds[3] = NULL; + gnutls_global_init(); + for(int i = 0; i < NET_SSL_MAXINSTANCES; ++i) + { + _SSL[i].session = NULL; + _SSL[i].xcred = NULL; + memset(_SSL[i].hostname, 0, MAX_HOSTNAME_LEN); + } } CWII_IPC_HLE_Device_net_ssl::~CWII_IPC_HLE_Device_net_ssl() { + gnutls_global_deinit(); } int CWII_IPC_HLE_Device_net_ssl::getSSLFreeID() { for (int i = 0; i < NET_SSL_MAXINSTANCES; i++) { - if (sslfds[i] == NULL) + if (_SSL[i].session == NULL) return i + 1; } return 0; @@ -87,6 +91,53 @@ bool CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress) return true; } +static int +_verify_certificate_callback (gnutls_session_t session) +{ + unsigned int status; + int ret; + gnutls_certificate_type_t type; + const char *hostname; + gnutls_datum_t out; + + /* Read hostname. */ + hostname = (const char *)gnutls_session_get_ptr (session); + WARN_LOG(WII_IPC_SSL, "_verify_certificate_callback: Verifying certificate for %s\n", hostname); + + /* This verification function uses the trusted CAs in the credentials + * structure. + */ + ret = gnutls_certificate_verify_peers3 (session, hostname, &status); + if (ret < 0) + { + WARN_LOG(WII_IPC_SSL, "gnutls_certificate_verify_peers3 error %d", ret); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + type = gnutls_certificate_type_get (session); + + ret = gnutls_certificate_verification_status_print( status, type, &out, 0); + if (ret < 0) + { + WARN_LOG(WII_IPC_SSL, "gnutls_certificate_verification_status_print error %d", ret); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + WARN_LOG(WII_IPC_SSL, "_verify_certificate_callback: %s", out.data); + + gnutls_free(out.data); + + if (status != 0) + { + /* Certificate is not trusted */ + WARN_LOG(WII_IPC_SSL, "_verify_certificate_callback: status = %d", status); + return GNUTLS_E_CERTIFICATE_ERROR; + } + /* Certificate verified successfully. */ + return 0; +} + + u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer) { s32 returnValue = 0; @@ -133,24 +184,72 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C { case IOCTLV_NET_SSL_NEW: { + int verifyOption = Memory::Read_U32(_BufferOut); + const char * hostname = (const char*) Memory::GetPointer(_BufferOut2); + int freeSSL = this->getSSLFreeID(); if (freeSSL) { - Memory::Write_U32(freeSSL, _BufferIn); + int sslID = freeSSL - 1; - SSL_CTX* ctx = SSL_CTX_new(SSLv23_method()); - - //SSL_CTX_set_options(ctx,0); - - SSL* ssl = SSL_new(ctx); - sslfds[freeSSL-1] = ssl; - + int ret = gnutls_init (&_SSL[sslID].session, GNUTLS_CLIENT); + if(ret) + { + _SSL[sslID].session = NULL; + goto _SSL_NEW_ERROR; + } + + gnutls_session_t session = _SSL[sslID].session; + + memcpy(_SSL[sslID].hostname, hostname, min((int)BufferOutSize2, MAX_HOSTNAME_LEN)); + _SSL[sslID].hostname[MAX_HOSTNAME_LEN-1] = '\0'; + + gnutls_session_set_ptr (session, (void *) _SSL[sslID].hostname); + gnutls_server_name_set (session, GNUTLS_NAME_DNS, _SSL[sslID].hostname, + strnlen(_SSL[sslID].hostname, MAX_HOSTNAME_LEN)); + + const char *err = NULL; + ret = gnutls_priority_set_direct (session, "NORMAL", &err); + if(ret) + { + _SSL[sslID].session = NULL; + goto _SSL_NEW_ERROR; + } + + /* X509 stuff */ + ret = gnutls_certificate_allocate_credentials (&_SSL[sslID].xcred); + if(ret) + { + _SSL[sslID].session = NULL; + _SSL[sslID].xcred = NULL; + goto _SSL_NEW_ERROR; + } + + gnutls_certificate_set_verify_function (_SSL[sslID].xcred, _verify_certificate_callback); + + /* put the x509 credentials to the current session + */ + ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, _SSL[sslID].xcred); + if(ret) + { + _SSL[sslID].session = NULL; + _SSL[sslID].xcred = NULL; + goto _SSL_NEW_ERROR; + } + + Memory::Write_U32(freeSSL, _BufferIn); + } + else + { +_SSL_NEW_ERROR: + Memory::Write_U32(-1, _BufferIn); } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_NEW " + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_NEW (%d, %s) " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + verifyOption, hostname, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); @@ -160,16 +259,24 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C case IOCTLV_NET_SSL_SHUTDOWN: { int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { - SSL_CTX* ctx = sslfds[sslID]->ctx; - SSL_shutdown(sslfds[sslID]); - if (ctx) - SSL_CTX_free(ctx); - sslfds[sslID] = NULL; + gnutls_session_t session = _SSL[sslID].session; + gnutls_bye (session, GNUTLS_SHUT_RDWR); + gnutls_deinit(session); + gnutls_certificate_free_credentials (_SSL[sslID].xcred); + + _SSL[sslID].session = NULL; + _SSL[sslID].xcred = NULL; + memset(_SSL[sslID].hostname, 0, MAX_HOSTNAME_LEN); + Memory::Write_U32(0, _BufferIn); } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SHUTDOWN " + else + { + Memory::Write_U32(-8, _BufferIn); + } + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SHUTDOWN " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -180,7 +287,7 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C } case IOCTLV_NET_SSL_SETROOTCA: { - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA " + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -190,53 +297,29 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C int sslID = Memory::Read_U32(_BufferOut) - 1; - void* certca = malloc(BufferOutSize2); - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { - std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); - - SSL* ssl = sslfds[sslID]; - - - FILE *wiiclientca = fopen((cert_base_path + "clientca.cer").c_str(), "rb"); - if (wiiclientca == NULL) - break; - - X509 *cert = d2i_X509_fp(wiiclientca, NULL); - fclose(wiiclientca); - if (SSL_use_certificate(ssl,cert) <= 0) - break; - if (cert) - X509_free(cert); - - - - FILE * clientcakey = fopen((cert_base_path + "clientcakey.der").c_str(), "rb"); - if (clientcakey == NULL) - break; - - EVP_PKEY * key = d2i_PrivateKey_fp(clientcakey, NULL); - - if (SSL_use_PrivateKey(ssl,key) <= 0) - break; - if (!SSL_check_private_key(ssl)) - break; - - - if (key) - EVP_PKEY_free(key); - - Memory::Write_U32(0, _BufferIn); + int ret = gnutls_certificate_set_x509_trust_file (_SSL[sslID].xcred, + (cert_base_path + "rootca.pem").c_str(), + GNUTLS_X509_FMT_PEM); + if(ret < 1) + Memory::Write_U32(-1, _BufferIn); + else + Memory::Write_U32(0, _BufferIn); + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA = %d", ret); + } + else + { + Memory::Write_U32(-8, _BufferIn); } - free(certca); break; } case IOCTLV_NET_SSL_SETBUILTINCLIENTCERT: { - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT " + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -245,41 +328,24 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { - SSL* ssl = sslfds[sslID]; - std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); - FILE * clientca = fopen((cert_base_path + "clientca.cer").c_str(), "rb"); - if (clientca == NULL) - break; - - X509 *cert = d2i_X509_fp(clientca, NULL); - fclose(clientca); - - FILE * clientcakey = fopen((cert_base_path + "clientcakey.der").c_str(), "rb"); - if (clientcakey == NULL) - break; - - - EVP_PKEY * key = d2i_PrivateKey_fp(clientcakey, NULL); - - if (SSL_use_certificate(ssl,cert) <= 0) - break; - if (SSL_use_PrivateKey(ssl,key) <= 0) - break; - - - if (!SSL_check_private_key(ssl)) - break; - - if (cert) - X509_free(cert); - if (key) - EVP_PKEY_free(key); - - Memory::Write_U32(0, _BufferIn); + int ret = gnutls_certificate_set_x509_key_file (_SSL[sslID].xcred, + (cert_base_path + "clientca.pem").c_str(), + (cert_base_path + "clientcakey.pem").c_str(), + GNUTLS_X509_FMT_PEM); + if(ret) + Memory::Write_U32(-1, _BufferIn); + else + Memory::Write_U32(0, _BufferIn); + + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = %d", ret); + } + else + { + Memory::Write_U32(-8, _BufferIn); } break; } @@ -287,11 +353,23 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C case IOCTLV_NET_SSL_SETBUILTINROOTCA: { int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL){ - - Memory::Write_U32(0, _BufferIn); + if (SSLID_VALID(sslID)) + { + std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); + int ret = gnutls_certificate_set_x509_trust_file (_SSL[sslID].xcred, + (cert_base_path + "rootca.pem").c_str(), + GNUTLS_X509_FMT_PEM); + if(ret < 1) + Memory::Write_U32(-1, _BufferIn); + else + Memory::Write_U32(0, _BufferIn); + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA = %d", ret); } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA " + else + { + Memory::Write_U32(-8, _BufferIn); + } + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -304,16 +382,22 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C case IOCTLV_NET_SSL_CONNECT: { int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { int sock = Memory::Read_U32(_BufferOut2); - SSL* ssl = sslfds[sslID]; - SSL_set_fd(ssl,sock); - - returnValue = SSL_connect(ssl); + gnutls_session_t session = _SSL[sslID].session; + + gnutls_transport_set_int (session, sock); + gnutls_handshake_set_timeout (session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + + returnValue = 1; Memory::Write_U32(0, _BufferIn); } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT " + else + { + Memory::Write_U32(-8, _BufferIn); + } + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -326,16 +410,30 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C case IOCTLV_NET_SSL_DOHANDSHAKE: { int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { - SSL* ssl = sslfds[sslID]; - SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); - returnValue = SSL_do_handshake(ssl); + gnutls_session_t session = _SSL[sslID].session; + do + { + returnValue = gnutls_handshake (session); + } + while (returnValue < 0 && gnutls_error_is_fatal (returnValue) == 0); -// if (returnValue == 1) + gnutls_alert_description_t alert = gnutls_alert_get (session); + + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE " + "%d %d", returnValue, alert); + returnValue = returnValue == GNUTLS_E_SUCCESS; + if (returnValue) Memory::Write_U32(0, _BufferIn); + else + Memory::Write_U32(-1, _BufferIn); } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE " + else + { + Memory::Write_U32(-8, _BufferIn); + } + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -349,74 +447,50 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C { int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { - SSL* ssl = sslfds[sslID]; + gnutls_session_t session = _SSL[sslID].session; - returnValue = SSL_write(ssl, Memory::GetPointer(_BufferOut2), BufferOutSize2); + returnValue = gnutls_record_send(session, Memory::GetPointer(_BufferOut2), BufferOutSize2); File::IOFile("ssl_write.bin", "ab").WriteBytes(Memory::GetPointer(_BufferOut2), BufferOutSize2); - - if (returnValue == -1) - returnValue = -SSL_get_error(ssl, returnValue); + Memory::Write_U32(returnValue, _BufferIn); } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_WRITE " + else + { + Memory::Write_U32(-8, _BufferIn); + } + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_WRITE " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); - INFO_LOG(WII_IPC_SSL, "%s", Memory::GetPointer(_BufferOut2)); + WARN_LOG(WII_IPC_SSL, "%s", Memory::GetPointer(_BufferOut2)); break; } case IOCTLV_NET_SSL_READ: { int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { - SSL* ssl = sslfds[sslID]; - returnValue = SSL_read(ssl, Memory::GetPointer(_BufferIn2), BufferInSize2); - if (returnValue == -1) + gnutls_session_t session = _SSL[sslID].session; + returnValue = gnutls_record_recv(session, Memory::GetPointer(_BufferIn2), BufferInSize2); + if (returnValue > 0) { - returnValue = -SSL_get_error(ssl, returnValue); - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ errorVal= %d", returnValue); - }else{ File::IOFile("ssl_read.bin", "ab").WriteBytes(Memory::GetPointer(_BufferIn2), returnValue); } - - // According to OpenSSL docs, all TLS calls (including reads) can cause - // writing on a socket, so we need to handle SSL_ERROR_WANT_WRITE too - // (which happens when OpenSSL writes on a nonblocking busy socket). The - // Wii does not like -SSL_ERROR_WANT_WRITE though, so we convert it to - // a read error. - if (returnValue == -SSL_ERROR_WANT_WRITE) - returnValue = -SSL_ERROR_WANT_READ; - - if (returnValue == -SSL_ERROR_SYSCALL) - { -#ifdef _WIN32 - int errorCode = WSAGetLastError(); - bool notConnected = (errorCode == WSAENOTCONN); -#else - int errorCode = errno; - bool notConnected = (errorCode == ENOTCONN); -#endif - if (notConnected) - { - returnValue = -SSL_ERROR_WANT_READ; - } - else - { - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ ERRORCODE= %d", errorCode); - } - } Memory::Write_U32(returnValue, _BufferIn); } + else + { + Memory::Write_U32(-8, _BufferIn); + } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ(%d)" + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ(%d)" "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -429,11 +503,16 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C case IOCTLV_NET_SSL_SETROOTCADEFAULT: { int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL){ + if (SSLID_VALID(sslID)) + { Memory::Write_U32(0, _BufferIn); } - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCADEFAULT " + else + { + Memory::Write_U32(-8, _BufferIn); + } + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCADEFAULT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -445,7 +524,7 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT: { - INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT " + WARN_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT " "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", @@ -454,42 +533,15 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer C _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); int sslID = Memory::Read_U32(_BufferOut) - 1; - if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + if (SSLID_VALID(sslID)) { - SSL* ssl = sslfds[sslID]; - - std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); - FILE * clientca = fopen((cert_base_path + "clientca.cer").c_str(), "rb"); - if (clientca == NULL) - break; - - X509 *cert = d2i_X509_fp(clientca, NULL); - fclose(clientca); - - FILE * clientcakey = fopen((cert_base_path + "clientcakey.der").c_str(), "rb"); - if (clientcakey == NULL) - break; - - - EVP_PKEY * key = d2i_PrivateKey_fp(clientcakey, NULL); - - - if (SSL_use_certificate(ssl,cert) <= 0) - break; - if (SSL_use_PrivateKey(ssl,key) <= 0) - break; - - - if (!SSL_check_private_key(ssl)) - break; - - if (cert) - X509_free(cert); - if (key) - EVP_PKEY_free(key); - + //gnutls_session_t session = _SSL[sslID].session; Memory::Write_U32(0, _BufferIn); } + else + { + Memory::Write_U32(-8, _BufferIn); + } break; } @@ -517,7 +569,7 @@ u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommand(u32 _Command, { default: { - INFO_LOG(WII_IPC_SSL, "%s unknown %i " + WARN_LOG(WII_IPC_SSL, "%s unknown %i " "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)", GetDeviceName().c_str(), _Command, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h index 156892d0d5..375c23d1a0 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h @@ -24,13 +24,15 @@ #endif #include "WII_IPC_HLE_Device.h" -#include -#include -#include -#include +#include +#include + +#define MAX_HOSTNAME_LEN 256 #define NET_SSL_MAXINSTANCES 4 +#define SSLID_VALID(x) (x >= 0 && x < NET_SSL_MAXINSTANCES && _SSL[x].session != NULL) + class CWII_IPC_HLE_Device_net_ssl : public IWII_IPC_HLE_Device { public: @@ -48,26 +50,31 @@ public: int getSSLFreeID(); private: - SSL * sslfds[NET_SSL_MAXINSTANCES]; - enum + struct _SSL{ + gnutls_session_t session; + gnutls_certificate_credentials_t xcred; + char hostname[MAX_HOSTNAME_LEN]; + } _SSL[NET_SSL_MAXINSTANCES]; + + enum { IOCTLV_NET_SSL_NEW = 0x01, IOCTLV_NET_SSL_CONNECT = 0x02, IOCTLV_NET_SSL_DOHANDSHAKE = 0x03, IOCTLV_NET_SSL_READ = 0x04, IOCTLV_NET_SSL_WRITE = 0x05, - IOCTLV_NET_SSL_SHUTDOWN = 0x06, + IOCTLV_NET_SSL_SHUTDOWN = 0x06, IOCTLV_NET_SSL_SETCLIENTCERT = 0x07, - IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT = 0x08, - IOCTLV_NET_SSL_REMOVECLIENTCERT = 0x09, + IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT = 0x08, + IOCTLV_NET_SSL_REMOVECLIENTCERT = 0x09, IOCTLV_NET_SSL_SETROOTCA = 0x0A, - IOCTLV_NET_SSL_SETROOTCADEFAULT = 0x0B, + IOCTLV_NET_SSL_SETROOTCADEFAULT = 0x0B, IOCTLV_NET_SSL_DOHANDSHAKEEX = 0x0C, - IOCTLV_NET_SSL_SETBUILTINROOTCA = 0x0D, - IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = 0x0E, + IOCTLV_NET_SSL_SETBUILTINROOTCA = 0x0D, + IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = 0x0E, IOCTLV_NET_SSL_DISABLEVERIFYOPTIONFORDEBUG = 0x0F, IOCTLV_NET_SSL_DEBUGGETVERSION = 0x14, - IOCTLV_NET_SSL_DEBUGGETTIME = 0x15, + IOCTLV_NET_SSL_DEBUGGETTIME = 0x15, };