Completed port to gnutls for linux.

This commit is contained in:
Matthew Parlane 2013-04-24 00:32:44 +12:00
parent d5ef9f3e85
commit b652f1974f
5 changed files with 324 additions and 205 deletions

View File

@ -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)

View File

@ -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 <b.ricks@fh-osnabrueck.de>
#
# 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 )

View File

@ -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)

View File

@ -20,30 +20,34 @@
#pragma optimize("",off)
#endif
#include <openssl/err.h>
#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);

View File

@ -24,13 +24,15 @@
#endif
#include "WII_IPC_HLE_Device.h"
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/pkcs12.h>
#include <openssl/x509v3.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#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,
};