From 2f02cc2996deda95f8478126775e3aabed15ab49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 5 Mar 2017 22:42:08 +0100 Subject: [PATCH] IOS/SSL: Make sure we are using a correct cert/key This adds a check to the SSL code to make sure we are using the correct client certificate and key (and root CA). Now, instead of silently failing, the user will be notified whenever a file is missing or when it is invalid, i.e. when the hash does not match; this is likely to happen for existing users as the program linked in the network guide extracted the wrong certs :( --- Source/Core/Core/IOS/Network/SSL.cpp | 62 ++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/IOS/Network/SSL.cpp b/Source/Core/Core/IOS/Network/SSL.cpp index f37e5fce6074..2ded34ffc6ef 100644 --- a/Source/Core/Core/IOS/Network/SSL.cpp +++ b/Source/Core/Core/IOS/Network/SSL.cpp @@ -2,14 +2,17 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include #include #include +#include #include "Common/FileUtil.h" #include "Common/Logging/Log.h" +#include "Common/MsgHandler.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/HW/Memmap.h" @@ -85,6 +88,47 @@ IPCCommandResult NetSSL::IOCtl(const IOCtlRequest& request) return GetDefaultReply(IPC_SUCCESS); } +constexpr std::array s_client_cert_hash = { + {0x22, 0x9e, 0xc6, 0x78, 0x52, 0x5e, 0x06, 0x05, 0x88, 0xe8, 0xea, + 0x23, 0xe5, 0x45, 0x9e, 0xc1, 0x4a, 0xf3, 0xc2, 0xeb, 0xb7, 0xb9, + 0xe6, 0x9e, 0xc4, 0x6b, 0x0f, 0xaf, 0x01, 0x17, 0x30, 0xd9}}; +constexpr std::array s_client_key_hash = {{0x72, 0x3b, 0xe9, 0xb3, 0x2c, 0x3a, 0xfb, 0x83, + 0xa4, 0xa3, 0x75, 0x7a, 0xdf, 0x35, 0x25, 0x29, + 0xe9, 0x0c, 0x0a, 0xd6, 0xfa, 0xd5, 0x25, 0x09, + 0x96, 0x3b, 0xa8, 0x94, 0x2a, 0xe6, 0x25, 0xdf}}; +constexpr std::array s_root_ca_hash = {{0xc5, 0xb0, 0xf8, 0xdf, 0xce, 0xc6, 0xb9, 0xed, + 0x2a, 0xc3, 0x8b, 0x8b, 0xc6, 0x9a, 0x4d, 0xb7, + 0xc2, 0x09, 0xdc, 0x17, 0x7d, 0x24, 0x3c, 0x8d, + 0xf2, 0xbd, 0xdf, 0x9e, 0x39, 0x17, 0x1e, 0x5f}}; + +static std::vector ReadCertFile(const std::string& path, const std::array& correct_hash) +{ + File::IOFile file(path, "r"); + std::vector bytes(file.GetSize()); + if (!file.ReadBytes(bytes.data(), bytes.size())) + { + ERROR_LOG(IOS_SSL, "Failed to read %s", path.c_str()); + PanicAlertT("IOS: Could not read a file required for SSL services (%s). Please refer to " + "https://dolphin-emu.org/docs/guides/wii-network-guide/ for " + "instructions on setting up Wii networking.", + path.c_str()); + return {}; + } + + std::array hash; + mbedtls_sha256(bytes.data(), bytes.size(), hash.data(), 0); + if (hash != correct_hash) + { + ERROR_LOG(IOS_SSL, "Wrong hash for %s", path.c_str()); + PanicAlertT("IOS: A file required for SSL services (%s) is invalid. Please refer to " + "https://dolphin-emu.org/docs/guides/wii-network-guide/ for " + "instructions on setting up Wii networking.", + path.c_str()); + return {}; + } + return bytes; +} + IPCCommandResult NetSSL::IOCtlV(const IOCtlVRequest& request) { u32 BufferIn = 0, BufferIn2 = 0, BufferIn3 = 0; @@ -283,11 +327,14 @@ IPCCommandResult NetSSL::IOCtlV(const IOCtlVRequest& request) if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; - std::string cert_base_path = File::GetUserPath(D_SESSION_WIIROOT_IDX); - int ret = - mbedtls_x509_crt_parse_file(&ssl->clicert, (cert_base_path + "/clientca.pem").c_str()); - int pk_ret = mbedtls_pk_parse_keyfile(&ssl->pk, (cert_base_path + "/clientcakey.pem").c_str(), - nullptr); + const std::string cert_base_path = File::GetUserPath(D_SESSION_WIIROOT_IDX); + const std::vector client_cert = + ReadCertFile(cert_base_path + "/clientca.pem", s_client_cert_hash); + const std::vector client_key = + ReadCertFile(cert_base_path + "/clientcakey.pem", s_client_key_hash); + + int ret = mbedtls_x509_crt_parse(&ssl->clicert, client_cert.data(), client_cert.size()); + int pk_ret = mbedtls_pk_parse_key(&ssl->pk, client_key.data(), client_key.size(), nullptr, 0); if (ret || pk_ret) { mbedtls_x509_crt_free(&ssl->clicert); @@ -341,9 +388,10 @@ IPCCommandResult NetSSL::IOCtlV(const IOCtlVRequest& request) if (SSLID_VALID(sslID)) { WII_SSL* ssl = &_SSL[sslID]; + const std::string cert_base_path = File::GetUserPath(D_SESSION_WIIROOT_IDX); + const std::vector root_ca = ReadCertFile(cert_base_path + "/rootca.pem", s_root_ca_hash); - int ret = mbedtls_x509_crt_parse_file( - &ssl->cacert, (File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/rootca.pem").c_str()); + int ret = mbedtls_x509_crt_parse(&ssl->cacert, root_ca.data(), root_ca.size()); if (ret) { mbedtls_x509_crt_free(&ssl->clicert);