1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

Fix #8802: public key signature being null terminated.

This commit is contained in:
Matt
2019-03-09 13:58:23 +01:00
parent 057a27ad01
commit d7a4570a1c
3 changed files with 28 additions and 32 deletions

View File

@@ -159,8 +159,7 @@ public:
void Client_Send_TOKEN();
void Client_Send_AUTH(
const std::string& name, const std::string& password, const std::string& pubkey, const std::string& sig,
size_t sigsize);
const std::string& name, const std::string& password, const std::string& pubkey, const std::vector<uint8_t>& signature);
void Server_Send_AUTH(NetworkConnection& connection);
void Server_Send_TOKEN(NetworkConnection& connection);
void Server_Send_MAP(NetworkConnection* connection = nullptr);
@@ -1358,7 +1357,7 @@ void Network::Client_Send_TOKEN()
}
void Network::Client_Send_AUTH(
const std::string& name, const std::string& password, const std::string& pubkey, const std::string& sig, size_t sigsize)
const std::string& name, const std::string& password, const std::string& pubkey, const std::vector<uint8_t>& signature)
{
std::unique_ptr<NetworkPacket> packet(NetworkPacket::Allocate());
*packet << (uint32_t)NETWORK_COMMAND_AUTH;
@@ -1366,9 +1365,9 @@ void Network::Client_Send_AUTH(
packet->WriteString(name.c_str());
packet->WriteString(password.c_str());
packet->WriteString(pubkey.c_str());
assert(sigsize <= (size_t)UINT32_MAX);
*packet << (uint32_t)sigsize;
packet->Write((const uint8_t*)sig.c_str(), sigsize);
assert(signature.size() <= (size_t)UINT32_MAX);
*packet << (uint32_t)signature.size();
packet->Write(signature.data(), signature.size());
_serverConnection->AuthStatus = NETWORK_AUTH_REQUESTED;
_serverConnection->QueuePacket(std::move(packet));
}
@@ -2195,12 +2194,12 @@ void Network::Client_Handle_TOKEN(NetworkConnection& connection, NetworkPacket&
uint32_t challenge_size;
packet >> challenge_size;
const char* challenge = (const char*)packet.Read(challenge_size);
size_t sigsize;
char* signature;
std::vector<uint8_t> signature;
const std::string pubkey = _key.PublicKeyString();
_challenge.resize(challenge_size);
std::memcpy(_challenge.data(), challenge, challenge_size);
bool ok = _key.Sign(_challenge.data(), _challenge.size(), &signature, &sigsize);
bool ok = _key.Sign(_challenge.data(), _challenge.size(), signature);
if (!ok)
{
log_error("Failed to sign server's challenge.");
@@ -2213,9 +2212,7 @@ void Network::Client_Handle_TOKEN(NetworkConnection& connection, NetworkPacket&
_key.Unload();
const char* password = String::IsNullOrEmpty(gCustomPassword) ? "" : gCustomPassword;
Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature, sigsize);
delete[] signature;
Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature);
}
void Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet)
@@ -2403,20 +2400,24 @@ void Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& p
{
try
{
const char* signature = (const char*)packet.Read(sigsize);
if (signature == nullptr)
std::vector<uint8_t> signature;
signature.resize(sigsize);
const uint8_t* signatureData = (const uint8_t*)packet.Read(sigsize);
if (signatureData == nullptr)
{
throw std::runtime_error("Failed to read packet.");
}
std::memcpy(signature.data(), signatureData, sigsize);
auto ms = MemoryStream(pubkey, strlen(pubkey));
if (!connection.Key.LoadPublic(&ms))
{
throw std::runtime_error("Failed to load public key.");
}
bool verified = connection.Key.Verify(
connection.Challenge.data(), connection.Challenge.size(), signature, sigsize);
bool verified = connection.Key.Verify(connection.Challenge.data(), connection.Challenge.size(), signature);
const std::string hash = connection.Key.PublicKeyHash();
if (verified)
{
@@ -3812,14 +3813,13 @@ void network_send_password(const std::string& password)
return;
}
const std::string pubkey = gNetwork._key.PublicKeyString();
size_t sigsize;
char* signature;
gNetwork._key.Sign(gNetwork._challenge.data(), gNetwork._challenge.size(), &signature, &sigsize);
std::vector<uint8_t> signature;
gNetwork._key.Sign(gNetwork._challenge.data(), gNetwork._challenge.size(), signature);
// Don't keep private key in memory. There's no need and it may get leaked
// when process dump gets collected at some point in future.
gNetwork._key.Unload();
gNetwork.Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature, sigsize);
delete[] signature;
gNetwork.Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature);
}
void network_set_password(const char* password)

View File

@@ -194,32 +194,27 @@ std::string NetworkKey::PublicKeyHash()
return nullptr;
}
bool NetworkKey::Sign(const uint8_t* md, const size_t len, char** signature, size_t* out_size)
bool NetworkKey::Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature)
{
try
{
auto rsa = Crypt::CreateRSA();
auto sig = rsa->SignData(*_key, md, len);
*out_size = sig.size();
*signature = new char[sig.size()];
std::memcpy(*signature, sig.data(), sig.size());
signature = rsa->SignData(*_key, md, len);
return true;
}
catch (const std::exception& e)
{
log_error("NetworkKey::Sign failed: %s", e.what());
*signature = nullptr;
*out_size = 0;
return false;
}
}
bool NetworkKey::Verify(const uint8_t* md, const size_t len, const char* sig, const size_t siglen)
bool NetworkKey::Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature)
{
try
{
auto rsa = Crypt::CreateRSA();
return rsa->VerifyData(*_key, md, len, sig, siglen);
return rsa->VerifyData(*_key, md, len, signature.data(), signature.size());
}
catch (const std::exception& e)
{

View File

@@ -16,6 +16,7 @@
# include <memory>
# include <string>
# include <vector>
interface IStream;
@@ -37,8 +38,8 @@ public:
std::string PublicKeyString();
std::string PublicKeyHash();
void Unload();
bool Sign(const uint8_t* md, const size_t len, char** signature, size_t* out_size);
bool Verify(const uint8_t* md, const size_t len, const char* sig, const size_t siglen);
bool Sign(const uint8_t* md, const size_t len, std::vector<uint8_t>& signature);
bool Verify(const uint8_t* md, const size_t len, const std::vector<uint8_t>& signature);
private:
NetworkKey(const NetworkKey&) = delete;