commit
014fab58e6
@ -36,14 +36,24 @@ set(SHARED_SRC
|
|||||||
../../src/StringUtils.cpp
|
../../src/StringUtils.cpp
|
||||||
../../src/Log.cpp
|
../../src/Log.cpp
|
||||||
../../src/MCLogger.cpp
|
../../src/MCLogger.cpp
|
||||||
../../src/Crypto.cpp
|
../../src/PolarSSL++/AesCfb128Decryptor.cpp
|
||||||
|
../../src/PolarSSL++/AesCfb128Encryptor.cpp
|
||||||
|
../../src/PolarSSL++/CtrDrbgContext.cpp
|
||||||
|
../../src/PolarSSL++/EntropyContext.cpp
|
||||||
|
../../src/PolarSSL++/PublicKey.cpp
|
||||||
|
../../src/PolarSSL++/RsaPrivateKey.cpp
|
||||||
)
|
)
|
||||||
set(SHARED_HDR
|
set(SHARED_HDR
|
||||||
../../src/ByteBuffer.h
|
../../src/ByteBuffer.h
|
||||||
../../src/StringUtils.h
|
../../src/StringUtils.h
|
||||||
../../src/Log.h
|
../../src/Log.h
|
||||||
../../src/MCLogger.h
|
../../src/MCLogger.h
|
||||||
../../src/Crypto.h
|
../../src/PolarSSL++/AesCfb128Decryptor.h
|
||||||
|
../../src/PolarSSL++/AesCfb128Encryptor.h
|
||||||
|
../../src/PolarSSL++/CtrDrbgContext.h
|
||||||
|
../../src/PolarSSL++/EntropyContext.h
|
||||||
|
../../src/PolarSSL++/PublicKey.h
|
||||||
|
../../src/PolarSSL++/RsaPrivateKey.h
|
||||||
)
|
)
|
||||||
set(SHARED_OSS_SRC
|
set(SHARED_OSS_SRC
|
||||||
../../src/OSSupport/CriticalSection.cpp
|
../../src/OSSupport/CriticalSection.cpp
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "PolarSSL++/PublicKey.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <direct.h> // For _mkdir()
|
#include <direct.h> // For _mkdir()
|
||||||
@ -471,7 +472,7 @@ bool cConnection::SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer)
|
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer)
|
||||||
{
|
{
|
||||||
DataLog(a_Data, a_Size, "Encrypting %d bytes to %s", a_Size, a_Peer);
|
DataLog(a_Data, a_Size, "Encrypting %d bytes to %s", a_Size, a_Peer);
|
||||||
const Byte * Data = (const Byte *)a_Data;
|
const Byte * Data = (const Byte *)a_Data;
|
||||||
@ -495,7 +496,7 @@ bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryp
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
|
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
|
||||||
{
|
{
|
||||||
AString All;
|
AString All;
|
||||||
a_Data.ReadAll(All);
|
a_Data.ReadAll(All);
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "ByteBuffer.h"
|
#include "ByteBuffer.h"
|
||||||
#include "OSSupport/Timer.h"
|
#include "OSSupport/Timer.h"
|
||||||
|
#include "PolarSSL++/AesCfb128Decryptor.h"
|
||||||
|
#include "PolarSSL++/AesCfb128Encryptor.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -66,8 +68,8 @@ protected:
|
|||||||
cByteBuffer m_ClientBuffer;
|
cByteBuffer m_ClientBuffer;
|
||||||
cByteBuffer m_ServerBuffer;
|
cByteBuffer m_ServerBuffer;
|
||||||
|
|
||||||
cAESCFBDecryptor m_ServerDecryptor;
|
cAesCfb128Decryptor m_ServerDecryptor;
|
||||||
cAESCFBEncryptor m_ServerEncryptor;
|
cAesCfb128Encryptor m_ServerEncryptor;
|
||||||
|
|
||||||
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
|
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
|
||||||
|
|
||||||
@ -109,10 +111,10 @@ protected:
|
|||||||
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
|
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
|
||||||
|
|
||||||
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
||||||
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer);
|
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer);
|
||||||
|
|
||||||
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
||||||
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
|
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
|
||||||
|
|
||||||
/// Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped
|
/// Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped
|
||||||
bool DecodeClientsPackets(const char * a_Data, int a_Size);
|
bool DecodeClientsPackets(const char * a_Data, int a_Size);
|
||||||
|
@ -216,6 +216,20 @@ typedef unsigned char Byte;
|
|||||||
// Pretty much the same as ASSERT() but stays in Release builds
|
// Pretty much the same as ASSERT() but stays in Release builds
|
||||||
#define VERIFY( x ) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), exit(1), 0 ) )
|
#define VERIFY( x ) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), exit(1), 0 ) )
|
||||||
|
|
||||||
|
// Allow both Older versions of MSVC and newer versions of everything use a shared_ptr:
|
||||||
|
// Note that we cannot typedef, because C++ doesn't allow (partial) templates to be typedeffed.
|
||||||
|
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||||
|
// MSVC before 2010 doesn't have std::shared_ptr, but has std::tr1::shared_ptr, defined in <memory> included earlier
|
||||||
|
#define SharedPtr std::tr1::shared_ptr
|
||||||
|
#elif (__cplusplus >= 201103L)
|
||||||
|
// C++11 has std::shared_ptr in <memory>, included earlier
|
||||||
|
#define SharedPtr std::shared_ptr
|
||||||
|
#else
|
||||||
|
// C++03 has std::tr1::shared_ptr in <tr1/memory>
|
||||||
|
#include <tr1/memory>
|
||||||
|
#define SharedPtr std::tr1::shared_ptr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -232,12 +246,6 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "../../src/Crypto.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define LOGERROR printf
|
#define LOGERROR printf
|
||||||
#define LOGINFO printf
|
#define LOGINFO printf
|
||||||
#define LOGWARNING printf
|
#define LOGWARNING printf
|
||||||
|
@ -20,7 +20,7 @@ You need to set the server *not* to verify usernames ("online-mode=false" in ser
|
|||||||
|
|
||||||
|
|
||||||
ProtoProxy is not much dependent on the protocol - it will work with unknown packets, it just won't parse them into human-readable format.
|
ProtoProxy is not much dependent on the protocol - it will work with unknown packets, it just won't parse them into human-readable format.
|
||||||
The latest protocol which has been tested is 1.6.1 (#73).
|
The latest protocol which has been tested is 1.7.9 (#5).
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "PolarSSL++/RsaPrivateKey.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +19,7 @@
|
|||||||
class cServer
|
class cServer
|
||||||
{
|
{
|
||||||
SOCKET m_ListenSocket;
|
SOCKET m_ListenSocket;
|
||||||
cRSAPrivateKey m_PrivateKey;
|
cRsaPrivateKey m_PrivateKey;
|
||||||
AString m_PublicKeyDER;
|
AString m_PublicKeyDER;
|
||||||
short m_ConnectPort;
|
short m_ConnectPort;
|
||||||
|
|
||||||
@ -27,7 +29,7 @@ public:
|
|||||||
int Init(short a_ListenPort, short a_ConnectPort);
|
int Init(short a_ListenPort, short a_ConnectPort);
|
||||||
void Run(void);
|
void Run(void);
|
||||||
|
|
||||||
cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
||||||
const AString & GetPublicKeyDER (void) { return m_PublicKeyDER; }
|
const AString & GetPublicKeyDER (void) { return m_PublicKeyDER; }
|
||||||
|
|
||||||
short GetConnectPort(void) const { return m_ConnectPort; }
|
short GetConnectPort(void) const { return m_ConnectPort; }
|
||||||
|
@ -171,7 +171,7 @@ cByteBuffer::~cByteBuffer()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cByteBuffer::Write(const char * a_Bytes, size_t a_Count)
|
bool cByteBuffer::Write(const void * a_Bytes, size_t a_Count)
|
||||||
{
|
{
|
||||||
CHECK_THREAD;
|
CHECK_THREAD;
|
||||||
CheckValid();
|
CheckValid();
|
||||||
@ -187,13 +187,14 @@ bool cByteBuffer::Write(const char * a_Bytes, size_t a_Count)
|
|||||||
}
|
}
|
||||||
ASSERT(m_BufferSize >= m_WritePos);
|
ASSERT(m_BufferSize >= m_WritePos);
|
||||||
size_t TillEnd = m_BufferSize - m_WritePos;
|
size_t TillEnd = m_BufferSize - m_WritePos;
|
||||||
|
const char * Bytes = (const char *)a_Bytes;
|
||||||
if (TillEnd <= a_Count)
|
if (TillEnd <= a_Count)
|
||||||
{
|
{
|
||||||
// Need to wrap around the ringbuffer end
|
// Need to wrap around the ringbuffer end
|
||||||
if (TillEnd > 0)
|
if (TillEnd > 0)
|
||||||
{
|
{
|
||||||
memcpy(m_Buffer + m_WritePos, a_Bytes, TillEnd);
|
memcpy(m_Buffer + m_WritePos, Bytes, TillEnd);
|
||||||
a_Bytes += TillEnd;
|
Bytes += TillEnd;
|
||||||
a_Count -= TillEnd;
|
a_Count -= TillEnd;
|
||||||
WrittenBytes = TillEnd;
|
WrittenBytes = TillEnd;
|
||||||
}
|
}
|
||||||
@ -203,7 +204,7 @@ bool cByteBuffer::Write(const char * a_Bytes, size_t a_Count)
|
|||||||
// We're guaranteed that we'll fit in a single write op
|
// We're guaranteed that we'll fit in a single write op
|
||||||
if (a_Count > 0)
|
if (a_Count > 0)
|
||||||
{
|
{
|
||||||
memcpy(m_Buffer + m_WritePos, a_Bytes, a_Count);
|
memcpy(m_Buffer + m_WritePos, Bytes, a_Count);
|
||||||
m_WritePos += a_Count;
|
m_WritePos += a_Count;
|
||||||
WrittenBytes += a_Count;
|
WrittenBytes += a_Count;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
~cByteBuffer();
|
~cByteBuffer();
|
||||||
|
|
||||||
/// Writes the bytes specified to the ringbuffer. Returns true if successful, false if not
|
/// Writes the bytes specified to the ringbuffer. Returns true if successful, false if not
|
||||||
bool Write(const char * a_Bytes, size_t a_Count);
|
bool Write(const void * a_Bytes, size_t a_Count);
|
||||||
|
|
||||||
/// Returns the number of bytes that can be successfully written to the ringbuffer
|
/// Returns the number of bytes that can be successfully written to the ringbuffer
|
||||||
size_t GetFreeSpace(void) const;
|
size_t GetFreeSpace(void) const;
|
||||||
|
@ -5,7 +5,7 @@ include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/")
|
|||||||
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/jsoncpp/include")
|
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/jsoncpp/include")
|
||||||
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/polarssl/include")
|
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/polarssl/include")
|
||||||
|
|
||||||
set(FOLDERS OSSupport HTTPServer Items Blocks Protocol Generating)
|
set(FOLDERS OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++)
|
||||||
set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities Generating/Prefabs)
|
set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities Generating/Prefabs)
|
||||||
|
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ endif ()
|
|||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
target_link_libraries(${EXECUTABLE} OSSupport HTTPServer Bindings Items Blocks)
|
target_link_libraries(${EXECUTABLE} OSSupport HTTPServer Bindings Items Blocks)
|
||||||
target_link_libraries(${EXECUTABLE} Protocol Generating Generating_Prefabs WorldStorage)
|
target_link_libraries(${EXECUTABLE} Protocol Generating Generating_Prefabs WorldStorage)
|
||||||
target_link_libraries(${EXECUTABLE} Mobs Entities Simulator UI BlockEntities)
|
target_link_libraries(${EXECUTABLE} Mobs Entities Simulator UI BlockEntities PolarSSL++)
|
||||||
endif ()
|
endif ()
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib)
|
target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib)
|
||||||
|
509
src/Crypto.cpp
509
src/Crypto.cpp
@ -1,509 +0,0 @@
|
|||||||
|
|
||||||
// Crypto.cpp
|
|
||||||
|
|
||||||
// Implements classes that wrap the cryptographic code library
|
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
#include "Crypto.h"
|
|
||||||
|
|
||||||
#include "polarssl/pk.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Self-test the hash formatting for known values:
|
|
||||||
// sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48
|
|
||||||
// sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1
|
|
||||||
// sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6
|
|
||||||
|
|
||||||
class Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Test(void)
|
|
||||||
{
|
|
||||||
AString DigestNotch, DigestJeb, DigestSimon;
|
|
||||||
Byte Digest[20];
|
|
||||||
cSHA1Checksum Checksum;
|
|
||||||
Checksum.Update((const Byte *)"Notch", 5);
|
|
||||||
Checksum.Finalize(Digest);
|
|
||||||
cSHA1Checksum::DigestToJava(Digest, DigestNotch);
|
|
||||||
Checksum.Restart();
|
|
||||||
Checksum.Update((const Byte *)"jeb_", 4);
|
|
||||||
Checksum.Finalize(Digest);
|
|
||||||
cSHA1Checksum::DigestToJava(Digest, DigestJeb);
|
|
||||||
Checksum.Restart();
|
|
||||||
Checksum.Update((const Byte *)"simon", 5);
|
|
||||||
Checksum.Finalize(Digest);
|
|
||||||
cSHA1Checksum::DigestToJava(Digest, DigestSimon);
|
|
||||||
printf("Notch: \"%s\"\n", DigestNotch.c_str());
|
|
||||||
printf("jeb_: \"%s\"\n", DigestJeb.c_str());
|
|
||||||
printf("simon: \"%s\"\n", DigestSimon.c_str());
|
|
||||||
assert(DigestNotch == "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48");
|
|
||||||
assert(DigestJeb == "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1");
|
|
||||||
assert(DigestSimon == "88e16a1019277b15d58faf0541e11910eb756f6");
|
|
||||||
}
|
|
||||||
} test;
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// cRSAPrivateKey:
|
|
||||||
|
|
||||||
cRSAPrivateKey::cRSAPrivateKey(void)
|
|
||||||
{
|
|
||||||
rsa_init(&m_Rsa, RSA_PKCS_V15, 0);
|
|
||||||
InitRnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cRSAPrivateKey::cRSAPrivateKey(const cRSAPrivateKey & a_Other)
|
|
||||||
{
|
|
||||||
rsa_init(&m_Rsa, RSA_PKCS_V15, 0);
|
|
||||||
rsa_copy(&m_Rsa, &a_Other.m_Rsa);
|
|
||||||
InitRnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cRSAPrivateKey::~cRSAPrivateKey()
|
|
||||||
{
|
|
||||||
entropy_free(&m_Entropy);
|
|
||||||
rsa_free(&m_Rsa);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cRSAPrivateKey::InitRnd(void)
|
|
||||||
{
|
|
||||||
entropy_init(&m_Entropy);
|
|
||||||
const unsigned char pers[] = "rsa_genkey";
|
|
||||||
ctr_drbg_init(&m_Ctr_drbg, entropy_func, &m_Entropy, pers, sizeof(pers) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cRSAPrivateKey::Generate(unsigned a_KeySizeBits)
|
|
||||||
{
|
|
||||||
if (rsa_gen_key(&m_Rsa, ctr_drbg_random, &m_Ctr_drbg, a_KeySizeBits, 65537) != 0)
|
|
||||||
{
|
|
||||||
// Key generation failed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString cRSAPrivateKey::GetPubKeyDER(void)
|
|
||||||
{
|
|
||||||
class cPubKey
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cPubKey(rsa_context * a_Rsa) :
|
|
||||||
m_IsValid(false)
|
|
||||||
{
|
|
||||||
pk_init(&m_Key);
|
|
||||||
if (pk_init_ctx(&m_Key, pk_info_from_type(POLARSSL_PK_RSA)) != 0)
|
|
||||||
{
|
|
||||||
ASSERT(!"Cannot init PrivKey context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rsa_copy(pk_rsa(m_Key), a_Rsa) != 0)
|
|
||||||
{
|
|
||||||
ASSERT(!"Cannot copy PrivKey to PK context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_IsValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
~cPubKey()
|
|
||||||
{
|
|
||||||
if (m_IsValid)
|
|
||||||
{
|
|
||||||
pk_free(&m_Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator pk_context * (void) { return &m_Key; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool m_IsValid;
|
|
||||||
pk_context m_Key;
|
|
||||||
} PkCtx(&m_Rsa);
|
|
||||||
|
|
||||||
unsigned char buf[3000];
|
|
||||||
int res = pk_write_pubkey_der(PkCtx, buf, sizeof(buf));
|
|
||||||
if (res < 0)
|
|
||||||
{
|
|
||||||
return AString();
|
|
||||||
}
|
|
||||||
return AString((const char *)(buf + sizeof(buf) - res), (size_t)res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cRSAPrivateKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
|
||||||
{
|
|
||||||
if (a_EncryptedLength < m_Rsa.len)
|
|
||||||
{
|
|
||||||
LOGD("%s: Invalid a_EncryptedLength: got %u, exp at least %u",
|
|
||||||
__FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len)
|
|
||||||
);
|
|
||||||
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a_DecryptedMaxLength < m_Rsa.len)
|
|
||||||
{
|
|
||||||
LOGD("%s: Invalid a_DecryptedMaxLength: got %u, exp at least %u",
|
|
||||||
__FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len)
|
|
||||||
);
|
|
||||||
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
size_t DecryptedLength;
|
|
||||||
int res = rsa_pkcs1_decrypt(
|
|
||||||
&m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PRIVATE, &DecryptedLength,
|
|
||||||
a_EncryptedData, a_DecryptedData, a_DecryptedMaxLength
|
|
||||||
);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return (int)DecryptedLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
|
||||||
{
|
|
||||||
if (a_EncryptedMaxLength < m_Rsa.len)
|
|
||||||
{
|
|
||||||
LOGD("%s: Invalid a_EncryptedMaxLength: got %u, exp at least %u",
|
|
||||||
__FUNCTION__, (unsigned)a_EncryptedMaxLength, (unsigned)(m_Rsa.len)
|
|
||||||
);
|
|
||||||
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a_PlainLength < m_Rsa.len)
|
|
||||||
{
|
|
||||||
LOGD("%s: Invalid a_PlainLength: got %u, exp at least %u",
|
|
||||||
__FUNCTION__, (unsigned)a_PlainLength, (unsigned)(m_Rsa.len)
|
|
||||||
);
|
|
||||||
ASSERT(!"Invalid a_PlainLength!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int res = rsa_pkcs1_encrypt(
|
|
||||||
&m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PRIVATE,
|
|
||||||
a_PlainLength, a_PlainData, a_EncryptedData
|
|
||||||
);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return (int)m_Rsa.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// cPublicKey:
|
|
||||||
|
|
||||||
cPublicKey::cPublicKey(const AString & a_PublicKeyDER)
|
|
||||||
{
|
|
||||||
pk_init(&m_Pk);
|
|
||||||
if (pk_parse_public_key(&m_Pk, (const Byte *)a_PublicKeyDER.data(), a_PublicKeyDER.size()) != 0)
|
|
||||||
{
|
|
||||||
ASSERT(!"Cannot parse PubKey");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
InitRnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPublicKey::~cPublicKey()
|
|
||||||
{
|
|
||||||
pk_free(&m_Pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cPublicKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
|
||||||
{
|
|
||||||
size_t DecryptedLen = a_DecryptedMaxLength;
|
|
||||||
int res = pk_decrypt(&m_Pk,
|
|
||||||
a_EncryptedData, a_EncryptedLength,
|
|
||||||
a_DecryptedData, &DecryptedLen, a_DecryptedMaxLength,
|
|
||||||
ctr_drbg_random, &m_Ctr_drbg
|
|
||||||
);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
return (int)DecryptedLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cPublicKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
|
||||||
{
|
|
||||||
size_t EncryptedLength = a_EncryptedMaxLength;
|
|
||||||
int res = pk_encrypt(&m_Pk,
|
|
||||||
a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength,
|
|
||||||
ctr_drbg_random, &m_Ctr_drbg
|
|
||||||
);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
return (int)EncryptedLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPublicKey::InitRnd(void)
|
|
||||||
{
|
|
||||||
entropy_init(&m_Entropy);
|
|
||||||
const unsigned char pers[] = "rsa_genkey";
|
|
||||||
ctr_drbg_init(&m_Ctr_drbg, entropy_func, &m_Entropy, pers, sizeof(pers) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// cAESCFBDecryptor:
|
|
||||||
|
|
||||||
cAESCFBDecryptor::cAESCFBDecryptor(void) :
|
|
||||||
m_IVOffset(0),
|
|
||||||
m_IsValid(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cAESCFBDecryptor::~cAESCFBDecryptor()
|
|
||||||
{
|
|
||||||
// Clear the leftover in-memory data, so that they can't be accessed by a backdoor
|
|
||||||
memset(&m_Aes, 0, sizeof(m_Aes));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cAESCFBDecryptor::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);
|
|
||||||
m_IsValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cAESCFBDecryptor::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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// cAESCFBEncryptor:
|
|
||||||
|
|
||||||
cAESCFBEncryptor::cAESCFBEncryptor(void) :
|
|
||||||
m_IVOffset(0),
|
|
||||||
m_IsValid(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cAESCFBEncryptor::~cAESCFBEncryptor()
|
|
||||||
{
|
|
||||||
// Clear the leftover in-memory data, so that they can't be accessed by a backdoor
|
|
||||||
memset(&m_Aes, 0, sizeof(m_Aes));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cAESCFBEncryptor::Init(const Byte a_Key[16], const Byte a_IV[16])
|
|
||||||
{
|
|
||||||
ASSERT(!IsValid()); // Cannot Init twice
|
|
||||||
ASSERT(m_IVOffset == 0);
|
|
||||||
|
|
||||||
memcpy(m_IV, a_IV, 16);
|
|
||||||
aes_setkey_enc(&m_Aes, a_Key, 128);
|
|
||||||
m_IsValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cAESCFBEncryptor::ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length)
|
|
||||||
{
|
|
||||||
ASSERT(IsValid()); // Must Init() first
|
|
||||||
|
|
||||||
// PolarSSL doesn't do AES-CFB8, so we need to implement it ourselves:
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
a_EncryptedOut[i] = a_PlainIn[i] ^ Buffer[0];
|
|
||||||
m_IV[sizeof(m_IV) - 1] = a_EncryptedOut[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// cSHA1Checksum:
|
|
||||||
|
|
||||||
cSHA1Checksum::cSHA1Checksum(void) :
|
|
||||||
m_DoesAcceptInput(true)
|
|
||||||
{
|
|
||||||
sha1_starts(&m_Sha1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSHA1Checksum::Update(const Byte * a_Data, size_t a_Length)
|
|
||||||
{
|
|
||||||
ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed
|
|
||||||
|
|
||||||
sha1_update(&m_Sha1, a_Data, a_Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSHA1Checksum::Finalize(cSHA1Checksum::Checksum & a_Output)
|
|
||||||
{
|
|
||||||
ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed
|
|
||||||
|
|
||||||
sha1_finish(&m_Sha1, a_Output);
|
|
||||||
m_DoesAcceptInput = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSHA1Checksum::DigestToJava(const Checksum & a_Digest, AString & a_Out)
|
|
||||||
{
|
|
||||||
Checksum Digest;
|
|
||||||
memcpy(Digest, a_Digest, sizeof(Digest));
|
|
||||||
|
|
||||||
bool IsNegative = (Digest[0] >= 0x80);
|
|
||||||
if (IsNegative)
|
|
||||||
{
|
|
||||||
// Two's complement:
|
|
||||||
bool carry = true; // Add one to the whole number
|
|
||||||
for (int i = 19; i >= 0; i--)
|
|
||||||
{
|
|
||||||
Digest[i] = ~Digest[i];
|
|
||||||
if (carry)
|
|
||||||
{
|
|
||||||
carry = (Digest[i] == 0xff);
|
|
||||||
Digest[i]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a_Out.clear();
|
|
||||||
a_Out.reserve(40);
|
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
|
||||||
AppendPrintf(a_Out, "%02x", Digest[i]);
|
|
||||||
}
|
|
||||||
while ((a_Out.length() > 0) && (a_Out[0] == '0'))
|
|
||||||
{
|
|
||||||
a_Out.erase(0, 1);
|
|
||||||
}
|
|
||||||
if (IsNegative)
|
|
||||||
{
|
|
||||||
a_Out.insert(0, "-");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSHA1Checksum::Restart(void)
|
|
||||||
{
|
|
||||||
sha1_starts(&m_Sha1);
|
|
||||||
m_DoesAcceptInput = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
198
src/Crypto.h
198
src/Crypto.h
@ -1,198 +0,0 @@
|
|||||||
|
|
||||||
// Crypto.h
|
|
||||||
|
|
||||||
// Declares classes that wrap the cryptographic code library
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "polarssl/rsa.h"
|
|
||||||
#include "polarssl/aes.h"
|
|
||||||
#include "polarssl/entropy.h"
|
|
||||||
#include "polarssl/ctr_drbg.h"
|
|
||||||
#include "polarssl/sha1.h"
|
|
||||||
#include "polarssl/pk.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Encapsulates an RSA private key used in PKI cryptography */
|
|
||||||
class cRSAPrivateKey
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Creates a new empty object, the key is not assigned */
|
|
||||||
cRSAPrivateKey(void);
|
|
||||||
|
|
||||||
/** Deep-copies the key from a_Other */
|
|
||||||
cRSAPrivateKey(const cRSAPrivateKey & a_Other);
|
|
||||||
|
|
||||||
~cRSAPrivateKey();
|
|
||||||
|
|
||||||
/** Generates a new key within this object, with the specified size in bits.
|
|
||||||
Returns true on success, false on failure. */
|
|
||||||
bool Generate(unsigned a_KeySizeBits = 1024);
|
|
||||||
|
|
||||||
/** Returns the public key part encoded in ASN1 DER encoding */
|
|
||||||
AString GetPubKeyDER(void);
|
|
||||||
|
|
||||||
/** Decrypts the data using RSAES-PKCS#1 algorithm.
|
|
||||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
|
||||||
Returns the number of bytes decrypted, or negative number for error. */
|
|
||||||
int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength);
|
|
||||||
|
|
||||||
/** Encrypts the data using RSAES-PKCS#1 algorithm.
|
|
||||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
|
||||||
Returns the number of bytes decrypted, or negative number for error. */
|
|
||||||
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
rsa_context m_Rsa;
|
|
||||||
entropy_context m_Entropy;
|
|
||||||
ctr_drbg_context m_Ctr_drbg;
|
|
||||||
|
|
||||||
/** Initializes the m_Entropy and m_Ctr_drbg contexts
|
|
||||||
Common part of this object's construction, called from all constructors. */
|
|
||||||
void InitRnd(void);
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cPublicKey
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cPublicKey(const AString & a_PublicKeyDER);
|
|
||||||
~cPublicKey();
|
|
||||||
|
|
||||||
/** Decrypts the data using the stored public key
|
|
||||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
|
||||||
Returns the number of bytes decrypted, or negative number for error. */
|
|
||||||
int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength);
|
|
||||||
|
|
||||||
/** Encrypts the data using the stored public key
|
|
||||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
|
||||||
Returns the number of bytes decrypted, or negative number for error. */
|
|
||||||
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
pk_context m_Pk;
|
|
||||||
entropy_context m_Entropy;
|
|
||||||
ctr_drbg_context m_Ctr_drbg;
|
|
||||||
|
|
||||||
/** Initializes the m_Entropy and m_Ctr_drbg contexts
|
|
||||||
Common part of this object's construction, called from all constructors. */
|
|
||||||
void InitRnd(void);
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Decrypts data using the AES / CFB (128) algorithm */
|
|
||||||
class cAESCFBDecryptor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Byte test;
|
|
||||||
|
|
||||||
cAESCFBDecryptor(void);
|
|
||||||
~cAESCFBDecryptor();
|
|
||||||
|
|
||||||
/** Initializes the decryptor with the specified Key / IV */
|
|
||||||
void Init(const Byte a_Key[16], const Byte a_IV[16]);
|
|
||||||
|
|
||||||
/** Decrypts a_Length bytes of the encrypted data; produces a_Length output bytes */
|
|
||||||
void ProcessData(Byte * a_DecryptedOut, const Byte * a_EncryptedIn, size_t a_Length);
|
|
||||||
|
|
||||||
/** Returns true if the object has been initialized with the Key / IV */
|
|
||||||
bool IsValid(void) const { return m_IsValid; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
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;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Encrypts data using the AES / CFB (128) algorithm */
|
|
||||||
class cAESCFBEncryptor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cAESCFBEncryptor(void);
|
|
||||||
~cAESCFBEncryptor();
|
|
||||||
|
|
||||||
/** Initializes the decryptor with the specified Key / IV */
|
|
||||||
void Init(const Byte a_Key[16], const Byte a_IV[16]);
|
|
||||||
|
|
||||||
/** Encrypts a_Length bytes of the plain data; produces a_Length output bytes */
|
|
||||||
void ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length);
|
|
||||||
|
|
||||||
/** Returns true if the object has been initialized with the Key / IV */
|
|
||||||
bool IsValid(void) const { return m_IsValid; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
aes_context m_Aes;
|
|
||||||
|
|
||||||
/** The InitialVector, used by the CFB mode encryption */
|
|
||||||
Byte m_IV[16];
|
|
||||||
|
|
||||||
/** Current offset in the m_IV, used by the CFB mode encryption */
|
|
||||||
size_t m_IVOffset;
|
|
||||||
|
|
||||||
/** Indicates whether the object has been initialized with the Key / IV */
|
|
||||||
bool m_IsValid;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Calculates a SHA1 checksum for data stream */
|
|
||||||
class cSHA1Checksum
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef Byte Checksum[20]; // The type used for storing the checksum
|
|
||||||
|
|
||||||
cSHA1Checksum(void);
|
|
||||||
|
|
||||||
/** Adds the specified data to the checksum */
|
|
||||||
void Update(const Byte * a_Data, size_t a_Length);
|
|
||||||
|
|
||||||
/** Calculates and returns the final checksum */
|
|
||||||
void Finalize(Checksum & a_Output);
|
|
||||||
|
|
||||||
/** Returns true if the object is accepts more input data, false if Finalize()-d (need to Restart()) */
|
|
||||||
bool DoesAcceptInput(void) const { return m_DoesAcceptInput; }
|
|
||||||
|
|
||||||
/** Converts a raw 160-bit SHA1 digest into a Java Hex representation
|
|
||||||
According to http://wiki.vg/wiki/index.php?title=Protocol_Encryption&oldid=2802
|
|
||||||
*/
|
|
||||||
static void DigestToJava(const Checksum & a_Digest, AString & a_JavaOut);
|
|
||||||
|
|
||||||
/** Clears the current context and start a new checksum calculation */
|
|
||||||
void Restart(void);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** True if the object is accepts more input data, false if Finalize()-d (need to Restart()) */
|
|
||||||
bool m_DoesAcceptInput;
|
|
||||||
|
|
||||||
sha1_context m_Sha1;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -264,7 +264,21 @@ template class SizeChecker<UInt16, 2>;
|
|||||||
|
|
||||||
// Same as assert but in all Self test builds
|
// Same as assert but in all Self test builds
|
||||||
#ifdef SELF_TEST
|
#ifdef SELF_TEST
|
||||||
#define assert_test(x) ( !!(x) || (assert(!#x), exit(1), 0))
|
#define assert_test(x) ( !!(x) || (assert(!#x), exit(1), 0))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Allow both Older versions of MSVC and newer versions of everything use a shared_ptr:
|
||||||
|
// Note that we cannot typedef, because C++ doesn't allow (partial) templates to be typedeffed.
|
||||||
|
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||||
|
// MSVC before 2010 doesn't have std::shared_ptr, but has std::tr1::shared_ptr, defined in <memory> included earlier
|
||||||
|
#define SharedPtr std::tr1::shared_ptr
|
||||||
|
#elif (__cplusplus >= 201103L)
|
||||||
|
// C++11 has std::shared_ptr in <memory>, included earlier
|
||||||
|
#define SharedPtr std::shared_ptr
|
||||||
|
#else
|
||||||
|
// C++03 has std::tr1::shared_ptr in <tr1/memory>
|
||||||
|
#include <tr1/memory>
|
||||||
|
#define SharedPtr std::tr1::shared_ptr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -296,7 +310,7 @@ T Clamp(T a_Value, T a_Min, T a_Max)
|
|||||||
|
|
||||||
|
|
||||||
#ifndef TOLUA_TEMPLATE_BIND
|
#ifndef TOLUA_TEMPLATE_BIND
|
||||||
#define TOLUA_TEMPLATE_BIND(x)
|
#define TOLUA_TEMPLATE_BIND(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ bool cSocket::ConnectToLocalhostIPv4(unsigned short a_Port)
|
|||||||
|
|
||||||
bool cSocket::ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Port)
|
bool cSocket::ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Port)
|
||||||
{
|
{
|
||||||
// First try IP Address string to hostent conversion, because it's faster
|
// First try IP Address string to hostent conversion, because it's faster and local:
|
||||||
unsigned long addr = inet_addr(a_HostNameOrAddr.c_str());
|
unsigned long addr = inet_addr(a_HostNameOrAddr.c_str());
|
||||||
if (addr == INADDR_NONE)
|
if (addr == INADDR_NONE)
|
||||||
{
|
{
|
||||||
@ -307,10 +307,16 @@ bool cSocket::ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Por
|
|||||||
CloseSocket();
|
CloseSocket();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Should be optimised to a single word copy
|
|
||||||
memcpy(&addr, hp->h_addr, hp->h_length);
|
memcpy(&addr, hp->h_addr, hp->h_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the socket is not created yet, create one:
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
m_Socket = socket((int)IPv4, SOCK_STREAM, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the socket:
|
||||||
sockaddr_in server;
|
sockaddr_in server;
|
||||||
server.sin_addr.s_addr = addr;
|
server.sin_addr.s_addr = addr;
|
||||||
server.sin_family = AF_INET;
|
server.sin_family = AF_INET;
|
||||||
|
67
src/PolarSSL++/AesCfb128Decryptor.cpp
Normal file
67
src/PolarSSL++/AesCfb128Decryptor.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
// AesCfb128Decryptor.cpp
|
||||||
|
|
||||||
|
// Implements the cAesCfb128Decryptor class decrypting data using AES CFB-128
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "AesCfb128Decryptor.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cAesCfb128Decryptor::cAesCfb128Decryptor(void) :
|
||||||
|
m_IVOffset(0),
|
||||||
|
m_IsValid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
m_IsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
52
src/PolarSSL++/AesCfb128Decryptor.h
Normal file
52
src/PolarSSL++/AesCfb128Decryptor.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
// AesCfb128Decryptor.h
|
||||||
|
|
||||||
|
// Declares the cAesCfb128Decryptor class decrypting data using AES CFB-128
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/aes.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Decrypts data using the AES / CFB 128 algorithm */
|
||||||
|
class cAesCfb128Decryptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Byte test;
|
||||||
|
|
||||||
|
cAesCfb128Decryptor(void);
|
||||||
|
~cAesCfb128Decryptor();
|
||||||
|
|
||||||
|
/** Initializes the decryptor with the specified Key / IV */
|
||||||
|
void Init(const Byte a_Key[16], const Byte a_IV[16]);
|
||||||
|
|
||||||
|
/** Decrypts a_Length bytes of the encrypted data; produces a_Length output bytes */
|
||||||
|
void ProcessData(Byte * a_DecryptedOut, const Byte * a_EncryptedIn, size_t a_Length);
|
||||||
|
|
||||||
|
/** Returns true if the object has been initialized with the Key / IV */
|
||||||
|
bool IsValid(void) const { return m_IsValid; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
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;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
68
src/PolarSSL++/AesCfb128Encryptor.cpp
Normal file
68
src/PolarSSL++/AesCfb128Encryptor.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
// AesCfb128Encryptor.cpp
|
||||||
|
|
||||||
|
// Implements the cAesCfb128Encryptor class encrypting data using AES CFB-128
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "AesCfb128Encryptor.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cAesCfb128Encryptor::cAesCfb128Encryptor(void) :
|
||||||
|
m_IVOffset(0),
|
||||||
|
m_IsValid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cAesCfb128Encryptor::Init(const Byte a_Key[16], const Byte a_IV[16])
|
||||||
|
{
|
||||||
|
ASSERT(!IsValid()); // Cannot Init twice
|
||||||
|
ASSERT(m_IVOffset == 0);
|
||||||
|
|
||||||
|
memcpy(m_IV, a_IV, 16);
|
||||||
|
aes_setkey_enc(&m_Aes, a_Key, 128);
|
||||||
|
m_IsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cAesCfb128Encryptor::ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid()); // Must Init() first
|
||||||
|
|
||||||
|
// PolarSSL doesn't do AES-CFB8, so we need to implement it ourselves:
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
a_EncryptedOut[i] = a_PlainIn[i] ^ Buffer[0];
|
||||||
|
m_IV[sizeof(m_IV) - 1] = a_EncryptedOut[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
50
src/PolarSSL++/AesCfb128Encryptor.h
Normal file
50
src/PolarSSL++/AesCfb128Encryptor.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
// AesCfb128Encryptor.h
|
||||||
|
|
||||||
|
// Declares the cAesCfb128Encryptor class encrypting data using AES CFB-128
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/aes.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Encrypts data using the AES / CFB (128) algorithm */
|
||||||
|
class cAesCfb128Encryptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cAesCfb128Encryptor(void);
|
||||||
|
~cAesCfb128Encryptor();
|
||||||
|
|
||||||
|
/** Initializes the decryptor with the specified Key / IV */
|
||||||
|
void Init(const Byte a_Key[16], const Byte a_IV[16]);
|
||||||
|
|
||||||
|
/** Encrypts a_Length bytes of the plain data; produces a_Length output bytes */
|
||||||
|
void ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length);
|
||||||
|
|
||||||
|
/** Returns true if the object has been initialized with the Key / IV */
|
||||||
|
bool IsValid(void) const { return m_IsValid; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
aes_context m_Aes;
|
||||||
|
|
||||||
|
/** The InitialVector, used by the CFB mode encryption */
|
||||||
|
Byte m_IV[16];
|
||||||
|
|
||||||
|
/** Current offset in the m_IV, used by the CFB mode encryption */
|
||||||
|
size_t m_IVOffset;
|
||||||
|
|
||||||
|
/** Indicates whether the object has been initialized with the Key / IV */
|
||||||
|
bool m_IsValid;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
195
src/PolarSSL++/BlockingSslClientSocket.cpp
Normal file
195
src/PolarSSL++/BlockingSslClientSocket.cpp
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
|
||||||
|
// BlockingSslClientSocket.cpp
|
||||||
|
|
||||||
|
// Implements the cBlockingSslClientSocket class representing a blocking TCP socket with client SSL encryption over it
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "BlockingSslClientSocket.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBlockingSslClientSocket::cBlockingSslClientSocket(void) :
|
||||||
|
m_Ssl(*this),
|
||||||
|
m_IsConnected(false)
|
||||||
|
{
|
||||||
|
// Nothing needed yet
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cBlockingSslClientSocket::Connect(const AString & a_ServerName, UInt16 a_Port)
|
||||||
|
{
|
||||||
|
// If already connected, report an error:
|
||||||
|
if (m_IsConnected)
|
||||||
|
{
|
||||||
|
// TODO: Handle this better - if connected to the same server and port, and the socket is alive, return success
|
||||||
|
m_LastErrorText = "Already connected";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the underlying socket:
|
||||||
|
m_Socket.CreateSocket(cSocket::IPv4);
|
||||||
|
if (!m_Socket.ConnectIPv4(a_ServerName.c_str(), a_Port))
|
||||||
|
{
|
||||||
|
Printf(m_LastErrorText, "Socket connect failed: %s", m_Socket.GetLastErrorString().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the SSL:
|
||||||
|
int ret = m_Ssl.Initialize(true);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
Printf(m_LastErrorText, "SSL initialization failed: -0x%x", -ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have been assigned a trusted CA root cert store, push it into the SSL context:
|
||||||
|
if (m_CACerts.get() != NULL)
|
||||||
|
{
|
||||||
|
m_Ssl.SetCACerts(m_CACerts, m_ExpectedPeerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = m_Ssl.Handshake();
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
Printf(m_LastErrorText, "SSL handshake failed: -0x%x", -ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IsConnected = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cBlockingSslClientSocket::SetTrustedRootCertsFromString(const AString & a_CACerts, const AString & a_ExpectedPeerName)
|
||||||
|
{
|
||||||
|
// Warn if used multiple times, but don't signal an error:
|
||||||
|
if (m_CACerts.get() != NULL)
|
||||||
|
{
|
||||||
|
LOGWARNING(
|
||||||
|
"SSL: Trying to set multiple trusted CA root cert stores, only the last one will be used. Name: %s",
|
||||||
|
a_ExpectedPeerName.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the cert:
|
||||||
|
m_CACerts.reset(new cX509Cert);
|
||||||
|
int ret = m_CACerts->Parse(a_CACerts.data(), a_CACerts.size());
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
Printf(m_LastErrorText, "CA cert parsing failed: -0x%x", -ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_ExpectedPeerName = a_ExpectedPeerName;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cBlockingSslClientSocket::Send(const void * a_Data, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
ASSERT(m_IsConnected);
|
||||||
|
|
||||||
|
// Keep sending the data until all of it is sent:
|
||||||
|
const char * Data = (const char *)a_Data;
|
||||||
|
size_t NumBytes = a_NumBytes;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int res = m_Ssl.WritePlain(a_Data, a_NumBytes);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
ASSERT(res != POLARSSL_ERR_NET_WANT_READ); // This should never happen with callback-based SSL
|
||||||
|
ASSERT(res != POLARSSL_ERR_NET_WANT_WRITE); // This should never happen with callback-based SSL
|
||||||
|
Printf(m_LastErrorText, "Data cannot be written to SSL context: -0x%x", -res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Data += res;
|
||||||
|
NumBytes -= res;
|
||||||
|
if (NumBytes == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cBlockingSslClientSocket::Receive(void * a_Data, size_t a_MaxBytes)
|
||||||
|
{
|
||||||
|
ASSERT(m_IsConnected);
|
||||||
|
|
||||||
|
int res = m_Ssl.ReadPlain(a_Data, a_MaxBytes);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
Printf(m_LastErrorText, "Data cannot be read form SSL context: -0x%x", -res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cBlockingSslClientSocket::Disconnect(void)
|
||||||
|
{
|
||||||
|
// Ignore if not connected
|
||||||
|
if (!m_IsConnected)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Ssl.NotifyClose();
|
||||||
|
m_Socket.CloseSocket();
|
||||||
|
m_IsConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cBlockingSslClientSocket::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
int res = m_Socket.Receive((char *)a_Buffer, a_NumBytes, 0);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
// PolarSSL's net routines distinguish between connection reset and general failure, we don't need to
|
||||||
|
return POLARSSL_ERR_NET_RECV_FAILED;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cBlockingSslClientSocket::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
int res = m_Socket.Send((const char *)a_Buffer, a_NumBytes);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
// PolarSSL's net routines distinguish between connection reset and general failure, we don't need to
|
||||||
|
return POLARSSL_ERR_NET_SEND_FAILED;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
80
src/PolarSSL++/BlockingSslClientSocket.h
Normal file
80
src/PolarSSL++/BlockingSslClientSocket.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
// BlockingSslClientSocket.h
|
||||||
|
|
||||||
|
// Declares the cBlockingSslClientSocket class representing a blocking TCP socket with client SSL encryption over it
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CallbackSslContext.h"
|
||||||
|
#include "../OSSupport/Socket.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cBlockingSslClientSocket :
|
||||||
|
protected cCallbackSslContext::cDataCallbacks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cBlockingSslClientSocket(void);
|
||||||
|
|
||||||
|
/** Connects to the specified server and performs SSL handshake.
|
||||||
|
Returns true if successful, false on failure. Sets internal error text on failure. */
|
||||||
|
bool Connect(const AString & a_ServerName, UInt16 a_Port);
|
||||||
|
|
||||||
|
/** Sends the specified data over the connection.
|
||||||
|
Returns true if successful, false on failure. Sets the internal error text on failure. */
|
||||||
|
bool Send(const void * a_Data, size_t a_NumBytes);
|
||||||
|
|
||||||
|
/** Receives data from the connection.
|
||||||
|
Blocks until there is any data available, then returns as much as possible.
|
||||||
|
Returns the number of bytes actually received, negative number on failure.
|
||||||
|
Sets the internal error text on failure. */
|
||||||
|
int Receive(void * a_Data, size_t a_MaxBytes);
|
||||||
|
|
||||||
|
/** Disconnects the connection gracefully, if possible.
|
||||||
|
Note that this also frees the internal SSL context, so all the certificates etc. are lost. */
|
||||||
|
void Disconnect(void);
|
||||||
|
|
||||||
|
/** Sets the root certificates that are to be trusted. Forces the connection to use strict cert
|
||||||
|
verification. Needs to be used before calling Connect().
|
||||||
|
a_ExpectedPeerName is the name that we expect to receive in the SSL peer's cert; verification will fail if
|
||||||
|
the presented name is different (possible MITM).
|
||||||
|
Returns true on success, false on failure. Sets internal error text on failure. */
|
||||||
|
bool SetTrustedRootCertsFromString(const AString & a_CACerts, const AString & a_ExpectedPeerName);
|
||||||
|
|
||||||
|
/** Returns the text of the last error that has occurred in this instance. */
|
||||||
|
const AString & GetLastErrorText(void) const { return m_LastErrorText; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** The SSL context used for the socket */
|
||||||
|
cCallbackSslContext m_Ssl;
|
||||||
|
|
||||||
|
/** The underlying socket to the SSL server */
|
||||||
|
cSocket m_Socket;
|
||||||
|
|
||||||
|
/** The trusted CA root cert store, if we are to verify the cert strictly. Set by SetTrustedRootCertsFromString(). */
|
||||||
|
cX509CertPtr m_CACerts;
|
||||||
|
|
||||||
|
/** The expected SSL peer's name, if we are to verify the cert strictly. Set by SetTrustedRootCertsFromString(). */
|
||||||
|
AString m_ExpectedPeerName;
|
||||||
|
|
||||||
|
/** Text of the last error that has occurred. */
|
||||||
|
AString m_LastErrorText;
|
||||||
|
|
||||||
|
/** Set to true if the connection established successfully. */
|
||||||
|
bool m_IsConnected;
|
||||||
|
|
||||||
|
|
||||||
|
// cCallbackSslContext::cDataCallbacks overrides:
|
||||||
|
virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override;
|
||||||
|
virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
62
src/PolarSSL++/BufferedSslContext.cpp
Normal file
62
src/PolarSSL++/BufferedSslContext.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
// BufferedSslContext.cpp
|
||||||
|
|
||||||
|
// Implements the cBufferedSslContext class representing a SSL context with the SSL peer data backed by a cByteBuffer
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "BufferedSslContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBufferedSslContext::cBufferedSslContext(size_t a_BufferSize):
|
||||||
|
m_OutgoingData(a_BufferSize),
|
||||||
|
m_IncomingData(a_BufferSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cBufferedSslContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
// Called when PolarSSL wants to read encrypted data from the SSL peer
|
||||||
|
// Read the data from the buffer inside this object, where the owner has stored them using WriteIncoming():
|
||||||
|
size_t NumBytes = std::min(a_NumBytes, m_IncomingData.GetReadableSpace());
|
||||||
|
if (NumBytes == 0)
|
||||||
|
{
|
||||||
|
return POLARSSL_ERR_NET_WANT_READ;
|
||||||
|
}
|
||||||
|
if (!m_IncomingData.ReadBuf(a_Buffer, NumBytes))
|
||||||
|
{
|
||||||
|
m_IncomingData.ResetRead();
|
||||||
|
return POLARSSL_ERR_NET_RECV_FAILED;
|
||||||
|
}
|
||||||
|
m_IncomingData.CommitRead();
|
||||||
|
return (int)NumBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cBufferedSslContext::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
// Called when PolarSSL wants to write encrypted data to the SSL peer
|
||||||
|
// Write the data into the buffer inside this object, where the owner can later read them using ReadOutgoing():
|
||||||
|
if (!m_OutgoingData.CanWriteBytes(a_NumBytes))
|
||||||
|
{
|
||||||
|
return POLARSSL_ERR_NET_WANT_WRITE;
|
||||||
|
}
|
||||||
|
if (!m_OutgoingData.Write((const char *)a_Buffer, a_NumBytes))
|
||||||
|
{
|
||||||
|
return POLARSSL_ERR_NET_SEND_FAILED;
|
||||||
|
}
|
||||||
|
return (int)a_NumBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
52
src/PolarSSL++/BufferedSslContext.h
Normal file
52
src/PolarSSL++/BufferedSslContext.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
// BufferedSslContext.h
|
||||||
|
|
||||||
|
// Declares the cBufferedSslContext class representing a SSL context with the SSL peer data backed by a cByteBuffer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SslContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cBufferedSslContext :
|
||||||
|
public cSslContext
|
||||||
|
{
|
||||||
|
typedef cSslContext super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Creates a new context with the buffers of specified size for the encrypted / decrypted data. */
|
||||||
|
cBufferedSslContext(size_t a_BufferSize = 64000);
|
||||||
|
|
||||||
|
/** Stores the specified data in the "incoming" buffer, to be process by the SSL decryptor.
|
||||||
|
This is the data received from the SSL peer.
|
||||||
|
Returns the number of bytes actually stored. If 0 is returned, owner should check the error state. */
|
||||||
|
size_t WriteIncoming(const void * a_Data, size_t a_NumBytes);
|
||||||
|
|
||||||
|
/** Retrieves data from the "outgoing" buffer, after being processed by the SSL encryptor.
|
||||||
|
This is the data to be sent to the SSL peer.
|
||||||
|
Returns the number of bytes actually retrieved. */
|
||||||
|
size_t ReadOutgoing(void * a_Data, size_t a_DataMaxSize);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Buffer for the data that has been encrypted into the SSL stream and should be sent out. */
|
||||||
|
cByteBuffer m_OutgoingData;
|
||||||
|
|
||||||
|
/** Buffer for the data that has come in and needs to be decrypted from the SSL stream. */
|
||||||
|
cByteBuffer m_IncomingData;
|
||||||
|
|
||||||
|
|
||||||
|
// cSslContext overrides:
|
||||||
|
virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override;
|
||||||
|
virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
41
src/PolarSSL++/CMakeLists.txt
Normal file
41
src/PolarSSL++/CMakeLists.txt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
cmake_minimum_required (VERSION 2.6)
|
||||||
|
project (MCServer)
|
||||||
|
|
||||||
|
include_directories ("${PROJECT_SOURCE_DIR}/../")
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
AesCfb128Decryptor.cpp
|
||||||
|
AesCfb128Encryptor.cpp
|
||||||
|
BlockingSslClientSocket.cpp
|
||||||
|
BufferedSslContext.cpp
|
||||||
|
CallbackSslContext.cpp
|
||||||
|
CtrDrbgContext.cpp
|
||||||
|
EntropyContext.cpp
|
||||||
|
PublicKey.cpp
|
||||||
|
RsaPrivateKey.cpp
|
||||||
|
Sha1Checksum.cpp
|
||||||
|
SslContext.cpp
|
||||||
|
X509Cert.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
AesCfb128Decryptor.h
|
||||||
|
AesCfb128Encryptor.h
|
||||||
|
BlockingSslClientSocket.h
|
||||||
|
BufferedSslContext.h
|
||||||
|
CallbackSslContext.h
|
||||||
|
CtrDrbgContext.h
|
||||||
|
EntropyContext.h
|
||||||
|
PublicKey.h
|
||||||
|
RsaPrivateKey.h
|
||||||
|
SslContext.h
|
||||||
|
Sha1Checksum.h
|
||||||
|
X509Cert.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(PolarSSL++ ${SOURCES} ${HEADERS})
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
target_link_libraries(PolarSSL++ polarssl)
|
||||||
|
endif()
|
59
src/PolarSSL++/CallbackSslContext.cpp
Normal file
59
src/PolarSSL++/CallbackSslContext.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
// CallbackSslContext.cpp
|
||||||
|
|
||||||
|
// Declares the cCallbackSslContext class representing a SSL context wrapper that uses callbacks to read and write SSL peer data
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "CallbackSslContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cCallbackSslContext::cCallbackSslContext(void)
|
||||||
|
{
|
||||||
|
// Nothing needed, but the constructor needs to exist so
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cCallbackSslContext::cCallbackSslContext(cCallbackSslContext::cDataCallbacks & a_Callbacks) :
|
||||||
|
m_Callbacks(&a_Callbacks)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cCallbackSslContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
if (m_Callbacks == NULL)
|
||||||
|
{
|
||||||
|
LOGWARNING("SSL: Trying to receive data with no callbacks, aborting.");
|
||||||
|
return POLARSSL_ERR_NET_RECV_FAILED;
|
||||||
|
}
|
||||||
|
return m_Callbacks->ReceiveEncrypted(a_Buffer, a_NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cCallbackSslContext::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
if (m_Callbacks == NULL)
|
||||||
|
{
|
||||||
|
LOGWARNING("SSL: Trying to send data with no callbacks, aborting.");
|
||||||
|
return POLARSSL_ERR_NET_SEND_FAILED;
|
||||||
|
}
|
||||||
|
return m_Callbacks->SendEncrypted(a_Buffer, a_NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
61
src/PolarSSL++/CallbackSslContext.h
Normal file
61
src/PolarSSL++/CallbackSslContext.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
// CallbackSslContext.h
|
||||||
|
|
||||||
|
// Declares the cCallbackSslContext class representing a SSL context wrapper that uses callbacks to read and write SSL peer data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SslContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cCallbackSslContext :
|
||||||
|
public cSslContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Interface used as a data sink for the SSL peer data. */
|
||||||
|
class cDataCallbacks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Called when PolarSSL wants to read encrypted data from the SSL peer.
|
||||||
|
The returned value is the number of bytes received, or a PolarSSL error on failure.
|
||||||
|
The implementation can return POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE to indicate
|
||||||
|
that there's currently no more data and that there might be more data in the future. In such cases the
|
||||||
|
SSL operation that invoked this call will terminate with the same return value, so that the owner is
|
||||||
|
notified of this condition and can potentially restart the operation later on. */
|
||||||
|
virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) = 0;
|
||||||
|
|
||||||
|
/** Called when PolarSSL wants to write encrypted data to the SSL peer.
|
||||||
|
The returned value is the number of bytes sent, or a PolarSSL error on failure.
|
||||||
|
The implementation can return POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE to indicate
|
||||||
|
that there's currently no more data and that there might be more data in the future. In such cases the
|
||||||
|
SSL operation that invoked this call will terminate with the same return value, so that the owner is
|
||||||
|
notified of this condition and can potentially restart the operation later on. */
|
||||||
|
virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) = 0;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
/** Creates a new SSL context with no callbacks assigned */
|
||||||
|
cCallbackSslContext(void);
|
||||||
|
|
||||||
|
/** Creates a new SSL context with the specified callbacks */
|
||||||
|
cCallbackSslContext(cDataCallbacks & a_Callbacks);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** The callbacks to use to send and receive SSL peer data */
|
||||||
|
cDataCallbacks * m_Callbacks;
|
||||||
|
|
||||||
|
// cSslContext overrides:
|
||||||
|
virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override;
|
||||||
|
virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
49
src/PolarSSL++/CtrDrbgContext.cpp
Normal file
49
src/PolarSSL++/CtrDrbgContext.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
// CtrDrbgContext.cpp
|
||||||
|
|
||||||
|
// Implements the cCtrDrbgContext class representing a wrapper over CTR-DRBG implementation in PolarSSL
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "CtrDrbgContext.h"
|
||||||
|
#include "EntropyContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cCtrDrbgContext::cCtrDrbgContext(void) :
|
||||||
|
m_EntropyContext(new cEntropyContext),
|
||||||
|
m_IsValid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cCtrDrbgContext::cCtrDrbgContext(const SharedPtr<cEntropyContext> & a_EntropyContext) :
|
||||||
|
m_EntropyContext(a_EntropyContext),
|
||||||
|
m_IsValid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cCtrDrbgContext::Initialize(const void * a_Custom, size_t a_CustomSize)
|
||||||
|
{
|
||||||
|
if (m_IsValid)
|
||||||
|
{
|
||||||
|
// Already initialized
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = ctr_drbg_init(&m_CtrDrbg, entropy_func, &(m_EntropyContext->m_Entropy), (const unsigned char *)a_Custom, a_CustomSize);
|
||||||
|
m_IsValid = (res == 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
63
src/PolarSSL++/CtrDrbgContext.h
Normal file
63
src/PolarSSL++/CtrDrbgContext.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
|
||||||
|
// CtrDrbgContext.h
|
||||||
|
|
||||||
|
// Declares the cCtrDrbgContext class representing a wrapper over CTR-DRBG implementation in PolarSSL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/ctr_drbg.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fwd: EntropyContext.h
|
||||||
|
class cEntropyContext;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cCtrDrbgContext
|
||||||
|
{
|
||||||
|
friend class cSslContext;
|
||||||
|
friend class cRsaPrivateKey;
|
||||||
|
friend class cPublicKey;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Constructs the context with a new entropy context. */
|
||||||
|
cCtrDrbgContext(void);
|
||||||
|
|
||||||
|
/** Constructs the context with the specified entropy context. */
|
||||||
|
cCtrDrbgContext(const SharedPtr<cEntropyContext> & a_EntropyContext);
|
||||||
|
|
||||||
|
/** Initializes the context.
|
||||||
|
a_Custom is optional additional data to use for entropy, nullptr is accepted.
|
||||||
|
Returns 0 if successful, PolarSSL error code on failure. */
|
||||||
|
int Initialize(const void * a_Custom, size_t a_CustomSize);
|
||||||
|
|
||||||
|
/** Returns true if the object is valid (has been initialized properly) */
|
||||||
|
bool IsValid(void) const { return m_IsValid; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** The entropy source used for generating the random */
|
||||||
|
SharedPtr<cEntropyContext> m_EntropyContext;
|
||||||
|
|
||||||
|
/** The random generator context */
|
||||||
|
ctr_drbg_context m_CtrDrbg;
|
||||||
|
|
||||||
|
/** Set to true if the object is valid (has been initialized properly) */
|
||||||
|
bool m_IsValid;
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns the internal context ptr. Only use in PolarSSL API calls. */
|
||||||
|
ctr_drbg_context * GetInternal(void) { return &m_CtrDrbg; }
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
29
src/PolarSSL++/EntropyContext.cpp
Normal file
29
src/PolarSSL++/EntropyContext.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
// EntropyContext.cpp
|
||||||
|
|
||||||
|
// Implements the cEntropyContext class representing a wrapper over entropy contexts in PolarSSL
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "EntropyContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cEntropyContext::cEntropyContext(void)
|
||||||
|
{
|
||||||
|
entropy_init(&m_Entropy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cEntropyContext::~cEntropyContext()
|
||||||
|
{
|
||||||
|
entropy_free(&m_Entropy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
31
src/PolarSSL++/EntropyContext.h
Normal file
31
src/PolarSSL++/EntropyContext.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
// EntropyContext.h
|
||||||
|
|
||||||
|
// Declares the cEntropyContext class representing a wrapper over entropy contexts in PolarSSL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/entropy.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cEntropyContext
|
||||||
|
{
|
||||||
|
friend class cCtrDrbgContext;
|
||||||
|
public:
|
||||||
|
cEntropyContext(void);
|
||||||
|
~cEntropyContext();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
entropy_context m_Entropy;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
73
src/PolarSSL++/PublicKey.cpp
Normal file
73
src/PolarSSL++/PublicKey.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
// PublicKey.cpp
|
||||||
|
|
||||||
|
// Implements the cPublicKey class representing a RSA public key in PolarSSL
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "PublicKey.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPublicKey::cPublicKey(const AString & a_PublicKeyDER)
|
||||||
|
{
|
||||||
|
pk_init(&m_Pk);
|
||||||
|
if (pk_parse_public_key(&m_Pk, (const Byte *)a_PublicKeyDER.data(), a_PublicKeyDER.size()) != 0)
|
||||||
|
{
|
||||||
|
ASSERT(!"Cannot parse PubKey");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_CtrDrbg.Initialize("rsa_pubkey", 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPublicKey::~cPublicKey()
|
||||||
|
{
|
||||||
|
pk_free(&m_Pk);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cPublicKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
||||||
|
{
|
||||||
|
size_t DecryptedLen = a_DecryptedMaxLength;
|
||||||
|
int res = pk_decrypt(&m_Pk,
|
||||||
|
a_EncryptedData, a_EncryptedLength,
|
||||||
|
a_DecryptedData, &DecryptedLen, a_DecryptedMaxLength,
|
||||||
|
ctr_drbg_random, m_CtrDrbg.GetInternal()
|
||||||
|
);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return (int)DecryptedLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cPublicKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
||||||
|
{
|
||||||
|
size_t EncryptedLength = a_EncryptedMaxLength;
|
||||||
|
int res = pk_encrypt(&m_Pk,
|
||||||
|
a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength,
|
||||||
|
ctr_drbg_random, m_CtrDrbg.GetInternal()
|
||||||
|
);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return (int)EncryptedLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
48
src/PolarSSL++/PublicKey.h
Normal file
48
src/PolarSSL++/PublicKey.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
// PublicKey.h
|
||||||
|
|
||||||
|
// Declares the cPublicKey class representing a RSA public key in PolarSSL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CtrDrbgContext.h"
|
||||||
|
#include "polarssl/pk.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cPublicKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Constructs the public key out of the DER-encoded pubkey data */
|
||||||
|
cPublicKey(const AString & a_PublicKeyDER);
|
||||||
|
|
||||||
|
~cPublicKey();
|
||||||
|
|
||||||
|
/** Decrypts the data using the stored public key
|
||||||
|
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||||
|
Returns the number of bytes decrypted, or negative number for error. */
|
||||||
|
int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength);
|
||||||
|
|
||||||
|
/** Encrypts the data using the stored public key
|
||||||
|
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||||
|
Returns the number of bytes decrypted, or negative number for error. */
|
||||||
|
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** The public key PolarSSL representation */
|
||||||
|
pk_context m_Pk;
|
||||||
|
|
||||||
|
/** The random generator used in encryption and decryption */
|
||||||
|
cCtrDrbgContext m_CtrDrbg;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
176
src/PolarSSL++/RsaPrivateKey.cpp
Normal file
176
src/PolarSSL++/RsaPrivateKey.cpp
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
|
||||||
|
// RsaPrivateKey.cpp
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "RsaPrivateKey.h"
|
||||||
|
#include "CtrDrbgContext.h"
|
||||||
|
#include "polarssl/pk.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cRsaPrivateKey::cRsaPrivateKey(void)
|
||||||
|
{
|
||||||
|
rsa_init(&m_Rsa, RSA_PKCS_V15, 0);
|
||||||
|
m_CtrDrbg.Initialize("RSA", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cRsaPrivateKey::cRsaPrivateKey(const cRsaPrivateKey & a_Other)
|
||||||
|
{
|
||||||
|
rsa_init(&m_Rsa, RSA_PKCS_V15, 0);
|
||||||
|
rsa_copy(&m_Rsa, &a_Other.m_Rsa);
|
||||||
|
m_CtrDrbg.Initialize("RSA", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cRsaPrivateKey::~cRsaPrivateKey()
|
||||||
|
{
|
||||||
|
rsa_free(&m_Rsa);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cRsaPrivateKey::Generate(unsigned a_KeySizeBits)
|
||||||
|
{
|
||||||
|
int res = rsa_gen_key(&m_Rsa, ctr_drbg_random, m_CtrDrbg.GetInternal(), a_KeySizeBits, 65537);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
LOG("RSA key generation failed: -0x%x", -res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cRsaPrivateKey::GetPubKeyDER(void)
|
||||||
|
{
|
||||||
|
class cPubKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cPubKey(rsa_context * a_Rsa) :
|
||||||
|
m_IsValid(false)
|
||||||
|
{
|
||||||
|
pk_init(&m_Key);
|
||||||
|
if (pk_init_ctx(&m_Key, pk_info_from_type(POLARSSL_PK_RSA)) != 0)
|
||||||
|
{
|
||||||
|
ASSERT(!"Cannot init PrivKey context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rsa_copy(pk_rsa(m_Key), a_Rsa) != 0)
|
||||||
|
{
|
||||||
|
ASSERT(!"Cannot copy PrivKey to PK context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_IsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~cPubKey()
|
||||||
|
{
|
||||||
|
if (m_IsValid)
|
||||||
|
{
|
||||||
|
pk_free(&m_Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator pk_context * (void) { return &m_Key; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool m_IsValid;
|
||||||
|
pk_context m_Key;
|
||||||
|
} PkCtx(&m_Rsa);
|
||||||
|
|
||||||
|
unsigned char buf[3000];
|
||||||
|
int res = pk_write_pubkey_der(PkCtx, buf, sizeof(buf));
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
return AString();
|
||||||
|
}
|
||||||
|
return AString((const char *)(buf + sizeof(buf) - res), (size_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cRsaPrivateKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
||||||
|
{
|
||||||
|
if (a_EncryptedLength < m_Rsa.len)
|
||||||
|
{
|
||||||
|
LOGD("%s: Invalid a_EncryptedLength: got %u, exp at least %u",
|
||||||
|
__FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len)
|
||||||
|
);
|
||||||
|
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a_DecryptedMaxLength < m_Rsa.len)
|
||||||
|
{
|
||||||
|
LOGD("%s: Invalid a_DecryptedMaxLength: got %u, exp at least %u",
|
||||||
|
__FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len)
|
||||||
|
);
|
||||||
|
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size_t DecryptedLength;
|
||||||
|
int res = rsa_pkcs1_decrypt(
|
||||||
|
&m_Rsa, ctr_drbg_random, m_CtrDrbg.GetInternal(), RSA_PRIVATE, &DecryptedLength,
|
||||||
|
a_EncryptedData, a_DecryptedData, a_DecryptedMaxLength
|
||||||
|
);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (int)DecryptedLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cRsaPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
||||||
|
{
|
||||||
|
if (a_EncryptedMaxLength < m_Rsa.len)
|
||||||
|
{
|
||||||
|
LOGD("%s: Invalid a_EncryptedMaxLength: got %u, exp at least %u",
|
||||||
|
__FUNCTION__, (unsigned)a_EncryptedMaxLength, (unsigned)(m_Rsa.len)
|
||||||
|
);
|
||||||
|
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a_PlainLength < m_Rsa.len)
|
||||||
|
{
|
||||||
|
LOGD("%s: Invalid a_PlainLength: got %u, exp at least %u",
|
||||||
|
__FUNCTION__, (unsigned)a_PlainLength, (unsigned)(m_Rsa.len)
|
||||||
|
);
|
||||||
|
ASSERT(!"Invalid a_PlainLength!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int res = rsa_pkcs1_encrypt(
|
||||||
|
&m_Rsa, ctr_drbg_random, m_CtrDrbg.GetInternal(), RSA_PRIVATE,
|
||||||
|
a_PlainLength, a_PlainData, a_EncryptedData
|
||||||
|
);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (int)m_Rsa.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
59
src/PolarSSL++/RsaPrivateKey.h
Normal file
59
src/PolarSSL++/RsaPrivateKey.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
// RsaPrivateKey.h
|
||||||
|
|
||||||
|
// Declares the cRsaPrivateKey class representing a private key for RSA operations.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CtrDrbgContext.h"
|
||||||
|
#include "polarssl/rsa.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Encapsulates an RSA private key used in PKI cryptography */
|
||||||
|
class cRsaPrivateKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Creates a new empty object, the key is not assigned */
|
||||||
|
cRsaPrivateKey(void);
|
||||||
|
|
||||||
|
/** Deep-copies the key from a_Other */
|
||||||
|
cRsaPrivateKey(const cRsaPrivateKey & a_Other);
|
||||||
|
|
||||||
|
~cRsaPrivateKey();
|
||||||
|
|
||||||
|
/** Generates a new key within this object, with the specified size in bits.
|
||||||
|
Returns true on success, false on failure. */
|
||||||
|
bool Generate(unsigned a_KeySizeBits = 1024);
|
||||||
|
|
||||||
|
/** Returns the public key part encoded in ASN1 DER encoding */
|
||||||
|
AString GetPubKeyDER(void);
|
||||||
|
|
||||||
|
/** Decrypts the data using RSAES-PKCS#1 algorithm.
|
||||||
|
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||||
|
Returns the number of bytes decrypted, or negative number for error. */
|
||||||
|
int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength);
|
||||||
|
|
||||||
|
/** Encrypts the data using RSAES-PKCS#1 algorithm.
|
||||||
|
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||||
|
Returns the number of bytes decrypted, or negative number for error. */
|
||||||
|
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** The PolarSSL key context */
|
||||||
|
rsa_context m_Rsa;
|
||||||
|
|
||||||
|
/** The random generator used for generating the key and encryption / decryption */
|
||||||
|
cCtrDrbgContext m_CtrDrbg;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
138
src/PolarSSL++/Sha1Checksum.cpp
Normal file
138
src/PolarSSL++/Sha1Checksum.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
|
||||||
|
// Sha1Checksum.cpp
|
||||||
|
|
||||||
|
// Declares the cSha1Checksum class representing the SHA-1 checksum calculator
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Sha1Checksum.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Self-test the hash formatting for known values:
|
||||||
|
// sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48
|
||||||
|
// sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1
|
||||||
|
// sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6
|
||||||
|
|
||||||
|
static class Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Test(void)
|
||||||
|
{
|
||||||
|
AString DigestNotch, DigestJeb, DigestSimon;
|
||||||
|
Byte Digest[20];
|
||||||
|
cSha1Checksum Checksum;
|
||||||
|
Checksum.Update((const Byte *)"Notch", 5);
|
||||||
|
Checksum.Finalize(Digest);
|
||||||
|
cSha1Checksum::DigestToJava(Digest, DigestNotch);
|
||||||
|
Checksum.Restart();
|
||||||
|
Checksum.Update((const Byte *)"jeb_", 4);
|
||||||
|
Checksum.Finalize(Digest);
|
||||||
|
cSha1Checksum::DigestToJava(Digest, DigestJeb);
|
||||||
|
Checksum.Restart();
|
||||||
|
Checksum.Update((const Byte *)"simon", 5);
|
||||||
|
Checksum.Finalize(Digest);
|
||||||
|
cSha1Checksum::DigestToJava(Digest, DigestSimon);
|
||||||
|
printf("Notch: \"%s\"\n", DigestNotch.c_str());
|
||||||
|
printf("jeb_: \"%s\"\n", DigestJeb.c_str());
|
||||||
|
printf("simon: \"%s\"\n", DigestSimon.c_str());
|
||||||
|
assert(DigestNotch == "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48");
|
||||||
|
assert(DigestJeb == "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1");
|
||||||
|
assert(DigestSimon == "88e16a1019277b15d58faf0541e11910eb756f6");
|
||||||
|
}
|
||||||
|
} test;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cSha1Checksum:
|
||||||
|
|
||||||
|
cSha1Checksum::cSha1Checksum(void) :
|
||||||
|
m_DoesAcceptInput(true)
|
||||||
|
{
|
||||||
|
sha1_starts(&m_Sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSha1Checksum::Update(const Byte * a_Data, size_t a_Length)
|
||||||
|
{
|
||||||
|
ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed
|
||||||
|
|
||||||
|
sha1_update(&m_Sha1, a_Data, a_Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSha1Checksum::Finalize(cSha1Checksum::Checksum & a_Output)
|
||||||
|
{
|
||||||
|
ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed
|
||||||
|
|
||||||
|
sha1_finish(&m_Sha1, a_Output);
|
||||||
|
m_DoesAcceptInput = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSha1Checksum::DigestToJava(const Checksum & a_Digest, AString & a_Out)
|
||||||
|
{
|
||||||
|
Checksum Digest;
|
||||||
|
memcpy(Digest, a_Digest, sizeof(Digest));
|
||||||
|
|
||||||
|
bool IsNegative = (Digest[0] >= 0x80);
|
||||||
|
if (IsNegative)
|
||||||
|
{
|
||||||
|
// Two's complement:
|
||||||
|
bool carry = true; // Add one to the whole number
|
||||||
|
for (int i = 19; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Digest[i] = ~Digest[i];
|
||||||
|
if (carry)
|
||||||
|
{
|
||||||
|
carry = (Digest[i] == 0xff);
|
||||||
|
Digest[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a_Out.clear();
|
||||||
|
a_Out.reserve(40);
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
AppendPrintf(a_Out, "%02x", Digest[i]);
|
||||||
|
}
|
||||||
|
while ((a_Out.length() > 0) && (a_Out[0] == '0'))
|
||||||
|
{
|
||||||
|
a_Out.erase(0, 1);
|
||||||
|
}
|
||||||
|
if (IsNegative)
|
||||||
|
{
|
||||||
|
a_Out.insert(0, "-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSha1Checksum::Restart(void)
|
||||||
|
{
|
||||||
|
sha1_starts(&m_Sha1);
|
||||||
|
m_DoesAcceptInput = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
52
src/PolarSSL++/Sha1Checksum.h
Normal file
52
src/PolarSSL++/Sha1Checksum.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
// Sha1Checksum.h
|
||||||
|
|
||||||
|
// Declares the cSha1Checksum class representing the SHA-1 checksum calculator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/sha1.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Calculates a SHA1 checksum for data stream */
|
||||||
|
class cSha1Checksum
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Byte Checksum[20]; // The type used for storing the checksum
|
||||||
|
|
||||||
|
cSha1Checksum(void);
|
||||||
|
|
||||||
|
/** Adds the specified data to the checksum */
|
||||||
|
void Update(const Byte * a_Data, size_t a_Length);
|
||||||
|
|
||||||
|
/** Calculates and returns the final checksum */
|
||||||
|
void Finalize(Checksum & a_Output);
|
||||||
|
|
||||||
|
/** Returns true if the object is accepts more input data, false if Finalize()-d (need to Restart()) */
|
||||||
|
bool DoesAcceptInput(void) const { return m_DoesAcceptInput; }
|
||||||
|
|
||||||
|
/** Converts a raw 160-bit SHA1 digest into a Java Hex representation
|
||||||
|
According to http://wiki.vg/wiki/index.php?title=Protocol_Encryption&oldid=2802
|
||||||
|
*/
|
||||||
|
static void DigestToJava(const Checksum & a_Digest, AString & a_JavaOut);
|
||||||
|
|
||||||
|
/** Clears the current context and start a new checksum calculation */
|
||||||
|
void Restart(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** True if the object is accepts more input data, false if Finalize()-d (need to Restart()) */
|
||||||
|
bool m_DoesAcceptInput;
|
||||||
|
|
||||||
|
sha1_context m_Sha1;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
243
src/PolarSSL++/SslContext.cpp
Normal file
243
src/PolarSSL++/SslContext.cpp
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
|
||||||
|
// 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"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cSslContext::cSslContext(void) :
|
||||||
|
m_IsValid(false),
|
||||||
|
m_HasHandshaken(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cSslContext::~cSslContext()
|
||||||
|
{
|
||||||
|
if (m_IsValid)
|
||||||
|
{
|
||||||
|
ssl_free(&m_Ssl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> & a_CtrDrbg)
|
||||||
|
{
|
||||||
|
// Check double-initialization:
|
||||||
|
if (m_IsValid)
|
||||||
|
{
|
||||||
|
LOGWARNING("SSL: Double initialization is not supported.");
|
||||||
|
return POLARSSL_ERR_SSL_MALLOC_FAILED; // 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() == NULL)
|
||||||
|
{
|
||||||
|
m_CtrDrbg.reset(new cCtrDrbgContext);
|
||||||
|
m_CtrDrbg->Initialize("MCServer", 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_OPTIONAL);
|
||||||
|
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);
|
||||||
|
ssl_set_verify(&m_Ssl, &SSLVerifyCert, this);
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_IsValid = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName)
|
||||||
|
{
|
||||||
|
// 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(), NULL, m_ExpectedPeerName.empty() ? NULL : 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, (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, (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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
137
src/PolarSSL++/SslContext.h
Normal file
137
src/PolarSSL++/SslContext.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
// SslContext.h
|
||||||
|
|
||||||
|
// Declares the cSslContext class that holds everything a single SSL context needs to function
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/ssl.h"
|
||||||
|
#include "../ByteBuffer.h"
|
||||||
|
#include "X509Cert.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fwd:
|
||||||
|
class cCtrDrbgContext;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Acts as a generic SSL encryptor / decryptor between the two endpoints. The "owner" of this class is expected
|
||||||
|
to create it, initialize it and then provide the means of reading and writing data through the SSL link.
|
||||||
|
This is an abstract base class, there are descendants that handle the specific aspects of how the SSL peer
|
||||||
|
data comes into the system:
|
||||||
|
- cBufferedSslContext uses a cByteBuffer to read and write the data
|
||||||
|
- cCallbackSslContext uses callbacks to provide the data
|
||||||
|
*/
|
||||||
|
class cSslContext abstract
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Creates a new uninitialized context */
|
||||||
|
cSslContext(void);
|
||||||
|
|
||||||
|
~cSslContext();
|
||||||
|
|
||||||
|
/** Initializes the context for use as a server or client.
|
||||||
|
Returns 0 on success, PolarSSL error on failure. */
|
||||||
|
int Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> & a_CtrDrbg = SharedPtr<cCtrDrbgContext>());
|
||||||
|
|
||||||
|
/** Returns true if the object has been initialized properly. */
|
||||||
|
bool IsValid(void) const { return m_IsValid; }
|
||||||
|
|
||||||
|
/** Sets a cert chain as the trusted cert store for this context.
|
||||||
|
Calling this will switch the context into strict cert verification mode.
|
||||||
|
a_ExpectedPeerName is the CommonName that we expect the SSL peer to have in its cert,
|
||||||
|
if it is different, the verification will fail. An empty string will disable the CN check. */
|
||||||
|
void SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName);
|
||||||
|
|
||||||
|
/** Writes data to be encrypted and sent to the SSL peer. Will perform SSL handshake, if needed.
|
||||||
|
Returns the number of bytes actually written, or PolarSSL error code.
|
||||||
|
If the return value is POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE, the owner should send any
|
||||||
|
cached outgoing data to the SSL peer and write any incoming data received from the SSL peer and then call
|
||||||
|
this function again with the same parameters. Note that this may repeat a few times before the data is
|
||||||
|
actually written, mainly due to initial handshake. */
|
||||||
|
int WritePlain(const void * a_Data, size_t a_NumBytes);
|
||||||
|
|
||||||
|
/** Reads data decrypted from the SSL stream. Will perform SSL handshake, if needed.
|
||||||
|
Returns the number of bytes actually read, or PolarSSL error code.
|
||||||
|
If the return value is POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE, the owner should send any
|
||||||
|
cached outgoing data to the SSL peer and write any incoming data received from the SSL peer and then call
|
||||||
|
this function again with the same parameters. Note that this may repeat a few times before the data is
|
||||||
|
actually read, mainly due to initial handshake. */
|
||||||
|
int ReadPlain(void * a_Data, size_t a_MaxBytes);
|
||||||
|
|
||||||
|
/** Performs the SSL handshake.
|
||||||
|
Returns zero on success, PoladSSL error code on failure.
|
||||||
|
If the return value is POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE, the owner should send any
|
||||||
|
cached outgoing data to the SSL peer and write any incoming data received from the SSL peer and then call
|
||||||
|
this function again. Note that this may repeat a few times before the handshake is completed. */
|
||||||
|
int Handshake(void);
|
||||||
|
|
||||||
|
/** Returns true if the SSL handshake has been completed. */
|
||||||
|
bool HasHandshaken(void) const { return m_HasHandshaken; }
|
||||||
|
|
||||||
|
/** Notifies the SSL peer that the connection is being closed.
|
||||||
|
Returns 0 on success, PolarSSL error code on failure. */
|
||||||
|
int NotifyClose(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** True if the object has been initialized properly. */
|
||||||
|
bool m_IsValid;
|
||||||
|
|
||||||
|
/** The random generator to use */
|
||||||
|
SharedPtr<cCtrDrbgContext> m_CtrDrbg;
|
||||||
|
|
||||||
|
/** The SSL context that PolarSSL uses. */
|
||||||
|
ssl_context m_Ssl;
|
||||||
|
|
||||||
|
/** True if the SSL handshake has been completed. */
|
||||||
|
bool m_HasHandshaken;
|
||||||
|
|
||||||
|
/** A copy of the trusted CA root cert store that is passed to us in SetCACerts(), so that the pointer
|
||||||
|
stays valid even after the call, when PolarSSL finally uses it. */
|
||||||
|
cX509CertPtr m_CACerts;
|
||||||
|
|
||||||
|
/** Buffer for the expected peer name. We need to buffer it because the caller may free the string they
|
||||||
|
give us before PolarSSL consumes the raw pointer it gets to the CN. */
|
||||||
|
AString m_ExpectedPeerName;
|
||||||
|
|
||||||
|
|
||||||
|
/** The callback used by PolarSSL when it wants to read encrypted data. */
|
||||||
|
static int ReceiveEncrypted(void * a_This, unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
return ((cSslContext *)a_This)->ReceiveEncrypted(a_Buffer, a_NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The callback used by PolarSSL when it wants to write encrypted data. */
|
||||||
|
static int SendEncrypted(void * a_This, const unsigned char * a_Buffer, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
return ((cSslContext *)a_This)->SendEncrypted(a_Buffer, a_NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
/** The callback used by PolarSSL to output debug messages */
|
||||||
|
static void SSLDebugMessage(void * a_UserParam, int a_Level, const char * a_Text);
|
||||||
|
|
||||||
|
/** The callback used by PolarSSL to log information on the cert chain */
|
||||||
|
static int SSLVerifyCert(void * a_This, x509_crt * a_Crt, int a_Depth, int * a_Flags);
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
/** Called when PolarSSL wants to read encrypted data. */
|
||||||
|
virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) = 0;
|
||||||
|
|
||||||
|
/** Called when PolarSSL wants to write encrypted data. */
|
||||||
|
virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) = 0;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
38
src/PolarSSL++/X509Cert.cpp
Normal file
38
src/PolarSSL++/X509Cert.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
// X509Cert.cpp
|
||||||
|
|
||||||
|
// Implements the cX509Cert class representing a wrapper over X509 certs in PolarSSL
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "X509Cert.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cX509Cert::cX509Cert(void)
|
||||||
|
{
|
||||||
|
x509_crt_init(&m_Cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cX509Cert::~cX509Cert()
|
||||||
|
{
|
||||||
|
x509_crt_free(&m_Cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cX509Cert::Parse(const void * a_CertContents, size_t a_Size)
|
||||||
|
{
|
||||||
|
return x509_crt_parse(&m_Cert, (const unsigned char *)a_CertContents, a_Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
41
src/PolarSSL++/X509Cert.h
Normal file
41
src/PolarSSL++/X509Cert.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
// X509Cert.h
|
||||||
|
|
||||||
|
// Declares the cX509Cert class representing a wrapper over X509 certs in PolarSSL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/x509_crt.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cX509Cert
|
||||||
|
{
|
||||||
|
friend class cSslContext;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cX509Cert(void);
|
||||||
|
~cX509Cert(void);
|
||||||
|
|
||||||
|
/** Parses the certificate chain data into the context.
|
||||||
|
Returns 0 on succes, or PolarSSL error code on failure. */
|
||||||
|
int Parse(const void * a_CertContents, size_t a_Size);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
x509_crt m_Cert;
|
||||||
|
|
||||||
|
/** Returns the internal cert ptr. Only use in PolarSSL API calls. */
|
||||||
|
x509_crt * GetInternal(void) { return &m_Cert; }
|
||||||
|
} ;
|
||||||
|
|
||||||
|
typedef SharedPtr<cX509Cert> cX509CertPtr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -10,13 +10,7 @@
|
|||||||
#include "inifile/iniFile.h"
|
#include "inifile/iniFile.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
|
||||||
#include "polarssl/config.h"
|
#include "PolarSSL++/BlockingSslClientSocket.h"
|
||||||
#include "polarssl/net.h"
|
|
||||||
#include "polarssl/ssl.h"
|
|
||||||
#include "polarssl/entropy.h"
|
|
||||||
#include "polarssl/ctr_drbg.h"
|
|
||||||
#include "polarssl/error.h"
|
|
||||||
#include "polarssl/certs.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -148,92 +142,74 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
|||||||
{
|
{
|
||||||
LOGD("Trying to auth user %s", a_UserName.c_str());
|
LOGD("Trying to auth user %s", a_UserName.c_str());
|
||||||
|
|
||||||
int ret, server_fd = -1;
|
int ret;
|
||||||
unsigned char buf[1024];
|
unsigned char buf[1024];
|
||||||
const char *pers = "cAuthenticator";
|
|
||||||
|
|
||||||
entropy_context entropy;
|
|
||||||
ctr_drbg_context ctr_drbg;
|
|
||||||
ssl_context ssl;
|
|
||||||
x509_crt cacert;
|
|
||||||
|
|
||||||
/* Initialize the RNG and the session data */
|
|
||||||
memset(&ssl, 0, sizeof(ssl_context));
|
|
||||||
x509_crt_init(&cacert);
|
|
||||||
|
|
||||||
entropy_init(&entropy);
|
|
||||||
if ((ret = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0)
|
|
||||||
{
|
|
||||||
LOGWARNING("cAuthenticator: ctr_drbg_init returned %d", ret);
|
|
||||||
|
|
||||||
// Free all resources which have been initialized up to this line
|
|
||||||
x509_crt_free(&cacert);
|
|
||||||
entropy_free(&entropy);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize certificates */
|
/* Initialize certificates */
|
||||||
// TODO: Grab the sessionserver's root CA and any intermediates and hard-code them here, instead of test_ca_list
|
// This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
|
||||||
ret = x509_crt_parse(&cacert, (const unsigned char *)test_ca_list, strlen(test_ca_list));
|
// Downloaded from http://certs.starfieldtech.com/repository/
|
||||||
|
static const AString StarfieldCACert(
|
||||||
|
// G2 cert
|
||||||
|
"-----BEGIN CERTIFICATE-----\n"
|
||||||
|
"MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n"
|
||||||
|
"EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n"
|
||||||
|
"HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\n"
|
||||||
|
"ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw\n"
|
||||||
|
"MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n"
|
||||||
|
"b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\n"
|
||||||
|
"aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp\n"
|
||||||
|
"Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n"
|
||||||
|
"ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\n"
|
||||||
|
"nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1\n"
|
||||||
|
"HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N\n"
|
||||||
|
"Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN\n"
|
||||||
|
"dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0\n"
|
||||||
|
"HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\n"
|
||||||
|
"BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G\n"
|
||||||
|
"CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU\n"
|
||||||
|
"sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3\n"
|
||||||
|
"4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n"
|
||||||
|
"8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K\n"
|
||||||
|
"pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\n"
|
||||||
|
"mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n"
|
||||||
|
"-----END CERTIFICATE-----\n\n"
|
||||||
|
// Original (G1) cert:
|
||||||
|
"-----BEGIN CERTIFICATE-----\n"
|
||||||
|
"MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n"
|
||||||
|
"MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n"
|
||||||
|
"U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n"
|
||||||
|
"NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n"
|
||||||
|
"ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n"
|
||||||
|
"ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n"
|
||||||
|
"DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n"
|
||||||
|
"8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n"
|
||||||
|
"+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n"
|
||||||
|
"X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n"
|
||||||
|
"K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n"
|
||||||
|
"1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n"
|
||||||
|
"A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n"
|
||||||
|
"zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n"
|
||||||
|
"YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n"
|
||||||
|
"bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n"
|
||||||
|
"DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n"
|
||||||
|
"L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n"
|
||||||
|
"eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n"
|
||||||
|
"xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n"
|
||||||
|
"VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n"
|
||||||
|
"WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n"
|
||||||
|
"-----END CERTIFICATE-----\n"
|
||||||
|
);
|
||||||
|
|
||||||
if (ret < 0)
|
// Connect the socket:
|
||||||
|
cBlockingSslClientSocket Socket;
|
||||||
|
Socket.SetTrustedRootCertsFromString(StarfieldCACert, m_Server);
|
||||||
|
if (!Socket.Connect(m_Server, 443))
|
||||||
{
|
{
|
||||||
LOGWARNING("cAuthenticator: x509_crt_parse returned -0x%x", -ret);
|
LOGWARNING("cAuthenticator: Can't connect to %s: %s", m_Server.c_str(), Socket.GetLastErrorText().c_str());
|
||||||
|
|
||||||
// Free all resources which have been initialized up to this line
|
|
||||||
x509_crt_free(&cacert);
|
|
||||||
entropy_free(&entropy);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect */
|
// Create the GET request:
|
||||||
if ((ret = net_connect(&server_fd, m_Server.c_str(), 443)) != 0)
|
|
||||||
{
|
|
||||||
LOGWARNING("cAuthenticator: Can't connect to %s: %d", m_Server.c_str(), ret);
|
|
||||||
|
|
||||||
// Free all resources which have been initialized up to this line
|
|
||||||
x509_crt_free(&cacert);
|
|
||||||
entropy_free(&entropy);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup */
|
|
||||||
if ((ret = ssl_init(&ssl)) != 0)
|
|
||||||
{
|
|
||||||
LOGWARNING("cAuthenticator: ssl_init returned %d", ret);
|
|
||||||
|
|
||||||
// Free all resources which have been initialized up to this line
|
|
||||||
x509_crt_free(&cacert);
|
|
||||||
net_close(server_fd);
|
|
||||||
ssl_free(&ssl);
|
|
||||||
entropy_free(&entropy);
|
|
||||||
memset(&ssl, 0, sizeof(ssl));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
|
|
||||||
ssl_set_authmode(&ssl, SSL_VERIFY_OPTIONAL);
|
|
||||||
ssl_set_ca_chain(&ssl, &cacert, NULL, "PolarSSL Server 1");
|
|
||||||
ssl_set_rng(&ssl, ctr_drbg_random, &ctr_drbg);
|
|
||||||
ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);
|
|
||||||
|
|
||||||
/* Handshake */
|
|
||||||
while ((ret = ssl_handshake(&ssl)) != 0)
|
|
||||||
{
|
|
||||||
if ((ret != POLARSSL_ERR_NET_WANT_READ) && (ret != POLARSSL_ERR_NET_WANT_WRITE))
|
|
||||||
{
|
|
||||||
LOGWARNING("cAuthenticator: ssl_handshake returned -0x%x", -ret);
|
|
||||||
|
|
||||||
// Free all resources which have been initialized up to this line
|
|
||||||
x509_crt_free(&cacert);
|
|
||||||
net_close(server_fd);
|
|
||||||
ssl_free(&ssl);
|
|
||||||
entropy_free(&entropy);
|
|
||||||
memset(&ssl, 0, sizeof(ssl));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the GET request */
|
|
||||||
AString ActualAddress = m_Address;
|
AString ActualAddress = m_Address;
|
||||||
ReplaceString(ActualAddress, "%USERNAME%", a_UserName);
|
ReplaceString(ActualAddress, "%USERNAME%", a_UserName);
|
||||||
ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);
|
ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);
|
||||||
@ -245,30 +221,23 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
|||||||
Request += "Connection: close\r\n";
|
Request += "Connection: close\r\n";
|
||||||
Request += "\r\n";
|
Request += "\r\n";
|
||||||
|
|
||||||
ret = ssl_write(&ssl, (const unsigned char *)Request.c_str(), Request.size());
|
if (!Socket.Send(Request.c_str(), Request.size()))
|
||||||
if (ret <= 0)
|
|
||||||
{
|
{
|
||||||
LOGWARNING("cAuthenticator: ssl_write returned %d", ret);
|
LOGWARNING("cAuthenticator: Writing SSL data failed: %s", Socket.GetLastErrorText().c_str());
|
||||||
|
|
||||||
// Free all resources which have been initialized up to this line
|
|
||||||
x509_crt_free(&cacert);
|
|
||||||
net_close(server_fd);
|
|
||||||
ssl_free(&ssl);
|
|
||||||
entropy_free(&entropy);
|
|
||||||
memset(&ssl, 0, sizeof(ssl));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the HTTP response */
|
// Read the HTTP response:
|
||||||
std::string Response;
|
std::string Response;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
memset(buf, 0, sizeof(buf));
|
ret = Socket.Receive(buf, sizeof(buf));
|
||||||
ret = ssl_read(&ssl, buf, sizeof(buf));
|
|
||||||
|
|
||||||
if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
|
if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
|
||||||
{
|
{
|
||||||
continue;
|
// This value should never be returned, it is handled internally by cBlockingSslClientSocket
|
||||||
|
LOGWARNING("cAuthenticator: SSL reading failed internally.");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
|
if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
|
||||||
{
|
{
|
||||||
@ -276,24 +245,18 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
|||||||
}
|
}
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
LOGWARNING("cAuthenticator: ssl_read returned %d", ret);
|
LOGWARNING("cAuthenticator: SSL reading failed: -0x%x", -ret);
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
LOGWARNING("cAuthenticator: EOF");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Response.append((const char *)buf, ret);
|
Response.append((const char *)buf, (size_t)ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_close_notify(&ssl);
|
Socket.Disconnect();
|
||||||
x509_crt_free(&cacert);
|
|
||||||
net_close(server_fd);
|
|
||||||
ssl_free(&ssl);
|
|
||||||
entropy_free(&entropy);
|
|
||||||
memset(&ssl, 0, sizeof(ssl));
|
|
||||||
|
|
||||||
// Check the HTTP status line:
|
// Check the HTTP status line:
|
||||||
AString prefix("HTTP/1.1 200 OK");
|
AString prefix("HTTP/1.1 200 OK");
|
||||||
|
@ -18,19 +18,7 @@
|
|||||||
#include "../WorldStorage/FastNBT.h"
|
#include "../WorldStorage/FastNBT.h"
|
||||||
#include "../WorldStorage/EnchantmentSerializer.h"
|
#include "../WorldStorage/EnchantmentSerializer.h"
|
||||||
#include "../StringCompression.h"
|
#include "../StringCompression.h"
|
||||||
|
#include "PolarSSL++/Sha1Checksum.h"
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable:4127)
|
|
||||||
#pragma warning(disable:4244)
|
|
||||||
#pragma warning(disable:4231)
|
|
||||||
#pragma warning(disable:4189)
|
|
||||||
#pragma warning(disable:4702)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -819,7 +807,7 @@ void cProtocol132::SendEncryptionKeyRequest(void)
|
|||||||
void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce)
|
void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce)
|
||||||
{
|
{
|
||||||
// Decrypt EncNonce using privkey
|
// Decrypt EncNonce using privkey
|
||||||
cRSAPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey();
|
cRsaPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey();
|
||||||
|
|
||||||
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
|
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
|
||||||
int res = rsaDecryptor.Decrypt((const Byte *)a_EncNonce.data(), a_EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce));
|
int res = rsaDecryptor.Decrypt((const Byte *)a_EncNonce.data(), a_EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce));
|
||||||
@ -876,7 +864,7 @@ void cProtocol132::StartEncryption(const Byte * a_Key)
|
|||||||
m_IsEncrypted = true;
|
m_IsEncrypted = true;
|
||||||
|
|
||||||
// Prepare the m_AuthServerID:
|
// Prepare the m_AuthServerID:
|
||||||
cSHA1Checksum Checksum;
|
cSha1Checksum Checksum;
|
||||||
cServer * Server = cRoot::Get()->GetServer();
|
cServer * Server = cRoot::Get()->GetServer();
|
||||||
AString ServerID = Server->GetServerID();
|
AString ServerID = Server->GetServerID();
|
||||||
Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length());
|
Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length());
|
||||||
@ -884,7 +872,7 @@ void cProtocol132::StartEncryption(const Byte * a_Key)
|
|||||||
Checksum.Update((const Byte *)Server->GetPublicKeyDER().data(), Server->GetPublicKeyDER().size());
|
Checksum.Update((const Byte *)Server->GetPublicKeyDER().data(), Server->GetPublicKeyDER().size());
|
||||||
Byte Digest[20];
|
Byte Digest[20];
|
||||||
Checksum.Finalize(Digest);
|
Checksum.Finalize(Digest);
|
||||||
cSHA1Checksum::DigestToJava(Digest, m_AuthServerID);
|
cSha1Checksum::DigestToJava(Digest, m_AuthServerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../Crypto.h"
|
#include "PolarSSL++/AesCfb128Decryptor.h"
|
||||||
|
#include "PolarSSL++/AesCfb128Encryptor.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -79,8 +80,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
bool m_IsEncrypted;
|
bool m_IsEncrypted;
|
||||||
|
|
||||||
cAESCFBDecryptor m_Decryptor;
|
cAesCfb128Decryptor m_Decryptor;
|
||||||
cAESCFBEncryptor m_Encryptor;
|
cAesCfb128Encryptor m_Encryptor;
|
||||||
|
|
||||||
AString m_DataToSend;
|
AString m_DataToSend;
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ Implements the 1.7.x protocol classes:
|
|||||||
#include "../CompositeChat.h"
|
#include "../CompositeChat.h"
|
||||||
#include "../Entities/ArrowEntity.h"
|
#include "../Entities/ArrowEntity.h"
|
||||||
#include "../Entities/FireworkEntity.h"
|
#include "../Entities/FireworkEntity.h"
|
||||||
|
#include "PolarSSL++/Sha1Checksum.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1690,7 +1691,7 @@ void cProtocol172::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt EncNonce using privkey
|
// Decrypt EncNonce using privkey
|
||||||
cRSAPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey();
|
cRsaPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey();
|
||||||
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
|
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
|
||||||
int res = rsaDecryptor.Decrypt((const Byte *)EncNonce.data(), EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce));
|
int res = rsaDecryptor.Decrypt((const Byte *)EncNonce.data(), EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce));
|
||||||
if (res != 4)
|
if (res != 4)
|
||||||
@ -2293,7 +2294,7 @@ void cProtocol172::StartEncryption(const Byte * a_Key)
|
|||||||
m_IsEncrypted = true;
|
m_IsEncrypted = true;
|
||||||
|
|
||||||
// Prepare the m_AuthServerID:
|
// Prepare the m_AuthServerID:
|
||||||
cSHA1Checksum Checksum;
|
cSha1Checksum Checksum;
|
||||||
cServer * Server = cRoot::Get()->GetServer();
|
cServer * Server = cRoot::Get()->GetServer();
|
||||||
const AString & ServerID = Server->GetServerID();
|
const AString & ServerID = Server->GetServerID();
|
||||||
Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length());
|
Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length());
|
||||||
@ -2301,7 +2302,7 @@ void cProtocol172::StartEncryption(const Byte * a_Key)
|
|||||||
Checksum.Update((const Byte *)Server->GetPublicKeyDER().data(), Server->GetPublicKeyDER().size());
|
Checksum.Update((const Byte *)Server->GetPublicKeyDER().data(), Server->GetPublicKeyDER().size());
|
||||||
Byte Digest[20];
|
Byte Digest[20];
|
||||||
Checksum.Finalize(Digest);
|
Checksum.Finalize(Digest);
|
||||||
cSHA1Checksum::DigestToJava(Digest, m_AuthServerID);
|
cSha1Checksum::DigestToJava(Digest, m_AuthServerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ Declares the 1.7.x protocol classes:
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../Crypto.h"
|
#include "PolarSSL++/AesCfb128Decryptor.h"
|
||||||
|
#include "PolarSSL++/AesCfb128Encryptor.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -236,8 +237,8 @@ protected:
|
|||||||
|
|
||||||
bool m_IsEncrypted;
|
bool m_IsEncrypted;
|
||||||
|
|
||||||
cAESCFBDecryptor m_Decryptor;
|
cAesCfb128Decryptor m_Decryptor;
|
||||||
cAESCFBEncryptor m_Encryptor;
|
cAesCfb128Decryptor m_Encryptor;
|
||||||
|
|
||||||
/** The logfile where the comm is logged, when g_ShouldLogComm is true */
|
/** The logfile where the comm is logged, when g_ShouldLogComm is true */
|
||||||
cFile m_CommLogFile;
|
cFile m_CommLogFile;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#pragma warning(disable:4702)
|
#pragma warning(disable:4702)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Crypto.h"
|
#include "PolarSSL++/RsaPrivateKey.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@ -109,7 +109,7 @@ public: // tolua_export
|
|||||||
/** Returns base64 encoded favicon data (obtained from favicon.png) */
|
/** Returns base64 encoded favicon data (obtained from favicon.png) */
|
||||||
const AString & GetFaviconData(void) const { return m_FaviconData; }
|
const AString & GetFaviconData(void) const { return m_FaviconData; }
|
||||||
|
|
||||||
cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
||||||
const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; }
|
const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; }
|
||||||
|
|
||||||
bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; }
|
bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; }
|
||||||
@ -182,7 +182,7 @@ private:
|
|||||||
bool m_bRestarting;
|
bool m_bRestarting;
|
||||||
|
|
||||||
/** The private key used for the assymetric encryption start in the protocols */
|
/** The private key used for the assymetric encryption start in the protocols */
|
||||||
cRSAPrivateKey m_PrivateKey;
|
cRsaPrivateKey m_PrivateKey;
|
||||||
|
|
||||||
/** Public key for m_PrivateKey, ASN1-DER-encoded */
|
/** Public key for m_PrivateKey, ASN1-DER-encoded */
|
||||||
AString m_PublicKeyDER;
|
AString m_PublicKeyDER;
|
||||||
|
Loading…
Reference in New Issue
Block a user