Saveload: Remove use of randombytes in company passwords storage

Use RandomBytesWithFallback
Replace related key/data arrays with std::array
This commit is contained in:
Jonathan G Rennison
2024-02-06 19:17:57 +00:00
parent 9492aa1c0d
commit f966153ae2
4 changed files with 32 additions and 37 deletions

View File

@@ -71,8 +71,8 @@ bool _is_network_server; ///< Does this client wa
bool _network_settings_access; ///< Can this client change server settings? bool _network_settings_access; ///< Can this client change server settings?
NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies. NetworkCompanyState *_network_company_states = nullptr; ///< Statistics about some companies.
std::string _network_company_server_id; ///< Server ID string used for company passwords std::string _network_company_server_id; ///< Server ID string used for company passwords
uint8_t _network_company_password_storage_token[16]; ///< Non-secret token for storage of company passwords in savegames std::array<uint8_t, 16> _network_company_password_storage_token; ///< Non-secret token for storage of company passwords in savegames
uint8_t _network_company_password_storage_key[32]; ///< Key for storage of company passwords in savegames std::array<uint8_t, 32> _network_company_password_storage_key; ///< Key for storage of company passwords in savegames
ClientID _network_own_client_id; ///< Our client identifier. ClientID _network_own_client_id; ///< Our client identifier.
ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client. ClientID _redirect_console_to_client; ///< If not invalid, redirect the console output to a client.
uint8_t _network_reconnect; ///< Reconnect timeout uint8_t _network_reconnect; ///< Reconnect timeout

View File

@@ -26,8 +26,8 @@
extern NetworkCompanyState *_network_company_states; extern NetworkCompanyState *_network_company_states;
extern std::string _network_company_server_id; extern std::string _network_company_server_id;
extern uint8_t _network_company_password_storage_token[16]; extern std::array<uint8_t, 16> _network_company_password_storage_token;
extern uint8_t _network_company_password_storage_key[32]; extern std::array<uint8_t, 32> _network_company_password_storage_key;
extern ClientID _network_own_client_id; extern ClientID _network_own_client_id;
extern ClientID _redirect_console_to_client; extern ClientID _redirect_console_to_client;

View File

@@ -1912,16 +1912,16 @@ static bool IsValidHex256BitKeyString(std::string &newval)
static void ParseCompanyPasswordStorageToken(const std::string &value) static void ParseCompanyPasswordStorageToken(const std::string &value)
{ {
extern uint8_t _network_company_password_storage_token[16]; extern std::array<uint8_t, 16> _network_company_password_storage_token;
if (value.size() != 32) return; if (value.size() != 32) return;
DecodeHexText(value.c_str(), _network_company_password_storage_token, 16); DecodeHexText(value.c_str(), _network_company_password_storage_token.data(), _network_company_password_storage_token.size());
} }
static void ParseCompanyPasswordStorageSecret(const std::string &value) static void ParseCompanyPasswordStorageSecret(const std::string &value)
{ {
extern uint8_t _network_company_password_storage_key[32]; extern std::array<uint8_t, 32> _network_company_password_storage_key;
if (value.size() != 64) return; if (value.size() != 64) return;
DecodeHexText(value.c_str(), _network_company_password_storage_key, 32); DecodeHexText(value.c_str(), _network_company_password_storage_key.data(), _network_company_password_storage_key.size());
} }
/** Update the game info, and send it to the clients when we are running as a server. */ /** Update the game info, and send it to the clients when we are running as a server. */

View File

