Experimental guid authentication
This commit is contained in:
parent
59cb673692
commit
6fbae4461e
@ -9,6 +9,7 @@ namespace Components
|
|||||||
Loader::Register(new Flags());
|
Loader::Register(new Flags());
|
||||||
Loader::Register(new Singleton());
|
Loader::Register(new Singleton());
|
||||||
|
|
||||||
|
Loader::Register(new Auth());
|
||||||
Loader::Register(new Dvar());
|
Loader::Register(new Dvar());
|
||||||
Loader::Register(new Maps());
|
Loader::Register(new Maps());
|
||||||
Loader::Register(new News());
|
Loader::Register(new News());
|
||||||
|
@ -23,6 +23,7 @@ namespace Components
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Modules\Auth.hpp"
|
||||||
#include "Modules\Dvar.hpp"
|
#include "Modules\Dvar.hpp"
|
||||||
#include "Modules\Maps.hpp"
|
#include "Modules\Maps.hpp"
|
||||||
#include "Modules\News.hpp"
|
#include "Modules\News.hpp"
|
||||||
|
159
src/Components/Modules/Auth.cpp
Normal file
159
src/Components/Modules/Auth.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#include "STDInclude.hpp"
|
||||||
|
|
||||||
|
namespace Components
|
||||||
|
{
|
||||||
|
Auth::AuthInfo Auth::ClientAuthInfo[18];
|
||||||
|
|
||||||
|
void Auth::Frame()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < *Game::svs_numclients; i++)
|
||||||
|
{
|
||||||
|
Game::client_t* client = &Game::svs_clients[i];
|
||||||
|
Auth::AuthInfo* info = &Auth::ClientAuthInfo[i];
|
||||||
|
|
||||||
|
// State must be 5 or greater here, as otherwise the client will crash when being kicked.
|
||||||
|
// That's due to the hunk being freed by that time, but it hasn't been reallocated, therefore all future allocations will cause a crash.
|
||||||
|
// Additionally, the game won't catch the errors and simply lose the connection, so we even have to add a delay to send the data.
|
||||||
|
|
||||||
|
// Not sure if that's potentially unsafe, though.
|
||||||
|
// Players faking their GUID will be connected for 5 seconds, which allows them to fuck up everything.
|
||||||
|
// I think we have to perform the verification when clients are still in state 3, but for now it works.
|
||||||
|
|
||||||
|
// I think we even have to lock the client into state 3 until the verification is done.
|
||||||
|
// Intercepting the entire connection process to perform the authentication within state 3 solely is necessary, due to having a timeout.
|
||||||
|
// Not sending a response might allow the player to connect for a few seconds (<= 5) until the timeout is reached.
|
||||||
|
if (client->state >= 5)
|
||||||
|
{
|
||||||
|
if (info->state == Auth::STATE_NEGOTIATING && (Game::Com_Milliseconds() - info->time) > 1000 * 5)
|
||||||
|
{
|
||||||
|
info->state = Auth::STATE_INVALID;
|
||||||
|
info->time = Game::Com_Milliseconds();
|
||||||
|
Game::SV_KickClientError(client, "XUID verification timeout!");
|
||||||
|
}
|
||||||
|
else if (info->state == Auth::STATE_UNKNOWN && info->time && (Game::Com_Milliseconds() - info->time) > 1000 * 5) // Wait 5 seconds (error delay)
|
||||||
|
{
|
||||||
|
Logger::Print("Sending XUID authentication request to %s\n", Network::Address(client->adr).GetString());
|
||||||
|
|
||||||
|
info->state = Auth::STATE_NEGOTIATING;
|
||||||
|
info->time = Game::Com_Milliseconds();
|
||||||
|
info->challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
|
||||||
|
Network::SendCommand(client->adr, "xuidAuthReq", info->challenge);
|
||||||
|
}
|
||||||
|
else if (info->state == Auth::STATE_UNKNOWN && !info->time)
|
||||||
|
{
|
||||||
|
info->time = Game::Com_Milliseconds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Auth::RegisterClient(int clientNum)
|
||||||
|
{
|
||||||
|
if (clientNum >= 18) return;
|
||||||
|
|
||||||
|
Network::Address address(Game::svs_clients[clientNum].adr);
|
||||||
|
|
||||||
|
if (address.GetType() == Game::netadrtype_t::NA_BOT)
|
||||||
|
{
|
||||||
|
Auth::ClientAuthInfo[clientNum].state = Auth::STATE_VALID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::Print("Registering client %s\n", address.GetString());
|
||||||
|
Auth::ClientAuthInfo[clientNum].time = 0;
|
||||||
|
Auth::ClientAuthInfo[clientNum].state = Auth::STATE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __declspec(naked) Auth::RegisterClientStub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push esi
|
||||||
|
call Auth::RegisterClient
|
||||||
|
pop esi
|
||||||
|
|
||||||
|
imul esi, 366Ch
|
||||||
|
mov eax, 478A18h
|
||||||
|
jmp eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Auth::Auth()
|
||||||
|
{
|
||||||
|
// Only clients receive the auth request
|
||||||
|
if (!Dedicated::IsDedicated())
|
||||||
|
{
|
||||||
|
Network::Handle("xuidAuthReq", [] (Network::Address address, std::string data)
|
||||||
|
{
|
||||||
|
Logger::Print("Received XUID authentication request from %s\n", address.GetString());
|
||||||
|
|
||||||
|
// Only accept requests from the server we're connected to
|
||||||
|
if (address != *Game::connectedHost) return;
|
||||||
|
if (!Steam::User::GuidKey.IsValid()) return;
|
||||||
|
|
||||||
|
Proto::Auth::Response response;
|
||||||
|
response.set_publickey(Steam::User::GuidKey.GetPublicKey());
|
||||||
|
response.set_signature(Utils::Cryptography::ECDSA::SignMessage(Steam::User::GuidKey, data+"1"));
|
||||||
|
|
||||||
|
Network::SendCommand(address, "xuidAuthResp", response.SerializeAsString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Network::Handle("xuidAuthResp", [] (Network::Address address, std::string data)
|
||||||
|
{
|
||||||
|
Logger::Print("Received XUID authentication response from %s\n", address.GetString());
|
||||||
|
|
||||||
|
Proto::Auth::Response response;
|
||||||
|
response.ParseFromString(data);
|
||||||
|
|
||||||
|
if (response.signature().empty()) return;
|
||||||
|
if (response.publickey().empty()) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < *Game::svs_numclients; i++)
|
||||||
|
{
|
||||||
|
Game::client_t* client = &Game::svs_clients[i];
|
||||||
|
Auth::AuthInfo* info = &Auth::ClientAuthInfo[i];
|
||||||
|
|
||||||
|
if (client->state >= 3 && address == client->adr && info->state == Auth::STATE_NEGOTIATING)
|
||||||
|
{
|
||||||
|
unsigned int id = static_cast<unsigned int>(~0x110000100000000 & client->steamid);
|
||||||
|
|
||||||
|
// Check if guid matches the certificate
|
||||||
|
if (id != (Utils::OneAtATime(response.publickey().data(), response.publickey().size()) & ~0x80000000))
|
||||||
|
{
|
||||||
|
info->state = Auth::STATE_INVALID;
|
||||||
|
Game::SV_KickClientError(client, "XUID doesn't match the certificate!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->publicKey.Set(response.publickey());
|
||||||
|
|
||||||
|
if (Utils::Cryptography::ECDSA::VerifyMessage(info->publicKey, info->challenge, response.signature()))
|
||||||
|
{
|
||||||
|
info->state = Auth::STATE_VALID;
|
||||||
|
Logger::Print("Verified XUID from %s\n", address.GetString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->state = Auth::STATE_INVALID;
|
||||||
|
Game::SV_KickClientError(client, "Challenge signature was invalid!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Install frame handlers
|
||||||
|
Dedicated::OnFrame(Auth::Frame);
|
||||||
|
Renderer::OnFrame(Auth::Frame);
|
||||||
|
|
||||||
|
// Install registration hook
|
||||||
|
Utils::Hook(0x478A12, Auth::RegisterClientStub, HOOK_JUMP).Install()->Quick();
|
||||||
|
}
|
||||||
|
|
||||||
|
Auth::~Auth()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
35
src/Components/Modules/Auth.hpp
Normal file
35
src/Components/Modules/Auth.hpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
namespace Components
|
||||||
|
{
|
||||||
|
class Auth : public Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Auth();
|
||||||
|
~Auth();
|
||||||
|
const char* GetName() { return "Auth"; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum AuthState
|
||||||
|
{
|
||||||
|
STATE_UNKNOWN,
|
||||||
|
STATE_NEGOTIATING,
|
||||||
|
STATE_VALID,
|
||||||
|
STATE_INVALID,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AuthInfo
|
||||||
|
{
|
||||||
|
Utils::Cryptography::ECDSA::Key publicKey;
|
||||||
|
std::string challenge;
|
||||||
|
AuthState state;
|
||||||
|
int time;
|
||||||
|
};
|
||||||
|
|
||||||
|
static AuthInfo ClientAuthInfo[18];
|
||||||
|
|
||||||
|
static void Frame();
|
||||||
|
|
||||||
|
static void RegisterClient(int clientNum);
|
||||||
|
static void RegisterClientStub();
|
||||||
|
};
|
||||||
|
}
|
@ -193,6 +193,7 @@ namespace Components
|
|||||||
|
|
||||||
// Disable host migration
|
// Disable host migration
|
||||||
Utils::Hook::Set<BYTE>(0x5B58B2, 0xEB);
|
Utils::Hook::Set<BYTE>(0x5B58B2, 0xEB);
|
||||||
|
Utils::Hook::Set<BYTE>(0x4D6171, 0);
|
||||||
|
|
||||||
// Patch playlist stuff for non-party behavior
|
// Patch playlist stuff for non-party behavior
|
||||||
Utils::Hook::Set<Game::dvar_t**>(0x4A4093, &partyEnable);
|
Utils::Hook::Set<Game::dvar_t**>(0x4A4093, &partyEnable);
|
||||||
|
@ -177,6 +177,8 @@ namespace Game
|
|||||||
|
|
||||||
gentity_t* g_entities = (gentity_t*)0x18835D8;
|
gentity_t* g_entities = (gentity_t*)0x18835D8;
|
||||||
|
|
||||||
|
netadr_t* connectedHost = (netadr_t*)0xA1E888;
|
||||||
|
|
||||||
SOCKET* ip_socket = (SOCKET*)0x64A3008;
|
SOCKET* ip_socket = (SOCKET*)0x64A3008;
|
||||||
|
|
||||||
void* ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
void* ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
||||||
@ -303,4 +305,33 @@ namespace Game
|
|||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SV_KickClient(client_t* client, const char* reason)
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
mov edi, 0
|
||||||
|
mov esi, client
|
||||||
|
push reason
|
||||||
|
push 0
|
||||||
|
push 0
|
||||||
|
mov eax, 6249A0h
|
||||||
|
call eax
|
||||||
|
add esp, 0Ch
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SV_KickClientError(client_t* client, const char* reason)
|
||||||
|
{
|
||||||
|
if (client->state < 5)
|
||||||
|
{
|
||||||
|
Components::Network::Send(client->adr, Utils::VA("error\n%s", reason));
|
||||||
|
}
|
||||||
|
|
||||||
|
SV_KickClient(client, reason);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,6 +357,7 @@ namespace Game
|
|||||||
|
|
||||||
extern gentity_t* g_entities;
|
extern gentity_t* g_entities;
|
||||||
|
|
||||||
|
extern netadr_t* connectedHost;
|
||||||
extern SOCKET* ip_socket;
|
extern SOCKET* ip_socket;
|
||||||
|
|
||||||
void* ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
void* ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
||||||
@ -372,4 +373,7 @@ namespace Game
|
|||||||
void MessageBox(std::string message, std::string title);
|
void MessageBox(std::string message, std::string title);
|
||||||
|
|
||||||
unsigned int R_HashString(const char* string);
|
unsigned int R_HashString(const char* string);
|
||||||
|
|
||||||
|
void SV_KickClient(client_t* client, const char* reason);
|
||||||
|
void SV_KickClientError(client_t* client, const char* reason);
|
||||||
}
|
}
|
||||||
|
@ -905,7 +905,7 @@ namespace Game
|
|||||||
// 269044
|
// 269044
|
||||||
char pad6[9228];
|
char pad6[9228];
|
||||||
// 278272
|
// 278272
|
||||||
__int64 steamid;
|
unsigned __int64 steamid;
|
||||||
// 278280
|
// 278280
|
||||||
char pad7[403592];
|
char pad7[403592];
|
||||||
} client_t;
|
} client_t;
|
||||||
|
9
src/Proto/auth.proto
Normal file
9
src/Proto/auth.proto
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package Proto.Auth;
|
||||||
|
|
||||||
|
message Response
|
||||||
|
{
|
||||||
|
bytes signature = 1;
|
||||||
|
bytes publickey = 2;
|
||||||
|
}
|
@ -63,6 +63,7 @@
|
|||||||
|
|
||||||
// Protobuf
|
// Protobuf
|
||||||
#include "proto/network.pb.h"
|
#include "proto/network.pb.h"
|
||||||
|
#include "proto/auth.pb.h"
|
||||||
#include "proto/node.pb.h"
|
#include "proto/node.pb.h"
|
||||||
#include "proto/rcon.pb.h"
|
#include "proto/rcon.pb.h"
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Steam
|
namespace Steam
|
||||||
{
|
{
|
||||||
|
::Utils::Cryptography::ECDSA::Key User::GuidKey;
|
||||||
|
|
||||||
int User::GetHSteamUser()
|
int User::GetHSteamUser()
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -26,20 +28,20 @@ namespace Steam
|
|||||||
}
|
}
|
||||||
else if (Components::Singleton::IsFirstInstance()) // Hardware guid
|
else if (Components::Singleton::IsFirstInstance()) // Hardware guid
|
||||||
{
|
{
|
||||||
DATA_BLOB Data[2];
|
if (!User::GuidKey.IsValid())
|
||||||
Data[0].pbData = (BYTE *)"AAAAAAAAAA";
|
|
||||||
Data[0].cbData = 10;
|
|
||||||
|
|
||||||
CryptProtectData(Data, NULL, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE, &Data[1]);
|
|
||||||
|
|
||||||
subId = ::Utils::OneAtATime(reinterpret_cast<char*>(Data[1].pbData), 52);
|
|
||||||
|
|
||||||
if (!subId)
|
|
||||||
{
|
{
|
||||||
Components::Logger::Print("Hardware-based GUID generation failed!\n");
|
User::GuidKey.Import(::Utils::ReadFile("players/guid.dat"), PK_PRIVATE);
|
||||||
subId = (Game::Com_Milliseconds() + timeGetTime());
|
|
||||||
|
if (!User::GuidKey.IsValid())
|
||||||
|
{
|
||||||
|
User::GuidKey = ::Utils::Cryptography::ECDSA::GenerateKey(512);
|
||||||
|
::Utils::WriteFile("players/guid.dat", User::GuidKey.Export(PK_PRIVATE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string publicKey = User::GuidKey.GetPublicKey();
|
||||||
|
subId = ::Utils::OneAtATime(publicKey.data(), publicKey.size());
|
||||||
|
}
|
||||||
else // Random guid
|
else // Random guid
|
||||||
{
|
{
|
||||||
subId = (Game::Com_Milliseconds() + timeGetTime());
|
subId = (Game::Com_Milliseconds() + timeGetTime());
|
||||||
@ -54,7 +56,7 @@ namespace Steam
|
|||||||
|
|
||||||
int User::InitiateGameConnection(void *pAuthBlob, int cbMaxAuthBlob, SteamID steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer, bool bSecure)
|
int User::InitiateGameConnection(void *pAuthBlob, int cbMaxAuthBlob, SteamID steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer, bool bSecure)
|
||||||
{
|
{
|
||||||
// TODO: Generate auth ticket!
|
Components::Logger::Print("%s\n", __FUNCTION__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,5 +20,7 @@ namespace Steam
|
|||||||
virtual void EndAuthSession(SteamID steamID);
|
virtual void EndAuthSession(SteamID steamID);
|
||||||
virtual void CancelAuthTicket(unsigned int hAuthTicket);
|
virtual void CancelAuthTicket(unsigned int hAuthTicket);
|
||||||
virtual unsigned int UserHasLicenseForApp(SteamID steamID, unsigned int appID);
|
virtual unsigned int UserHasLicenseForApp(SteamID steamID, unsigned int appID);
|
||||||
|
|
||||||
|
static ::Utils::Cryptography::ECDSA::Key GuidKey;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,9 @@ namespace Utils
|
|||||||
public:
|
public:
|
||||||
Key() : KeyStorage(new ecc_key)
|
Key() : KeyStorage(new ecc_key)
|
||||||
{
|
{
|
||||||
ZeroMemory(this->KeyStorage.get(), sizeof(*this->KeyStorage.get()));
|
ZeroMemory(this->KeyStorage.get(), sizeof(*this->GetKeyPtr()));
|
||||||
};
|
};
|
||||||
Key(ecc_key* key) : Key() { if(key) std::memmove(this->KeyStorage.get(), key, sizeof(*key)); };
|
Key(ecc_key* key) : Key() { if(key) std::memmove(this->GetKeyPtr(), key, sizeof(*key)); };
|
||||||
Key(ecc_key key) : Key(&key) {};
|
Key(ecc_key key) : Key(&key) {};
|
||||||
~Key()
|
~Key()
|
||||||
{
|
{
|
||||||
@ -34,7 +34,7 @@ namespace Utils
|
|||||||
|
|
||||||
bool IsValid()
|
bool IsValid()
|
||||||
{
|
{
|
||||||
return (!Utils::MemIsSet(this->KeyStorage.get(), 0, sizeof(*this->KeyStorage.get())));
|
return (!Utils::MemIsSet(this->GetKeyPtr(), 0, sizeof(*this->GetKeyPtr())));
|
||||||
}
|
}
|
||||||
|
|
||||||
ecc_key* GetKeyPtr()
|
ecc_key* GetKeyPtr()
|
||||||
@ -59,20 +59,43 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
this->Free();
|
this->Free();
|
||||||
|
|
||||||
if (ecc_ansi_x963_import(reinterpret_cast<const uint8_t*>(pubKeyBuffer.data()), pubKeyBuffer.size(), this->KeyStorage.get()) != CRYPT_OK)
|
if (ecc_ansi_x963_import(reinterpret_cast<const uint8_t*>(pubKeyBuffer.data()), pubKeyBuffer.size(), this->GetKeyPtr()) != CRYPT_OK)
|
||||||
{
|
{
|
||||||
ZeroMemory(this->KeyStorage.get(), sizeof(*this->KeyStorage.get()));
|
ZeroMemory(this->KeyStorage.get(), sizeof(*this->GetKeyPtr()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Import(std::string key, int type = PK_PRIVATE)
|
||||||
|
{
|
||||||
|
this->Free();
|
||||||
|
|
||||||
|
if (ecc_import(reinterpret_cast<const uint8_t*>(key.data()), key.size(), this->GetKeyPtr()) != CRYPT_OK)
|
||||||
|
{
|
||||||
|
ZeroMemory(this->KeyStorage.get(), sizeof(*this->GetKeyPtr()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Export(int type = PK_PRIVATE)
|
||||||
|
{
|
||||||
|
uint8_t buffer[4096] = { 0 };
|
||||||
|
DWORD length = sizeof(buffer);
|
||||||
|
|
||||||
|
if (ecc_export(buffer, &length, type, this->GetKeyPtr()) == CRYPT_OK)
|
||||||
|
{
|
||||||
|
return std::string(reinterpret_cast<char*>(buffer), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void Free()
|
void Free()
|
||||||
{
|
{
|
||||||
if (this->IsValid())
|
if (this->IsValid())
|
||||||
{
|
{
|
||||||
ecc_free(this->KeyStorage.get());
|
ecc_free(this->GetKeyPtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroMemory(this->KeyStorage.get(), sizeof(*this->KeyStorage.get()));
|
ZeroMemory(this->GetKeyPtr(), sizeof(*this->GetKeyPtr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -92,9 +115,9 @@ namespace Utils
|
|||||||
public:
|
public:
|
||||||
Key() : KeyStorage(new rsa_key)
|
Key() : KeyStorage(new rsa_key)
|
||||||
{
|
{
|
||||||
ZeroMemory(this->KeyStorage.get(), sizeof(*this->KeyStorage.get()));
|
ZeroMemory(this->KeyStorage.get(), sizeof(*this->GetKeyPtr()));
|
||||||
};
|
};
|
||||||
Key(rsa_key* key) : Key() { if (key) std::memmove(this->KeyStorage.get(), key, sizeof(*key)); };
|
Key(rsa_key* key) : Key() { if (key) std::memmove(this->GetKeyPtr(), key, sizeof(*key)); };
|
||||||
Key(rsa_key key) : Key(&key) {};
|
Key(rsa_key key) : Key(&key) {};
|
||||||
~Key()
|
~Key()
|
||||||
{
|
{
|
||||||
@ -111,17 +134,17 @@ namespace Utils
|
|||||||
|
|
||||||
bool IsValid()
|
bool IsValid()
|
||||||
{
|
{
|
||||||
return (!Utils::MemIsSet(this->KeyStorage.get(), 0, sizeof(*this->KeyStorage.get())));
|
return (!Utils::MemIsSet(this->GetKeyPtr(), 0, sizeof(*this->GetKeyPtr())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Free()
|
void Free()
|
||||||
{
|
{
|
||||||
if (this->IsValid())
|
if (this->IsValid())
|
||||||
{
|
{
|
||||||
rsa_free(this->KeyStorage.get());
|
rsa_free(this->GetKeyPtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroMemory(this->KeyStorage.get(), sizeof(*this->KeyStorage.get()));
|
ZeroMemory(this->GetKeyPtr(), sizeof(*this->GetKeyPtr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user