8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 09:20:39 +01:00

Postfix for #7065: Connection hangs after delivery of 256 Gb; reworked according to java requirements

This commit is contained in:
AlexPeshkoff 2021-12-13 20:05:11 +03:00
parent 98e1f406ca
commit c7f10bf221
5 changed files with 93 additions and 94 deletions

View File

@ -514,14 +514,14 @@
#TracePlugin = fbtrace
# Wire crypt plugins are used to crypt data transferred over the wire.
# In default case wire is encrypted using ChaCha#20 or Alleged RC4.
# Key must be generated by auth plugin.
# In default case wire is encrypted using ChaCha#20 (32/64 bit counter variants)
# or Alleged RC4. Key must be generated by auth plugin.
# For chacha we are using 16 or 32 bytes key (depends upon what is provided
# by auth plugin), 12 bytes nonce and 4 bytes counter, 20 (10 + 10) rounds are made.
# by auth plugin), 12 (8) bytes nonce and 4 (8) bytes counter, 20 (10 + 10) rounds are made.
#
# Per-connection configurable.
#
#WireCryptPlugin = ChaCha, Arc4
#WireCryptPlugin = ChaCha64, ChaCha, Arc4
# Key holder is a kind of temp storage for DB crypt keys.
# There is no default for this kind of plugins.

View File

