Merge pull request #2868 from sepalani/dolphin_ssl

Dolphin new Dump SSL features
This commit is contained in:
shuffle2 2016-10-03 06:16:49 -07:00 committed by GitHub
commit f121fa07c2
8 changed files with 137 additions and 20 deletions

View File

@ -64,6 +64,7 @@
#define DUMP_FRAMES_DIR "Frames"
#define DUMP_AUDIO_DIR "Audio"
#define DUMP_DSP_DIR "DSP"
#define DUMP_SSL_DIR "SSL"
#define LOGS_DIR "Logs"
#define MAIL_LOGS_DIR "Mail"
#define SHADERS_DIR "Shaders"

View File

@ -781,6 +781,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
s_user_paths[D_DUMPAUDIO_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
s_user_paths[D_DUMPTEXTURES_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
s_user_paths[D_DUMPDSP_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_DSP_DIR DIR_SEP;
s_user_paths[D_DUMPSSL_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_SSL_DIR DIR_SEP;
s_user_paths[D_LOGS_IDX] = s_user_paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
s_user_paths[D_MAILLOGS_IDX] = s_user_paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP;
s_user_paths[D_THEMES_IDX] = s_user_paths[D_USER_IDX] + THEMES_DIR DIR_SEP;
@ -825,6 +826,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
s_user_paths[D_DUMPAUDIO_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP;
s_user_paths[D_DUMPTEXTURES_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP;
s_user_paths[D_DUMPDSP_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_DSP_DIR DIR_SEP;
s_user_paths[D_DUMPSSL_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_SSL_DIR DIR_SEP;
s_user_paths[F_RAMDUMP_IDX] = s_user_paths[D_DUMP_IDX] + RAM_DUMP;
s_user_paths[F_ARAMDUMP_IDX] = s_user_paths[D_DUMP_IDX] + ARAM_DUMP;
s_user_paths[F_FAKEVMEMDUMP_IDX] = s_user_paths[D_DUMP_IDX] + FAKEVMEM_DUMP;

View File

@ -39,6 +39,7 @@ enum
D_DUMPAUDIO_IDX,
D_DUMPTEXTURES_IDX,
D_DUMPDSP_IDX,
D_DUMPSSL_IDX,
D_LOAD_IDX,
D_LOGS_IDX,
D_MAILLOGS_IDX,

View File

@ -66,6 +66,7 @@ void SConfig::SaveSettings()
SaveInputSettings(ini);
SaveFifoPlayerSettings(ini);
SaveAnalyticsSettings(ini);
SaveNetworkSettings(ini);
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
m_SYSCONF->Save();
@ -80,6 +81,7 @@ void CreateDumpPath(const std::string& path)
File::SetUserPath(D_DUMP_IDX, path + '/');
File::CreateFullPath(File::GetUserPath(D_DUMPAUDIO_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPDSP_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPSSL_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPFRAMES_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPTEXTURES_IDX));
}
@ -300,6 +302,17 @@ void SConfig::SaveFifoPlayerSettings(IniFile& ini)
fifoplayer->Set("LoopReplay", bLoopFifoReplay);
}
void SConfig::SaveNetworkSettings(IniFile& ini)
{
IniFile::Section* network = ini.GetOrCreateSection("Network");
network->Set("SSLDumpRead", m_SSLDumpRead);
network->Set("SSLDumpWrite", m_SSLDumpWrite);
network->Set("SSLVerifyCert", m_SSLVerifyCert);
network->Set("SSLDumpRootCA", m_SSLDumpRootCA);
network->Set("SSLDumpPeerCert", m_SSLDumpPeerCert);
}
void SConfig::SaveAnalyticsSettings(IniFile& ini)
{
IniFile::Section* analytics = ini.GetOrCreateSection("Analytics");
@ -324,6 +337,7 @@ void SConfig::LoadSettings()
LoadDSPSettings(ini);
LoadInputSettings(ini);
LoadFifoPlayerSettings(ini);
LoadNetworkSettings(ini);
LoadAnalyticsSettings(ini);
m_SYSCONF = new SysConf();
@ -570,6 +584,17 @@ void SConfig::LoadFifoPlayerSettings(IniFile& ini)
fifoplayer->Get("LoopReplay", &bLoopFifoReplay, true);
}
void SConfig::LoadNetworkSettings(IniFile& ini)
{
IniFile::Section* network = ini.GetOrCreateSection("Network");
network->Get("SSLDumpRead", &m_SSLDumpRead, false);
network->Get("SSLDumpWrite", &m_SSLDumpWrite, false);
network->Get("SSLVerifyCert", &m_SSLVerifyCert, false);
network->Get("SSLDumpRootCA", &m_SSLDumpRootCA, false);
network->Get("SSLDumpPeerCert", &m_SSLDumpPeerCert, false);
}
void SConfig::LoadAnalyticsSettings(IniFile& ini)
{
IniFile::Section* analytics = ini.GetOrCreateSection("Analytics");

View File

@ -290,6 +290,13 @@ struct SConfig : NonCopyable
bool m_AdapterRumble[4];
bool m_AdapterKonga[4];
// Network settings
bool m_SSLDumpRead;
bool m_SSLDumpWrite;
bool m_SSLVerifyCert;
bool m_SSLDumpRootCA;
bool m_SSLDumpPeerCert;
SysConf* m_SYSCONF;
// Save settings
@ -316,6 +323,7 @@ private:
void SaveInputSettings(IniFile& ini);
void SaveMovieSettings(IniFile& ini);
void SaveFifoPlayerSettings(IniFile& ini);
void SaveNetworkSettings(IniFile& ini);
void SaveAnalyticsSettings(IniFile& ini);
void LoadGeneralSettings(IniFile& ini);
@ -327,6 +335,7 @@ private:
void LoadInputSettings(IniFile& ini);
void LoadMovieSettings(IniFile& ini);
void LoadFifoPlayerSettings(IniFile& ini);
void LoadNetworkSettings(IniFile& ini);
void LoadAnalyticsSettings(IniFile& ini);
static SConfig* m_Instance;

View File

@ -6,12 +6,23 @@
#include "Common/FileUtil.h"
#include "Common/NandPaths.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h"
#include "Core/IPC_HLE/WII_Socket.h"
WII_SSL CWII_IPC_HLE_Device_net_ssl::_SSL[NET_SSL_MAXINSTANCES];
static constexpr mbedtls_x509_crt_profile mbedtls_x509_crt_profile_wii = {
/* Hashes from SHA-1 and above */
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
0xFFFFFFF, /* Any PK alg */
0xFFFFFFF, /* Any curve */
0, /* No RSA min key size */
};
CWII_IPC_HLE_Device_net_ssl::CWII_IPC_HLE_Device_net_ssl(u32 _DeviceID,
const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
@ -30,13 +41,16 @@ CWII_IPC_HLE_Device_net_ssl::~CWII_IPC_HLE_Device_net_ssl()
if (ssl.active)
{
mbedtls_ssl_close_notify(&ssl.ctx);
mbedtls_ssl_session_free(&ssl.session);
mbedtls_ssl_free(&ssl.ctx);
mbedtls_ssl_config_free(&ssl.config);
mbedtls_x509_crt_free(&ssl.cacert);
mbedtls_x509_crt_free(&ssl.clicert);
mbedtls_ssl_session_free(&ssl.session);
mbedtls_ssl_free(&ssl.ctx);
mbedtls_ssl_config_free(&ssl.config);
mbedtls_ctr_drbg_free(&ssl.ctr_drbg);
mbedtls_entropy_free(&ssl.entropy);
ssl.hostname.clear();
ssl.active = false;
@ -152,13 +166,14 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
WII_SSL* ssl = &_SSL[sslID];
mbedtls_ssl_init(&ssl->ctx);
mbedtls_entropy_init(&ssl->entropy);
const char* pers = "dolphin-emu";
static constexpr const char* pers = "dolphin-emu";
mbedtls_ctr_drbg_init(&ssl->ctr_drbg);
int ret = mbedtls_ctr_drbg_seed(&ssl->ctr_drbg, mbedtls_entropy_func, &ssl->entropy,
(const unsigned char*)pers, strlen(pers));
if (ret)
{
mbedtls_ssl_free(&ssl->ctx);
mbedtls_ctr_drbg_free(&ssl->ctr_drbg);
mbedtls_entropy_free(&ssl->entropy);
goto _SSL_NEW_ERROR;
}
@ -171,10 +186,13 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
// For some reason we can't use TLSv1.2, v1.1 and below are fine!
mbedtls_ssl_conf_max_version(&ssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_2);
mbedtls_ssl_conf_cert_profile(&ssl->config, &mbedtls_x509_crt_profile_wii);
mbedtls_ssl_set_session(&ssl->ctx, &ssl->session);
mbedtls_ssl_conf_authmode(&ssl->config, MBEDTLS_SSL_VERIFY_NONE);
if (SConfig::GetInstance().m_SSLVerifyCert && verifyOption)
mbedtls_ssl_conf_authmode(&ssl->config, MBEDTLS_SSL_VERIFY_REQUIRED);
else
mbedtls_ssl_conf_authmode(&ssl->config, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_renegotiation(&ssl->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED);
ssl->hostname = hostname;
@ -204,16 +222,18 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
if (SSLID_VALID(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
mbedtls_ssl_close_notify(&ssl->ctx);
mbedtls_ssl_session_free(&ssl->session);
mbedtls_ssl_free(&ssl->ctx);
mbedtls_ssl_config_free(&ssl->config);
mbedtls_entropy_free(&ssl->entropy);
mbedtls_ssl_close_notify(&ssl->ctx);
mbedtls_x509_crt_free(&ssl->cacert);
mbedtls_x509_crt_free(&ssl->clicert);
mbedtls_ssl_session_free(&ssl->session);
mbedtls_ssl_free(&ssl->ctx);
mbedtls_ssl_config_free(&ssl->config);
mbedtls_ctr_drbg_free(&ssl->ctr_drbg);
mbedtls_entropy_free(&ssl->entropy);
ssl->hostname.clear();
ssl->active = false;
@ -248,6 +268,12 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
int ret =
mbedtls_x509_crt_parse_der(&ssl->cacert, Memory::GetPointer(BufferOut2), BufferOutSize2);
if (SConfig::GetInstance().m_SSLDumpRootCA)
{
std::string filename = File::GetUserPath(D_DUMPSSL_IDX) + ssl->hostname + "_rootca.der";
File::IOFile(filename, "wb").WriteBytes(Memory::GetPointer(BufferOut2), BufferOutSize2);
}
if (ret)
{
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);

View File

@ -3,12 +3,14 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <mbedtls/error.h>
#ifndef _WIN32
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include "Common/FileUtil.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
@ -312,7 +314,14 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
case IOCTLV_NET_SSL_DOHANDSHAKE:
{
int ret = mbedtls_ssl_handshake(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx);
mbedtls_ssl_context* ctx = &CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx;
int ret = mbedtls_ssl_handshake(ctx);
if (ret)
{
char error_buffer[256] = "";
mbedtls_strerror(ret, error_buffer, sizeof(error_buffer));
ERROR_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE: %s", error_buffer);
}
switch (ret)
{
case 0:
@ -328,11 +337,49 @@ void WiiSocket::Update(bool read, bool write, bool except)
if (!nonBlock)
ReturnValue = SSL_ERR_WAGAIN;
break;
case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
{
char error_buffer[256] = "";
int res = mbedtls_ssl_get_verify_result(ctx);
mbedtls_x509_crt_verify_info(error_buffer, sizeof(error_buffer), "", res);
ERROR_LOG(WII_IPC_SSL, "MBEDTLS_ERR_X509_CERT_VERIFY_FAILED (verify_result = %d): %s",
res, error_buffer);
if (res & MBEDTLS_X509_BADCERT_CN_MISMATCH)
res = SSL_ERR_VCOMMONNAME;
else if (res & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
res = SSL_ERR_VROOTCA;
else if (res & MBEDTLS_X509_BADCERT_REVOKED)
res = SSL_ERR_VCHAIN;
else if (res & MBEDTLS_X509_BADCERT_EXPIRED || res & MBEDTLS_X509_BADCERT_FUTURE)
res = SSL_ERR_VDATE;
else
res = SSL_ERR_FAILED;
Memory::Write_U32(res, BufferIn);
if (!nonBlock)
ReturnValue = res;
break;
}
default:
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
break;
}
// mbedtls_ssl_get_peer_cert(ctx) seems not to work if handshake failed
// Below is an alternative to dump the peer certificate
if (SConfig::GetInstance().m_SSLDumpPeerCert && ctx->session_negotiate != nullptr)
{
const mbedtls_x509_crt* cert = ctx->session_negotiate->peer_cert;
if (cert != nullptr)
{
std::string filename = File::GetUserPath(D_DUMPSSL_IDX) +
((ctx->hostname != nullptr) ? ctx->hostname : "") +
"_peercert.der";
File::IOFile(filename, "wb").WriteBytes(cert->raw.p, cert->raw.len);
}
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",
@ -345,10 +392,13 @@ void WiiSocket::Update(bool read, bool write, bool except)
int ret = mbedtls_ssl_write(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx,
Memory::GetPointer(BufferOut2), BufferOutSize2);
#ifdef DEBUG_SSL
File::IOFile("ssl_write.bin", "ab")
.WriteBytes(Memory::GetPointer(BufferOut2), BufferOutSize2);
#endif
if (SConfig::GetInstance().m_SSLDumpWrite && ret > 0)
{
std::string filename = File::GetUserPath(D_DUMPSSL_IDX) +
SConfig::GetInstance().GetUniqueID() + "_write.bin";
File::IOFile(filename, "ab").WriteBytes(Memory::GetPointer(BufferOut2), ret);
}
if (ret >= 0)
{
// Return bytes written or SSL_ERR_ZERO if none
@ -379,12 +429,14 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
int ret = mbedtls_ssl_read(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx,
Memory::GetPointer(BufferIn2), BufferInSize2);
#ifdef DEBUG_SSL
if (ret > 0)
if (SConfig::GetInstance().m_SSLDumpRead && ret > 0)
{
File::IOFile("ssl_read.bin", "ab").WriteBytes(Memory::GetPointer(BufferIn2), ret);
std::string filename = File::GetUserPath(D_DUMPSSL_IDX) +
SConfig::GetInstance().GetUniqueID() + "_read.bin";
File::IOFile(filename, "ab").WriteBytes(Memory::GetPointer(BufferIn2), ret);
}
#endif
if (ret >= 0)
{
// Return bytes read or SSL_ERR_ZERO if none

View File

@ -51,6 +51,7 @@ void CreateDirectories()
File::CreateFullPath(File::GetUserPath(D_CACHE_IDX));
File::CreateFullPath(File::GetUserPath(D_CONFIG_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPDSP_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPSSL_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPTEXTURES_IDX));
File::CreateFullPath(File::GetUserPath(D_GAMESETTINGS_IDX));
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX));