1
0
Fork 0

Update mbedtls to 2.5.1 (#3964)

* Renaming changes:
  * macro prefix "POLARSSL" -> "MBEDTLS"
  * functions now prefixed with "mbedtls_"
  * rename PolarSSL++ -> mbedTLS++
  * rename polarssl submodule

* Use mbedtls' AES-CFB8 implementation.

* Add cSslConfig to wrap mbedtls_ssl_config

* Update cTCPLink and cBlockingSslClientSocket to use cSslConfig

* Use cSslConfig in cHTTPServer

* Use cSslConfig for cMojangAPI::SecureRequest

* CI Fixes

* Set -fomit-frame-pointer on the right target
master
peterbell10 2017-08-30 15:00:06 +01:00 committed by Tiger Wang
parent c6bc822054
commit 84941bcc9f
59 changed files with 952 additions and 699 deletions

6
.gitmodules vendored
View File

@ -7,9 +7,9 @@
[submodule "Server/Plugins/ChatLog"]
path = Server/Plugins/ChatLog
url = https://github.com/cuberite/ChatLog.git
[submodule "lib/polarssl"]
path = lib/polarssl
url = https://github.com/cuberite/polarssl.git
[submodule "lib/mbedtls"]
path = lib/mbedtls
url = https://github.com/ARMmbed/mbedtls.git
ignore = dirty
[submodule "lib/SQLiteCpp"]
path = lib/SQLiteCpp

View File

@ -1,4 +1,4 @@
# This is the top-level CMakeLists.txt file for the Cuberite project
# This is the top-level CMakeLists.txt file for the Cuberite project
#
# Use CMake to generate the build files for your platform
#
@ -209,8 +209,8 @@ link_directories(lib/jsoncpp/src/lib_json)
if (NOT EXISTS ${PROJECT_SOURCE_DIR}/lib/SQLiteCpp/CMakeLists.txt)
message(FATAL_ERROR "SQLiteCpp is missing in folder lib/SQLiteCpp. Have you initialized the submodules / downloaded the extra libraries?")
endif()
if (NOT EXISTS ${PROJECT_SOURCE_DIR}/lib/polarssl/CMakeLists.txt)
message(FATAL_ERROR "PolarSSL is missing in folder lib/polarssl. Have you initialized the submodules / downloaded the extra libraries?")
if (NOT EXISTS ${PROJECT_SOURCE_DIR}/lib/mbedtls/CMakeLists.txt)
message(FATAL_ERROR "mbedTLS is missing in folder lib/mbedtls. Have you initialized the submodules / downloaded the extra libraries?")
endif()
if (NOT EXISTS ${PROJECT_SOURCE_DIR}/lib/libevent/CMakeLists.txt)
message(FATAL_ERROR "LibEvent is missing in folder lib/libevent. Have you initialized and updated the submodules / downloaded the extra libraries?")
@ -274,13 +274,13 @@ if (WIN32)
endif()
# We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used
# (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those)
include(lib/polarssl.cmake EXCLUDE_FROM_ALL)
# (mbedTLS also has test and example programs in their CMakeLists.txt, we don't want those)
include(lib/mbedtls.cmake EXCLUDE_FROM_ALL)
if(NOT MSVC AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm")
# mbed TLS uses the frame pointer's register in inline assembly:
# mbed TLS uses the frame pointer's register in inline assembly for its bignum implementation:
# https://tls.mbed.org/kb/development/arm-thumb-error-r7-cannot-be-used-in-asm-here
target_compile_options(mbedtls PUBLIC -fomit-frame-pointer)
target_compile_options(mbedcrypto PRIVATE -fomit-frame-pointer)
endif()
set_exe_flags()
@ -302,7 +302,9 @@ if (MSVC)
jsoncpp_lib_static
lua
luaexpat
mbedcrypto
mbedtls
mbedx509
sqlite
SQLiteCpp
tolualib

View File

@ -8,7 +8,7 @@ set_lib_flags()
# Set include paths to the used libraries:
include_directories(SYSTEM "../../lib")
include_directories(SYSTEM "../../lib/polarssl/include")
include_directories(SYSTEM "../../lib/mbedtls/include")
include_directories("../../src")
function(flatten_files arg1)
@ -20,7 +20,7 @@ function(flatten_files arg1)
set(${arg1} "${res}" PARENT_SCOPE)
endfunction()
include(../../lib/polarssl.cmake)
include(../../lib/mbedtls.cmake)
add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib)
set_exe_flags()
@ -30,12 +30,12 @@ set(SHARED_SRC
../../src/ByteBuffer.cpp
../../src/StringUtils.cpp
../../src/UUID.cpp
../../src/PolarSSL++/AesCfb128Decryptor.cpp
../../src/PolarSSL++/AesCfb128Encryptor.cpp
../../src/PolarSSL++/CryptoKey.cpp
../../src/PolarSSL++/CtrDrbgContext.cpp
../../src/PolarSSL++/EntropyContext.cpp
../../src/PolarSSL++/RsaPrivateKey.cpp
../../src/mbedTLS++/AesCfb128Decryptor.cpp
../../src/mbedTLS++/AesCfb128Encryptor.cpp
../../src/mbedTLS++/CryptoKey.cpp
../../src/mbedTLS++/CtrDrbgContext.cpp
../../src/mbedTLS++/EntropyContext.cpp
../../src/mbedTLS++/RsaPrivateKey.cpp
../../src/LoggerListeners.cpp
../../src/Logger.cpp
)
@ -43,12 +43,12 @@ set(SHARED_HDR
../../src/ByteBuffer.h
../../src/StringUtils.h
../../src/UUID.h
../../src/PolarSSL++/AesCfb128Decryptor.h
../../src/PolarSSL++/AesCfb128Encryptor.h
../../src/PolarSSL++/CryptoKey.h
../../src/PolarSSL++/CtrDrbgContext.h
../../src/PolarSSL++/EntropyContext.h
../../src/PolarSSL++/RsaPrivateKey.h
../../src/mbedTLS++/AesCfb128Decryptor.h
../../src/mbedTLS++/AesCfb128Encryptor.h
../../src/mbedTLS++/CryptoKey.h
../../src/mbedTLS++/CtrDrbgContext.h
../../src/mbedTLS++/EntropyContext.h
../../src/mbedTLS++/RsaPrivateKey.h
)
set(SHARED_OSS_SRC
../../src/OSSupport/CriticalSection.cpp

View File

@ -1,4 +1,4 @@

// Connection.cpp
// Interfaces to the cConnection class representing a single pair of connected sockets
@ -7,7 +7,7 @@
#include "Connection.h"
#include "Server.h"
#include <iostream>
#include "PolarSSL++/CryptoKey.h"
#include "mbedTLS++/CryptoKey.h"
#include "../../src/Logger.h"
#ifdef _WIN32

View File

@ -1,4 +1,4 @@

// Connection.h
// Interfaces to the cConnection class representing a single pair of connected sockets
@ -10,8 +10,8 @@
#pragma once
#include "ByteBuffer.h"
#include "PolarSSL++/AesCfb128Decryptor.h"
#include "PolarSSL++/AesCfb128Encryptor.h"
#include "mbedTLS++/AesCfb128Decryptor.h"
#include "mbedTLS++/AesCfb128Encryptor.h"

View File

@ -1,4 +1,4 @@

// Server.h
// Interfaces to the cServer class encapsulating the entire "server"
@ -9,7 +9,7 @@
#pragma once
#include "PolarSSL++/RsaPrivateKey.h"
#include "mbedTLS++/RsaPrivateKey.h"

1
lib/mbedtls Submodule

@ -0,0 +1 @@
Subproject commit f2a597fa3dd1c7b15e0fee62f6932b253295803d

View File

@ -1,10 +1,10 @@

# This script includes PolarSSL, if not already included.
# It is needed for when multiple projects reference PolarSSL.
if(NOT TARGET mbedtls)
message("including polarssl")
message("including mbedtls")
set(ENABLE_TESTING OFF CACHE BOOL "Disable tests")
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable programs")
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/mbedtls/ ${CMAKE_CURRENT_BINARY_DIR}/lib/mbedtls EXCLUDE_FROM_ALL)
endif()

@ -1 +0,0 @@
Subproject commit 4f4c5b7450631e46a94cb89adf4a7737fbb178bc

View File

@ -6,8 +6,8 @@
#include "Globals.h"
#include "LuaTCPLink.h"
#include "LuaServerHandle.h"
#include "../PolarSSL++/X509Cert.h"
#include "../PolarSSL++/CryptoKey.h"
#include "../mbedTLS++/X509Cert.h"
#include "../mbedTLS++/CryptoKey.h"

View File

@ -1,4 +1,4 @@

#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "ManualBindings.h"
@ -6,8 +6,8 @@
#include <sstream>
#include <iomanip>
#include "tolua++/include/tolua++.h"
#include "polarssl/md5.h"
#include "polarssl/sha1.h"
#include "mbedtls/md5.h"
#include "mbedtls/sha1.h"
#include "PluginLua.h"
#include "PluginManager.h"
#include "LuaWindow.h"
@ -1838,7 +1838,7 @@ static int tolua_md5(lua_State * tolua_S)
{
return 0;
}
md5(SourceString, len, Output);
mbedtls_md5(SourceString, len, Output);
lua_pushlstring(tolua_S, reinterpret_cast<const char *>(Output), ARRAYCOUNT(Output));
return 1;
}
@ -1869,7 +1869,7 @@ static int tolua_md5HexString(lua_State * tolua_S)
{
return 0;
}
md5(SourceString, len, md5Output);
mbedtls_md5(SourceString, len, md5Output);
// Convert the md5 checksum to hex string:
std::stringstream Output;
@ -1896,7 +1896,7 @@ static int tolua_sha1(lua_State * tolua_S)
{
return 0;
}
sha1(SourceString, len, Output);
mbedtls_sha1(SourceString, len, Output);
lua_pushlstring(tolua_S, reinterpret_cast<const char *>(Output), ARRAYCOUNT(Output));
return 1;
}
@ -1915,7 +1915,7 @@ static int tolua_sha1HexString(lua_State * tolua_S)
{
return 0;
}
sha1(SourceString, len, sha1Output);
mbedtls_sha1(SourceString, len, sha1Output);
// Convert the sha1 checksum to hex string:
std::stringstream Output;