@ -6,3 +6,7 @@ Plugin = UDR {
Config = UDR_config {
path = $(dir_plugins)/udr
}
Plugin = ChaCha64 {
Module = $(dir_plugins)/ChaCha
}

View File

@ -275,7 +275,7 @@ constexpr ConfigEntry entries[MAX_CONFIG_KEY] =
{TYPE_STRING, "SecurityDatabase", false, nullptr}, // sec/db alias - rely on ConfigManager::getDefaultSecurityDb(
{TYPE_STRING, "ServerMode", true, nullptr}, // actual value differs in boot/regular cases and set at setupDefaultConfig(
{TYPE_STRING, "WireCrypt", false, nullptr},
{TYPE_STRING, "WireCryptPlugin", false, "ChaCha, Arc4"},
{TYPE_STRING, "WireCryptPlugin", false, "ChaCha64, ChaCha, Arc4"},
{TYPE_STRING, "KeyHolderPlugin", false, ""},
{TYPE_BOOLEAN, "RemoteAccess", false, true},
{TYPE_BOOLEAN, "IPv6V6Only", false, false},

View File

@ -31,6 +31,8 @@
#include <tomcrypt.h>
#include <../common/os/guid.h>
#include "../remote/remot_proto.h"
using namespace Firebird;
namespace
@ -84,105 +86,94 @@ private:
};
class ChaCha FB_FINAL : public StdPlugin<IWireCryptPluginImpl<ChaCha, CheckStatusWrapper> >
template <unsigned IV_SIZE>
class ChaCha FB_FINAL : public StdPlugin<IWireCryptPluginImpl<ChaCha<IV_SIZE>, CheckStatusWrapper> >
{
public:
explicit ChaCha(IPluginConfig* cfg)
: en(NULL), de(NULL), iv(getPool()), pluginConfig(cfg)
{ }
explicit ChaCha(IPluginConfig*)
: en(NULL), de(NULL), iv(this->getPool())
{
if (IV_SIZE == 16)
{
GenerateRandomBytes(iv.getBuffer(16), 12);
iv[12] = iv[13] = iv[14] = iv[15] = 0;
}
else
GenerateRandomBytes(iv.getBuffer(8), 8);
}
// ICryptPlugin implementation
const char* getKnownTypes(CheckStatusWrapper* status);
void setKey(CheckStatusWrapper* status, ICryptKey* key);
void encrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to);
void decrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to);
const unsigned char* getSpecificData(CheckStatusWrapper* status, const char* type, unsigned* len);
void setSpecificData(CheckStatusWrapper* status, const char* type, unsigned len, const unsigned char* data);
const char* getKnownTypes(CheckStatusWrapper* status)
{
status->init();
return "Symmetric";
}
void setKey(CheckStatusWrapper* status, ICryptKey* key)
{
status->init();
try
{
unsigned int l;
const void* k = key->getEncryptKey(&l);
en = createCypher(l, k);
k = key->getDecryptKey(&l);
de = createCypher(l, k);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void encrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to)
{
status->init();
en->transform(length, from, to);
}
void decrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to)
{
status->init();
de->transform(length, from, to);
}
const unsigned char* getSpecificData(CheckStatusWrapper* status, const char* type, unsigned* len)
{
*len = IV_SIZE;
WIRECRYPT_DEBUG(fprintf(stderr, "getSpecificData %d\n", *len));
return iv.begin();
}
void setSpecificData(CheckStatusWrapper* status, const char* type, unsigned len, const unsigned char* data)
{
WIRECRYPT_DEBUG(fprintf(stderr, "setSpecificData %d\n", len));
memcpy(iv.getBuffer(len), data, len);
}
private:
Cipher* createCypher(unsigned int l, const void* key);
Cipher* createCypher(unsigned int l, const void* key)
{
if (l < 16)
(Arg::Gds(isc_random) << "Key too short").raise();
hash_state md;
tomCheck(sha256_init(&md), "initializing sha256");
tomCheck(sha256_process(&md, static_cast<const unsigned char*>(key), l), "processing original key in sha256");
unsigned char stretched[32];
tomCheck(sha256_done(&md, stretched), "getting stretched key from sha256");
return FB_NEW Cipher(stretched, iv.getCount(), iv.begin());
}
AutoPtr<Cipher> en, de;
UCharBuffer iv;
RefPtr<IPluginConfig> pluginConfig;
};
void ChaCha::setKey(CheckStatusWrapper* status, ICryptKey* key)
{
status->init();
try
{
unsigned int l;
const void* k = key->getEncryptKey(&l);
en = createCypher(l, k);
k = key->getDecryptKey(&l);
de = createCypher(l, k);
}
catch (const Exception& ex)
{
ex.stuffException(status);
}
}
void ChaCha::encrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to)
{
status->init();
en->transform(length, from, to);
}
void ChaCha::decrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to)
{
status->init();
de->transform(length, from, to);
}
Cipher* ChaCha::createCypher(unsigned int l, const void* key)
{
if (l < 16)
(Arg::Gds(isc_random) << "Key too short").raise();
hash_state md;
tomCheck(sha256_init(&md), "initializing sha256");
tomCheck(sha256_process(&md, static_cast<const unsigned char*>(key), l), "processing original key in sha256");
unsigned char stretched[32];
tomCheck(sha256_done(&md, stretched), "getting stretched key from sha256");
return FB_NEW Cipher(stretched, iv.getCount(), iv.begin());
}
const char* ChaCha::getKnownTypes(CheckStatusWrapper* status)
{
status->init();
return "Symmetric";
}
const unsigned char* ChaCha::getSpecificData(CheckStatusWrapper* status, const char*, unsigned* len)
{
RefPtr<IConfig> config(pluginConfig->getDefaultConfig(status));
check(status);
RefPtr<IConfigEntry> entry(config->find(status, "CounterSize"));
check(status);
if (entry.hasData())
*len = entry->getIntValue() == 64 ? 8 : 16;
else
*len = 16;
if (*len == 16)
{
GenerateRandomBytes(iv.getBuffer(16), 12);
iv[12] = iv[13] = iv[14] = iv[15] = 0;
}
else
GenerateRandomBytes(iv.getBuffer(8), 8);
return iv.begin();
}
void ChaCha::setSpecificData(CheckStatusWrapper* status, const char*, unsigned len, const unsigned char* data)
{
memcpy(iv.getBuffer(len), data, len);
}
SimpleFactory<ChaCha> factory;
SimpleFactory<ChaCha<16> > factory;
SimpleFactory<ChaCha<8> > factory64;
} // anonymous namespace
@ -190,5 +181,6 @@ extern "C" void FB_EXPORTED FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
{
CachedMasterInterface::set(master);
PluginManagerInterfacePtr()->registerPluginFactory(IPluginManager::TYPE_WIRE_CRYPT, "ChaCha", &factory);
PluginManagerInterfacePtr()->registerPluginFactory(IPluginManager::TYPE_WIRE_CRYPT, "ChaCha64", &factory64);
getUnloadDetector()->registerMe();
}

View File

@ -1215,12 +1215,15 @@ bool rem_port::tryKeyType(const KnownServerKey& srvKey, InternalCryptKey* cryptK
for (unsigned n = 0; n < clientPlugins.getCount(); ++n)
{
Firebird::PathName p(clientPlugins[n]);
WIRECRYPT_DEBUG(fprintf(stderr, "tryKeyType, client plugin %s\n", p.c_str()));
if (srvKey.plugins.find(" " + p + " ") != Firebird::PathName::npos)
{
WIRECRYPT_DEBUG(fprintf(stderr, "tryKeyType, server listed plugin %s\n", p.c_str()));
Firebird::GetPlugins<Firebird::IWireCryptPlugin>
cp(Firebird::IPluginManager::TYPE_WIRE_CRYPT, p.c_str());
if (cp.hasData())
{
WIRECRYPT_DEBUG(fprintf(stderr, "tryKeyType, client loaded plugin %s\n", p.c_str()));
Firebird::LocalStatus st;
Firebird::CheckStatusWrapper statusWrapper(&st);