@@ -20,7 +20,6 @@
#include "../network/network.h" #include "../network/network.h"
#include "../network/network_func.h" #include "../network/network_func.h"
#include "../network/network_server.h" #include "../network/network_server.h"
#include "../3rdparty/randombytes/randombytes.h"
#include "../3rdparty/monocypher/monocypher.h" #include "../3rdparty/monocypher/monocypher.h"
#include "saveload.h" #include "saveload.h"
@@ -592,23 +591,23 @@ static void Load_PLYP()
return; return;
} }
uint8_t token[16]; std::array<uint8_t, 16> token;
ReadBuffer::GetCurrent()->CopyBytes(token, 16); ReadBuffer::GetCurrent()->CopyBytes(token.data(), 16);
if (memcmp(token, _network_company_password_storage_token, 16) != 0) { if (token != _network_company_password_storage_token) {
DEBUG(sl, 2, "Skipping encrypted company passwords"); DEBUG(sl, 2, "Skipping encrypted company passwords");
SlSkipBytes(size - 16); SlSkipBytes(size - 16);
return; return;
} }
uint8_t nonce[24]; std::array<uint8_t, 16> mac;
uint8_t mac[16]; std::array<uint8_t, 24> nonce;
ReadBuffer::GetCurrent()->CopyBytes(nonce, 24); ReadBuffer::GetCurrent()->CopyBytes(nonce.data(), 24);
ReadBuffer::GetCurrent()->CopyBytes(mac, 16); ReadBuffer::GetCurrent()->CopyBytes(mac.data(), 16);
std::vector<uint8_t> buffer(size - 16 - 24 - 16); std::vector<uint8_t> buffer(size - 16 - 24 - 16);
ReadBuffer::GetCurrent()->CopyBytes(buffer.data(), buffer.size()); ReadBuffer::GetCurrent()->CopyBytes(buffer.data(), buffer.size());
if (crypto_aead_unlock(buffer.data(), mac, _network_company_password_storage_key, nonce, nullptr, 0, buffer.data(), buffer.size()) == 0) { if (crypto_aead_unlock(buffer.data(), mac.data(), _network_company_password_storage_key.data(), nonce.data(), nullptr, 0, buffer.data(), buffer.size()) == 0) {
SlLoadFromBuffer(buffer.data(), buffer.size(), [invalid_mask]() { SlLoadFromBuffer(buffer.data(), buffer.size(), [invalid_mask]() {
_network_company_server_id.resize(SlReadUint32()); _network_company_server_id.resize(SlReadUint32());
ReadBuffer::GetCurrent()->CopyBytes((uint8_t *)_network_company_server_id.data(), _network_company_server_id.size()); ReadBuffer::GetCurrent()->CopyBytes((uint8_t *)_network_company_server_id.data(), _network_company_server_id.size());
@@ -652,13 +651,6 @@ static void Save_PLYP()
return; return;
} }
uint8_t nonce[24]; /* Use only once per key: random */
if (randombytes(nonce, 24) < 0) {
/* Can't get a random nonce, just give up */
SlSetLength(0);
return;
}
std::vector<byte> buffer = SlSaveToVector([]() { std::vector<byte> buffer = SlSaveToVector([]() {
SlWriteUint32((uint32_t)_network_company_server_id.size()); SlWriteUint32((uint32_t)_network_company_server_id.size());
MemoryDumper::GetCurrent()->CopyBytes((const uint8_t *)_network_company_server_id.data(), _network_company_server_id.size()); MemoryDumper::GetCurrent()->CopyBytes((const uint8_t *)_network_company_server_id.data(), _network_company_server_id.size());
@@ -674,27 +666,30 @@ static void Save_PLYP()
SlWriteUint16(0xFFFF); SlWriteUint16(0xFFFF);
/* Add some random length padding to not make it too obvious from the length whether passwords are set or not */ /* Add some random length padding to not make it too obvious from the length whether passwords are set or not */
uint8_t padding[256]; std::array<uint8_t, 256> padding;
if (randombytes(padding, 256) >= 0) { RandomBytesWithFallback(padding);
SlWriteByte(padding[0]); SlWriteByte(padding[0]);
MemoryDumper::GetCurrent()->CopyBytes(padding + 1, padding[0]); MemoryDumper::GetCurrent()->CopyBytes(padding.data() + 1, padding[0]);
} else {
SlWriteByte(0);
}
}); });
uint8_t mac[16]; /* Message authentication code */ /* Message authentication code */
std::array<uint8_t, 16> mac;
/* Use only once per key: random */
std::array<uint8_t, 24> nonce;
RandomBytesWithFallback(nonce);
/* Encrypt in place */ /* Encrypt in place */
crypto_aead_lock(buffer.data(), mac, _network_company_password_storage_key, nonce, nullptr, 0, buffer.data(), buffer.size()); crypto_aead_lock(buffer.data(), mac.data(), _network_company_password_storage_key.data(), nonce.data(), nullptr, 0, buffer.data(), buffer.size());
SlSetLength(2 + 16 + 24 + 16 + buffer.size()); SlSetLength(2 + 16 + 24 + 16 + buffer.size());
SlWriteUint16(0); // Invalid mask SlWriteUint16(0); // Invalid mask
MemoryDumper::GetCurrent()->CopyBytes(_network_company_password_storage_token, 16); static_assert(_network_company_password_storage_token.size() == 16);
MemoryDumper::GetCurrent()->CopyBytes(nonce, 24); MemoryDumper::GetCurrent()->CopyBytes(_network_company_password_storage_token.data(), 16);
MemoryDumper::GetCurrent()->CopyBytes(mac, 16); MemoryDumper::GetCurrent()->CopyBytes(nonce);
MemoryDumper::GetCurrent()->CopyBytes(buffer.data(), buffer.size()); MemoryDumper::GetCurrent()->CopyBytes(mac);
MemoryDumper::GetCurrent()->CopyBytes(buffer);
} }
static const ChunkHandler company_chunk_handlers[] = { static const ChunkHandler company_chunk_handlers[] = {