View File

@ -1,13 +1,13 @@
project (Cuberite)
project (Cuberite)
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/mbedtls/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libevent/include")
set(FOLDERS
OSSupport HTTP Items Blocks Protocol Generating PolarSSL++ Bindings
OSSupport HTTP Items Blocks Protocol Generating mbedTLS++ Bindings
WorldStorage Mobs Entities Simulator Simulator/IncrementalRedstoneSimulator
BlockEntities UI Noise
)
@ -177,7 +177,7 @@ endif()
if (NOT MSVC)
# Bindings need to reference other folders, so they are done here instead
# lib dependencies are not included
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/mbedtls/include")
foreach(folder ${FOLDERS})
add_subdirectory(${folder})
@ -349,7 +349,7 @@ if (NOT MSVC)
OSSupport HTTPServer Bindings Items Blocks Noise
Protocol Generating WorldStorage
Mobs Entities Simulator IncrementalRedstoneSimulator
BlockEntities UI PolarSSL++
BlockEntities UI mbedTLS++
)
endif ()

View File

@ -1,4 +1,4 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "ClientHandle.h"
#include "Server.h"
@ -33,7 +33,7 @@
#include "CompositeChat.h"
#include "Items/ItemSword.h"
#include "polarssl/md5.h"
#include "mbedtls/md5.h"

View File

@ -1,4 +1,4 @@

// HTTPServer.cpp
// Implements the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing
@ -9,6 +9,7 @@
#include "HTTPServerConnection.h"
#include "HTTPFormParser.h"
#include "SslHTTPServerConnection.h"
#include "mbedTLS++/SslConfig.h"
@ -88,17 +89,23 @@ bool cHTTPServer::Initialize(void)
AString KeyFile = cFile::ReadWholeFile("webadmin/httpskey.pem");
if (!CertFile.empty() && !KeyFile.empty())
{
m_Cert.reset(new cX509Cert);
int res = m_Cert->Parse(CertFile.data(), CertFile.size());
auto Cert = std::make_shared<cX509Cert>();
int res = Cert->Parse(CertFile.data(), CertFile.size());
if (res == 0)
{
m_CertPrivKey.reset(new cCryptoKey);
int res2 = m_CertPrivKey->ParsePrivate(KeyFile.data(), KeyFile.size(), "");
if (res2 != 0)
auto CertPrivKey = std::make_shared<cCryptoKey>();
res = CertPrivKey->ParsePrivate(KeyFile.data(), KeyFile.size(), "");
if (res == 0)
{
// Modifyable locally but otherwise must be const
auto Config = cSslConfig::MakeDefaultConfig(false);
Config->SetOwnCert(Cert, CertPrivKey);
m_SslConfig = std::move(Config);
}
else
{
// Reading the private key failed, reset the cert:
LOGWARNING("WebServer: Cannot read HTTPS certificate private key: -0x%x", -res2);
m_Cert.reset();
LOGWARNING("WebServer: Cannot read HTTPS certificate private key: -0x%x", -res);
}
}
else
@ -108,7 +115,7 @@ bool cHTTPServer::Initialize(void)
}
// Notify the admin about the HTTPS / HTTP status
if (m_Cert.get() == nullptr)
if (m_SslConfig == nullptr)
{
LOGWARNING("WebServer: The server will run in unsecured HTTP mode.");
LOGINFO("Put a valid HTTPS certificate in file 'webadmin/httpscert.crt' and its corresponding private key to 'webadmin/httpskey.pem' (without any password) to enable HTTPS support");
@ -184,9 +191,9 @@ cTCPLink::cCallbacksPtr cHTTPServer::OnIncomingConnection(const AString & a_Remo
UNUSED(a_RemoteIPAddress);
UNUSED(a_RemotePort);
if (m_Cert.get() != nullptr)
if (m_SslConfig != nullptr)
{
return std::make_shared<cSslHTTPServerConnection>(*this, m_Cert, m_CertPrivKey);
return std::make_shared<cSslHTTPServerConnection>(*this, m_SslConfig);
}
else
{

View File

@ -1,4 +1,4 @@

// HTTPServer.h
// Declares the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing
@ -11,8 +11,8 @@
#include "../OSSupport/Network.h"
#include "../IniFile.h"
#include "PolarSSL++/CryptoKey.h"
#include "PolarSSL++/X509Cert.h"
#include "mbedTLS++/CryptoKey.h"
#include "mbedTLS++/X509Cert.h"
@ -21,6 +21,7 @@
// fwd:
class cHTTPIncomingRequest;
class cHTTPServerConnection;
class cSslConfig;
@ -70,11 +71,8 @@ protected:
/** The callbacks to call for various events */
cCallbacks * m_Callbacks;
/** The server certificate to use for the SSL connections */
cX509CertPtr m_Cert;
/** The private key for m_Cert. */
cCryptoKeyPtr m_CertPrivKey;
/** Configuration for server ssl connections. */
std::shared_ptr<const cSslConfig> m_SslConfig;
/** Called by cHTTPServerListenCallbacks when there's a new incoming connection.

View File

@ -1,4 +1,4 @@

// SslHTTPConnection.cpp
// Implements the cSslHTTPServerConnection class representing a HTTP connection made over a SSL link
@ -11,14 +11,18 @@
cSslHTTPServerConnection::cSslHTTPServerConnection(cHTTPServer & a_HTTPServer, const cX509CertPtr & a_Cert, const cCryptoKeyPtr & a_PrivateKey) :
cSslHTTPServerConnection::cSslHTTPServerConnection(cHTTPServer & a_HTTPServer, std::shared_ptr<const cSslConfig> a_Config):
super(a_HTTPServer),
m_Ssl(64000),
m_Cert(a_Cert),
m_PrivateKey(a_PrivateKey)
m_Ssl(64000)
{
m_Ssl.Initialize(false);
m_Ssl.SetOwnCert(a_Cert, a_PrivateKey);
if (a_Config != nullptr)
{
m_Ssl.Initialize(a_Config);
}
else
{
m_Ssl.Initialize(false);
}
}
@ -59,7 +63,7 @@ void cSslHTTPServerConnection::OnReceivedData(const char * a_Data, size_t a_Size
// The link may have closed while processing the data, bail out:
return;
}
else if (NumRead == POLARSSL_ERR_NET_WANT_READ)
else if (NumRead == MBEDTLS_ERR_SSL_WANT_READ)
{
// SSL requires us to send data to peer first, do so by "sending" empty data:
SendData(nullptr, 0);

View File

@ -1,4 +1,4 @@

// SslHTTPServerConnection.h
// Declares the cSslHTTPServerConnection class representing a HTTP connection made over an SSL link
@ -10,7 +10,7 @@
#pragma once
#include "HTTPServerConnection.h"
#include "PolarSSL++/BufferedSslContext.h"
#include "mbedTLS++/BufferedSslContext.h"
@ -24,19 +24,13 @@ class cSslHTTPServerConnection :
public:
/** Creates a new connection on the specified server.
Sends the specified cert as the server certificate, uses the private key for decryption. */
cSslHTTPServerConnection(cHTTPServer & a_HTTPServer, const cX509CertPtr & a_Cert, const cCryptoKeyPtr & a_PrivateKey);
cSslHTTPServerConnection(cHTTPServer & a_HTTPServer, std::shared_ptr<const cSslConfig> a_Config);
virtual ~cSslHTTPServerConnection() override;
protected:
cBufferedSslContext m_Ssl;
/** The certificate to send to the client */
cX509CertPtr m_Cert;
/** The private key used for the certificate */
cCryptoKeyPtr m_PrivateKey;
// cHTTPConnection overrides:
virtual void OnReceivedData(const char * a_Data, size_t a_Size) override; // Data is received from the client
virtual void SendData(const void * a_Data, size_t a_Size) override; // Data is to be sent to client

View File

@ -7,8 +7,8 @@
#include "UrlClient.h"
#include "UrlParser.h"
#include "HTTPMessageParser.h"
#include "../PolarSSL++/X509Cert.h"
#include "../PolarSSL++/CryptoKey.h"
#include "../mbedTLS++/X509Cert.h"
#include "../mbedTLS++/CryptoKey.h"

View File

@ -1,10 +1,11 @@

// TCPLinkImpl.cpp
// Implements the cTCPLinkImpl class implementing the TCP link functionality
#include "Globals.h"
#include "TCPLinkImpl.h"
#include "mbedTLS++/SslConfig.h"
#include "NetworkSingleton.h"
#include "ServerHandleImpl.h"
#include "event2/buffer.h"
@ -245,26 +246,29 @@ AString cTCPLinkImpl::StartTLSClient(
{
return "TLS is already active on this link";
}
if (
((a_OwnCert == nullptr) && (a_OwnPrivKey != nullptr)) ||
((a_OwnCert != nullptr) && (a_OwnPrivKey != nullptr))
)
if ((a_OwnCert == nullptr) != (a_OwnPrivKey == nullptr))
{
return "Either provide both the certificate and private key, or neither";
}
// Create the TLS context:
m_TlsContext.reset(new cLinkTlsContext(*this));
m_TlsContext->Initialize(true);
m_TlsContext = std::make_shared<cLinkTlsContext>(*this);
if (a_OwnCert != nullptr)
{
m_TlsContext->SetOwnCert(a_OwnCert, a_OwnPrivKey);
auto Config = cSslConfig::MakeDefaultConfig(true);
Config->SetOwnCert(std::move(a_OwnCert), std::move(a_OwnPrivKey));
m_TlsContext->Initialize(Config);
}
else
{
m_TlsContext->Initialize(true);
}
m_TlsContext->SetSelf(cLinkTlsContextWPtr(m_TlsContext));
// Start the handshake:
m_TlsContext->Handshake();
return "";
return {};
}
@ -282,15 +286,18 @@ AString cTCPLinkImpl::StartTLSServer(
{
return "TLS is already active on this link";
}
if ((a_OwnCert == nullptr) || (a_OwnPrivKey == nullptr))
if ((a_OwnCert == nullptr) || (a_OwnPrivKey == nullptr))
{
return "Provide the server certificate and private key";
}
// Create the TLS context:
m_TlsContext.reset(new cLinkTlsContext(*this));
m_TlsContext->Initialize(false);
m_TlsContext->SetOwnCert(a_OwnCert, a_OwnPrivKey);
m_TlsContext = std::make_shared<cLinkTlsContext>(*this);
{
auto Config = cSslConfig::MakeDefaultConfig(false);
Config->SetOwnCert(a_OwnCert, a_OwnPrivKey);
m_TlsContext->Initialize(std::move(Config));
}
m_TlsContext->SetSelf(cLinkTlsContextWPtr(m_TlsContext));
// Push the initial data:
@ -298,7 +305,7 @@ AString cTCPLinkImpl::StartTLSServer(
// Start the handshake:
m_TlsContext->Handshake();
return "";
return {};
}
@ -659,7 +666,7 @@ int cTCPLinkImpl::cLinkTlsContext::ReceiveEncrypted(unsigned char * a_Buffer, si
// If there's nothing queued in the buffer, report empty buffer:
if (m_EncryptedData.empty())
{
return POLARSSL_ERR_NET_WANT_READ;
return MBEDTLS_ERR_SSL_WANT_READ;
}
// Copy as much data as possible to the provided buffer:

View File

@ -14,7 +14,7 @@
#include "Network.h"
#include <event2/event.h>
#include <event2/bufferevent.h>
#include "../PolarSSL++/SslContext.h"
#include "../mbedTLS++/SslContext.h"

View File

@ -1,307 +0,0 @@
// SslContext.cpp
// Implements the cSslContext class that holds everything a single SSL context needs to function
#include "Globals.h"
#include "SslContext.h"
#include "EntropyContext.h"
#include "CtrDrbgContext.h"
#include "polarssl/debug.h"
cSslContext::cSslContext(void) :
m_IsValid(false),
m_HasHandshaken(false)
{
memset(&m_Ssl, 0, sizeof(m_Ssl));
}
cSslContext::~cSslContext()
{
if (m_IsValid)
{
ssl_free(&m_Ssl);
}
}
int cSslContext::Initialize(bool a_IsClient, const std::shared_ptr<cCtrDrbgContext> & a_CtrDrbg)
{
// Check double-initialization:
if (m_IsValid)
{
LOGWARNING("SSL: Double initialization is not supported.");
return POLARSSL_ERR_SSL_BAD_INPUT_DATA; // There is no return value well-suited for this, reuse this one.
}
// Set the CtrDrbg context, create a new one if needed:
m_CtrDrbg = a_CtrDrbg;
if (m_CtrDrbg.get() == nullptr)
{
m_CtrDrbg.reset(new cCtrDrbgContext);
m_CtrDrbg->Initialize("Cuberite", 8);
}
// Initialize PolarSSL's structures:
memset(&m_Ssl, 0, sizeof(m_Ssl));
int res = ssl_init(&m_Ssl);
if (res != 0)
{
return res;
}
ssl_set_endpoint(&m_Ssl, a_IsClient ? SSL_IS_CLIENT : SSL_IS_SERVER);
ssl_set_authmode(&m_Ssl, SSL_VERIFY_NONE); // We cannot verify because we don't have a CA chain, required by PolarSSL, implemented yet (TODO)
ssl_set_rng(&m_Ssl, ctr_drbg_random, &m_CtrDrbg->m_CtrDrbg);
ssl_set_bio(&m_Ssl, ReceiveEncrypted, this, SendEncrypted, this);
#ifdef _DEBUG
/*
// These functions allow us to debug SSL and certificate problems, but produce way too much output,
// so they're disabled until someone needs them
ssl_set_dbg(&m_Ssl, &SSLDebugMessage, this);
debug_set_threshold(2);
ssl_set_verify(&m_Ssl, &SSLVerifyCert, this);
//*/
/*
// Set ciphersuite to the easiest one to decode, so that the connection can be wireshark-decoded:
static const int CipherSuites[] =
{
TLS_RSA_WITH_RC4_128_MD5,
TLS_RSA_WITH_RC4_128_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
0, // Must be 0-terminated!
};
ssl_set_ciphersuites(&m_Ssl, CipherSuites);
//*/
#endif
m_IsValid = true;
return 0;
}
void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cRsaPrivateKeyPtr & a_OwnCertPrivKey)
{
ASSERT(m_IsValid); // Call Initialize() first
// Check that both the cert and the key is valid:
if ((a_OwnCert.get() == nullptr) || (a_OwnCertPrivKey.get() == nullptr))
{
LOGWARNING("SSL: Own certificate is not valid, skipping the set.");
return;
}
// Make sure we have the cert stored for later, PolarSSL only uses the cert later on
m_OwnCert = a_OwnCert;
m_OwnCertPrivKey = a_OwnCertPrivKey;
// Set into the context:
ssl_set_own_cert_rsa(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey->GetInternal());
}
void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cCryptoKeyPtr & a_OwnCertPrivKey)
{
ASSERT(m_IsValid); // Call Initialize() first
// Check that both the cert and the key is valid:
if ((a_OwnCert.get() == nullptr) || (a_OwnCertPrivKey.get() == nullptr))
{
LOGWARNING("SSL: Own certificate is not valid, skipping the set.");
return;
}
// Make sure we have the cert stored for later, PolarSSL only uses the cert later on
m_OwnCert = a_OwnCert;
m_OwnCertPrivKey2 = a_OwnCertPrivKey;
// Set into the context:
ssl_set_own_cert(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey2->GetInternal());
}
void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName)
{
ASSERT(m_IsValid); // Call Initialize() first
// Store the data in our internal buffers, to avoid losing the pointers later on
// PolarSSL will need these after this call returns, and the caller may move / delete the data before that:
m_ExpectedPeerName = a_ExpectedPeerName;
m_CACerts = a_CACert;
// Set the trusted CA root cert store:
ssl_set_authmode(&m_Ssl, SSL_VERIFY_REQUIRED);
ssl_set_ca_chain(&m_Ssl, m_CACerts->GetInternal(), nullptr, m_ExpectedPeerName.empty() ? nullptr : m_ExpectedPeerName.c_str());
}
int cSslContext::WritePlain(const void * a_Data, size_t a_NumBytes)
{
ASSERT(m_IsValid); // Need to call Initialize() first
if (!m_HasHandshaken)
{
int res = Handshake();
if (res != 0)
{
return res;
}
}
return ssl_write(&m_Ssl, reinterpret_cast<const unsigned char *>(a_Data), a_NumBytes);
}
int cSslContext::ReadPlain(void * a_Data, size_t a_MaxBytes)
{
ASSERT(m_IsValid); // Need to call Initialize() first
if (!m_HasHandshaken)
{
int res = Handshake();
if (res != 0)
{
return res;
}
}
return ssl_read(&m_Ssl, reinterpret_cast<unsigned char *>(a_Data), a_MaxBytes);
}
int cSslContext::Handshake(void)
{
ASSERT(m_IsValid); // Need to call Initialize() first
ASSERT(!m_HasHandshaken); // Must not call twice
int res = ssl_handshake(&m_Ssl);
if (res == 0)
{
m_HasHandshaken = true;
}
return res;
}
int cSslContext::NotifyClose(void)
{
return ssl_close_notify(&m_Ssl);
}
#ifdef _DEBUG
void cSslContext::SSLDebugMessage(void * a_UserParam, int a_Level, const char * a_Text)
{
if (a_Level > 3)
{
// Don't want the trace messages
return;
}
// Remove the terminating LF:
size_t len = strlen(a_Text) - 1;
while ((len > 0) && (a_Text[len] <= 32))
{
len--;
}
AString Text(a_Text, len + 1);
LOGD("SSL (%d): %s", a_Level, Text.c_str());
}
int cSslContext::SSLVerifyCert(void * a_This, x509_crt * a_Crt, int a_Depth, int * a_Flags)
{
char buf[1024];
UNUSED(a_This);
LOG("Verify requested for (Depth %d):", a_Depth);
x509_crt_info(buf, sizeof(buf) - 1, "", a_Crt);
LOG("%s", buf);
int Flags = *a_Flags;
if ((Flags & BADCERT_EXPIRED) != 0)
{
LOG(" ! server certificate has expired");
}
if ((Flags & BADCERT_REVOKED) != 0)
{
LOG(" ! server certificate has been revoked");
}
if ((Flags & BADCERT_CN_MISMATCH) != 0)
{
LOG(" ! CN mismatch");
}
if ((Flags & BADCERT_NOT_TRUSTED) != 0)
{
LOG(" ! self-signed or not signed by a trusted CA");
}
if ((Flags & BADCRL_NOT_TRUSTED) != 0)
{
LOG(" ! CRL not trusted");
}
if ((Flags & BADCRL_EXPIRED) != 0)
{
LOG(" ! CRL expired");
}
if ((Flags & BADCERT_OTHER) != 0)
{
LOG(" ! other (unknown) flag");
}
if (Flags == 0)
{
LOG(" This certificate has no flags");
}
return 0;
}
#endif // _DEBUG

View File

@ -11,7 +11,7 @@
#include "../IniFile.h"
#include "json/json.h"
#include "PolarSSL++/BlockingSslClientSocket.h"
#include "mbedTLS++/BlockingSslClientSocket.h"

View File

@ -1,4 +1,4 @@

// MojangAPI.cpp
// Implements the cMojangAPI class representing the various API points provided by Mojang's webservices, and a cache for their results
@ -9,7 +9,8 @@
#include "SQLiteCpp/Statement.h"
#include "../IniFile.h"
#include "json/json.h"
#include "PolarSSL++/BlockingSslClientSocket.h"
#include "mbedTLS++/BlockingSslClientSocket.h"
#include "mbedTLS++/SslConfig.h"
#include "../RankManager.h"
#include "../OSSupport/IsThread.h"
#include "../Root.h"
@ -39,9 +40,9 @@ const int MAX_PER_QUERY = 100;
/** Returns the CA certificates that should be trusted for Mojang-related connections. */
static const AString & GetCACerts(void)
static cX509CertPtr GetCACerts(void)
{
static const AString Cert(
static const char CertString[] =
// GeoTrust root CA cert
// Currently used for signing *.mojang.com's cert
// Exported from Mozilla Firefox's built-in CA repository
@ -140,9 +141,33 @@ static const AString & GetCACerts(void)
"VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n"
"WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n"
"-----END CERTIFICATE-----\n"
);
;
return Cert;
static auto X509Cert = [&]()
{
auto Cert = std::make_shared<cX509Cert>();
VERIFY(0 == Cert->Parse(CertString, sizeof(CertString)));
return Cert;
}();
return X509Cert;
}
/** Returns the config to be used for secure requests. */
static std::shared_ptr<const cSslConfig> GetSslConfig()
{
static const std::shared_ptr<const cSslConfig> Config = []()
{
auto Conf = cSslConfig::MakeDefaultConfig(true);
Conf->SetCACerts(GetCACerts());
Conf->SetAuthMode(eSslAuthMode::Required);
return Conf;
}();
return Config;
}
@ -432,7 +457,8 @@ bool cMojangAPI::SecureRequest(const AString & a_ServerName, const AString & a_R
{
// Connect the socket:
cBlockingSslClientSocket Socket;
Socket.SetTrustedRootCertsFromString(GetCACerts(), a_ServerName);
Socket.SetSslConfig(GetSslConfig());
Socket.SetExpectedPeerName(a_ServerName);
if (!Socket.Connect(a_ServerName, 443))
{
LOGWARNING("%s: Can't connect to %s: %s", __FUNCTION__, a_ServerName.c_str(), Socket.GetLastErrorText().c_str());
@ -452,13 +478,13 @@ bool cMojangAPI::SecureRequest(const AString & a_ServerName, const AString & a_R
{
int ret = Socket.Receive(buf, sizeof(buf));
if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
if ((ret == MBEDTLS_ERR_SSL_WANT_READ) || (ret == MBEDTLS_ERR_SSL_WANT_WRITE))
{
// This value should never be returned, it is handled internally by cBlockingSslClientSocket
LOGWARNING("%s: SSL reading failed internally", __FUNCTION__);
return false;
}
if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
{
break;
}

View File

@ -11,7 +11,7 @@ Implements the 1.8 protocol classes:
#include "json/json.h"
#include "Protocol_1_8.h"
#include "ChunkDataSerializer.h"
#include "PolarSSL++/Sha1Checksum.h"
#include "mbedTLS++/Sha1Checksum.h"
#include "Packetizer.h"
#include "../ClientHandle.h"

View File

@ -29,8 +29,8 @@ Declares the 1.8 protocol classes:
#pragma warning(pop)
#endif
#include "PolarSSL++/AesCfb128Decryptor.h"
#include "PolarSSL++/AesCfb128Encryptor.h"
#include "mbedTLS++/AesCfb128Decryptor.h"
#include "mbedTLS++/AesCfb128Encryptor.h"

View File

@ -17,7 +17,7 @@ Implements the 1.9 protocol classes:
#include "json/json.h"
#include "Protocol_1_9.h"
#include "ChunkDataSerializer.h"
#include "PolarSSL++/Sha1Checksum.h"
#include "mbedTLS++/Sha1Checksum.h"
#include "Packetizer.h"
#include "../ClientHandle.h"

View File

@ -35,8 +35,8 @@ Declares the 1.9 protocol classes:
#pragma warning(pop)
#endif
#include "PolarSSL++/AesCfb128Decryptor.h"
#include "PolarSSL++/AesCfb128Encryptor.h"
#include "mbedTLS++/AesCfb128Decryptor.h"
#include "mbedTLS++/AesCfb128Encryptor.h"

View File

@ -22,7 +22,7 @@
#pragma warning(disable:4702)
#endif
#include "PolarSSL++/RsaPrivateKey.h"
#include "mbedTLS++/RsaPrivateKey.h"
#ifdef _MSC_VER
#pragma warning(pop)

View File

@ -5,7 +5,7 @@
#include "Globals.h"
#include "UUID.h"
#include "polarssl/md5.h"
#include "mbedtls/md5.h"
/** UUID normalised in textual form. */
@ -265,7 +265,7 @@ cUUID cUUID::GenerateVersion3(const AString & a_Name)
cUUID UUID;
// Generate an md5 checksum, and use it as base for the ID:
const Byte * ByteString = reinterpret_cast<const Byte *>(a_Name.data());
md5(ByteString, a_Name.length(), UUID.m_UUID.data());
mbedtls_md5(ByteString, a_Name.length(), UUID.m_UUID.data());
// Insert version number
UUID.m_UUID[6] = (UUID.m_UUID[6] & 0x0f) | 0x30;

View File

@ -1,4 +1,4 @@

// AesCfb128Decryptor.cpp
// Implements the cAesCfb128Decryptor class decrypting data using AES CFB-128
@ -10,10 +10,10 @@
cAesCfb128Decryptor::cAesCfb128Decryptor(void) :
m_IVOffset(0),
cAesCfb128Decryptor::cAesCfb128Decryptor(void):
m_IsValid(false)
{
mbedtls_aes_init(&m_Aes);
}
@ -23,7 +23,7 @@ cAesCfb128Decryptor::cAesCfb128Decryptor(void) :
cAesCfb128Decryptor::~cAesCfb128Decryptor()
{
// Clear the leftover in-memory data, so that they can't be accessed by a backdoor
memset(&m_Aes, 0, sizeof(m_Aes));
mbedtls_aes_free(&m_Aes);
}
@ -35,7 +35,7 @@ void cAesCfb128Decryptor::Init(const Byte a_Key[16], const Byte a_IV[16])
ASSERT(!IsValid()); // Cannot Init twice
memcpy(m_IV, a_IV, 16);
aes_setkey_enc(&m_Aes, a_Key, 128);
mbedtls_aes_setkey_enc(&m_Aes, a_Key, 128);
m_IsValid = true;
}
@ -46,19 +46,7 @@ void cAesCfb128Decryptor::Init(const Byte a_Key[16], const Byte a_IV[16])
void cAesCfb128Decryptor::ProcessData(Byte * a_DecryptedOut, const Byte * a_EncryptedIn, size_t a_Length)
{
ASSERT(IsValid()); // Must Init() first
// PolarSSL doesn't support AES-CFB8, need to implement it manually:
for (size_t i = 0; i < a_Length; i++)
{
Byte Buffer[sizeof(m_IV)];
aes_crypt_ecb(&m_Aes, AES_ENCRYPT, m_IV, Buffer);
for (size_t idx = 0; idx < sizeof(m_IV) - 1; idx++)
{
m_IV[idx] = m_IV[idx + 1];
}
m_IV[sizeof(m_IV) - 1] = a_EncryptedIn[i];
a_DecryptedOut[i] = a_EncryptedIn[i] ^ Buffer[0];
}
mbedtls_aes_crypt_cfb8(&m_Aes, MBEDTLS_AES_DECRYPT, a_Length, m_IV, a_EncryptedIn, a_DecryptedOut);
}

View File

@ -1,4 +1,4 @@

// AesCfb128Decryptor.h
// Declares the cAesCfb128Decryptor class decrypting data using AES CFB-128
@ -9,7 +9,7 @@
#pragma once
#include "polarssl/aes.h"
#include "mbedtls/aes.h"
@ -33,14 +33,11 @@ public:
bool IsValid(void) const { return m_IsValid; }
protected:
aes_context m_Aes;
mbedtls_aes_context m_Aes;
/** The InitialVector, used by the CFB mode decryption */
Byte m_IV[16];
/** Current offset in the m_IV, used by the CFB mode decryption */
size_t m_IVOffset;
/** Indicates whether the object has been initialized with the Key / IV */
bool m_IsValid;
} ;

View File

@ -1,4 +1,4 @@

// AesCfb128Encryptor.cpp
// Implements the cAesCfb128Encryptor class encrypting data using AES CFB-128
@ -10,10 +10,10 @@
cAesCfb128Encryptor::cAesCfb128Encryptor(void) :
m_IVOffset(0),
cAesCfb128Encryptor::cAesCfb128Encryptor(void):
m_IsValid(false)
{
mbedtls_aes_init(&m_Aes);
}
@ -23,7 +23,7 @@ cAesCfb128Encryptor::cAesCfb128Encryptor(void) :
cAesCfb128Encryptor::~cAesCfb128Encryptor()
{
// Clear the leftover in-memory data, so that they can't be accessed by a backdoor
memset(&m_Aes, 0, sizeof(m_Aes));
mbedtls_aes_free(&m_Aes);
}
@ -33,10 +33,9 @@ cAesCfb128Encryptor::~cAesCfb128Encryptor()
void cAesCfb128Encryptor::Init(const Byte a_Key[16], const Byte a_IV[16])
{
ASSERT(!IsValid()); // Cannot Init twice
ASSERT(m_IVOffset == 0);