mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-09 15:50:26 +03:00
don't select ElGamal routers for tunnels
This commit is contained in:
parent
bb518d3d51
commit
349022ae42
@ -398,7 +398,7 @@ namespace crypto
|
||||
}
|
||||
|
||||
// ElGamal
|
||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, bool zeroPadding)
|
||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted)
|
||||
{
|
||||
BN_CTX * ctx = BN_CTX_new ();
|
||||
BN_CTX_start (ctx);
|
||||
@ -436,18 +436,11 @@ namespace crypto
|
||||
BN_bin2bn (m, 255, b);
|
||||
BN_mod_mul (b, b1, b, elgp, ctx);
|
||||
// copy a and b
|
||||
if (zeroPadding)
|
||||
{
|
||||
encrypted[0] = 0;
|
||||
bn2buf (a, encrypted + 1, 256);
|
||||
encrypted[257] = 0;
|
||||
bn2buf (b, encrypted + 258, 256);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn2buf (a, encrypted, 256);
|
||||
bn2buf (b, encrypted + 256, 256);
|
||||
}
|
||||
encrypted[0] = 0;
|
||||
bn2buf (a, encrypted + 1, 256);
|
||||
encrypted[257] = 0;
|
||||
bn2buf (b, encrypted + 258, 256);
|
||||
|
||||
BN_free (a);
|
||||
BN_CTX_end (ctx);
|
||||
BN_CTX_free (ctx);
|
||||
@ -502,7 +495,7 @@ namespace crypto
|
||||
}
|
||||
|
||||
// ECIES
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, bool zeroPadding)
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted)
|
||||
{
|
||||
BN_CTX * ctx = BN_CTX_new ();
|
||||
BN_CTX_start (ctx);
|
||||
@ -516,19 +509,10 @@ namespace crypto
|
||||
EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
|
||||
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
||||
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
||||
if (zeroPadding)
|
||||
{
|
||||
encrypted[0] = 0;
|
||||
bn2buf (x, encrypted + 1, len);
|
||||
bn2buf (y, encrypted + 1 + len, len);
|
||||
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn2buf (x, encrypted, len);
|
||||
bn2buf (y, encrypted + len, len);
|
||||
RAND_bytes (encrypted + 2*len, 256 - 2*len);
|
||||
}
|
||||
encrypted[0] = 0;
|
||||
bn2buf (x, encrypted + 1, len);
|
||||
bn2buf (y, encrypted + 1 + len, len);
|
||||
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
|
||||
// encryption key and iv
|
||||
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
|
||||
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
||||
@ -545,13 +529,8 @@ namespace crypto
|
||||
CBCEncryption encryption;
|
||||
encryption.SetKey (shared);
|
||||
encryption.SetIV (iv);
|
||||
if (zeroPadding)
|
||||
{
|
||||
encrypted[257] = 0;
|
||||
encryption.Encrypt (m, 256, encrypted + 258);
|
||||
}
|
||||
else
|
||||
encryption.Encrypt (m, 256, encrypted + 256);
|
||||
encrypted[257] = 0;
|
||||
encryption.Encrypt (m, 256, encrypted + 258);
|
||||
EC_POINT_free (p);
|
||||
BN_CTX_end (ctx);
|
||||
BN_CTX_free (ctx);
|
||||
|
@ -108,12 +108,12 @@ namespace crypto
|
||||
};
|
||||
|
||||
// ElGamal
|
||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, bool zeroPadding = false); // 222 bytes data, 514 bytes encrypted with zeropadding, 512 without
|
||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted); // 222 bytes data, 514 bytes encrypted
|
||||
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data); // 514 bytes encrypted, 222 data
|
||||
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub);
|
||||
|
||||
// ECIES
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, bool zeroPadding = false); // 222 bytes data, 514 bytes encrypted with zeropadding, 512 without
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted); // 222 bytes data, 514 bytes encrypted
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data); // 514 bytes encrypted, 222 data
|
||||
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
|
||||
|
||||
|
@ -20,9 +20,9 @@ namespace crypto
|
||||
memcpy (m_PublicKey, pub, 256);
|
||||
}
|
||||
|
||||
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding)
|
||||
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted)
|
||||
{
|
||||
ElGamalEncrypt (m_PublicKey, data, encrypted, zeroPadding);
|
||||
ElGamalEncrypt (m_PublicKey, data, encrypted);
|
||||
}
|
||||
|
||||
ElGamalDecryptor::ElGamalDecryptor (const uint8_t * priv)
|
||||
@ -52,10 +52,10 @@ namespace crypto
|
||||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||
}
|
||||
|
||||
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding)
|
||||
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted)
|
||||
{
|
||||
if (m_Curve && m_PublicKey)
|
||||
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, zeroPadding);
|
||||
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted);
|
||||
}
|
||||
|
||||
ECIESP256Decryptor::ECIESP256Decryptor (const uint8_t * priv)
|
||||
@ -112,10 +112,10 @@ namespace crypto
|
||||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||
}
|
||||
|
||||
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding)
|
||||
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted)
|
||||
{
|
||||
if (m_PublicKey)
|
||||
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, zeroPadding);
|
||||
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted);
|
||||
}
|
||||
|
||||
ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv)
|
||||
@ -159,7 +159,7 @@ namespace crypto
|
||||
memcpy (m_PublicKey, pub, 32);
|
||||
}
|
||||
|
||||
void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub, bool)
|
||||
void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub)
|
||||
{
|
||||
memcpy (pub, m_PublicKey, 32);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace crypto
|
||||
public:
|
||||
|
||||
virtual ~CryptoKeyEncryptor () {};
|
||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding) = 0;
|
||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted) = 0;
|
||||
};
|
||||
|
||||
class CryptoKeyDecryptor
|
||||
@ -39,7 +39,7 @@ namespace crypto
|
||||
public:
|
||||
|
||||
ElGamalEncryptor (const uint8_t * pub);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding) override; // 222 bytes data, 512/514 bytes encrypted
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted) override; // 222 bytes data, 514 bytes encrypted
|
||||
|
||||
private:
|
||||
|
||||
@ -67,7 +67,7 @@ namespace crypto
|
||||
|
||||
ECIESP256Encryptor (const uint8_t * pub);
|
||||
~ECIESP256Encryptor ();
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding) override;
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted) override;
|
||||
|
||||
private:
|
||||
|
||||
@ -101,7 +101,7 @@ namespace crypto
|
||||
|
||||
ECIESGOSTR3410Encryptor (const uint8_t * pub);
|
||||
~ECIESGOSTR3410Encryptor ();
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding) override;
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted) override;
|
||||
|
||||
private:
|
||||
|
||||
@ -133,7 +133,7 @@ namespace crypto
|
||||
|
||||
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
|
||||
~ECIESX25519AEADRatchetEncryptor () {};
|
||||
void Encrypt (const uint8_t *, uint8_t * pub, bool) override;
|
||||
void Encrypt (const uint8_t *, uint8_t * pub) override;
|
||||
// copies m_PublicKey to pub
|
||||
|
||||
private:
|
||||
|
@ -259,7 +259,7 @@ namespace data
|
||||
if (!m_EncryptionKey) return;
|
||||
auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (data, encrypted, true);
|
||||
encryptor->Encrypt (data, encrypted);
|
||||
}
|
||||
|
||||
void LeaseSet::SetBuffer (const uint8_t * buf, size_t len)
|
||||
@ -662,7 +662,7 @@ namespace data
|
||||
{
|
||||
auto encryptor = m_Encryptor; // TODO: atomic
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (data, encrypted, true);
|
||||
encryptor->Encrypt (data, encrypted);
|
||||
}
|
||||
|
||||
uint64_t LeaseSet2::ExtractExpirationTimestamp (const uint8_t * buf, size_t len) const
|
||||
|
@ -1171,7 +1171,8 @@ namespace data
|
||||
{
|
||||
return !router->IsHidden () && router != compatibleWith &&
|
||||
(reverse ? compatibleWith->IsReachableFrom (*router) :
|
||||
router->IsReachableFrom (*compatibleWith));
|
||||
router->IsReachableFrom (*compatibleWith)) &&
|
||||
router->IsECIES ();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1213,11 +1214,8 @@ namespace data
|
||||
(reverse ? compatibleWith->IsReachableFrom (*router) :
|
||||
router->IsReachableFrom (*compatibleWith)) &&
|
||||
(router->GetCaps () & RouterInfo::eHighBandwidth) &&
|
||||
#if defined(__x86_64__)
|
||||
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION;
|
||||
#else
|
||||
router->GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
|
||||
#endif
|
||||
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION &&
|
||||
router->IsECIES ();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1159,7 +1159,7 @@ namespace data
|
||||
{
|
||||
auto encryptor = m_RouterIdentity->CreateEncryptor (nullptr);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (data, encrypted, true);
|
||||
encryptor->Encrypt (data, encrypted);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsEligibleFloodfill () const
|
||||
|
@ -191,6 +191,7 @@ namespace data
|
||||
void UpdateSupportedTransports ();
|
||||
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
||||
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
||||
bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
|
||||
bool IsSSU (bool v4only = true) const;
|
||||
bool IsSSUV6 () const;
|
||||
bool IsNTCP2 (bool v4only = true) const;
|
||||
|
@ -83,48 +83,6 @@ namespace tunnel
|
||||
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record);
|
||||
}
|
||||
|
||||
void ElGamalTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID)
|
||||
{
|
||||
// generate keys
|
||||
RAND_bytes (layerKey, 32);
|
||||
RAND_bytes (ivKey, 32);
|
||||
RAND_bytes (replyKey, 32);
|
||||
RAND_bytes (replyIV, 16);
|
||||
// fill clear text
|
||||
uint8_t flag = 0;
|
||||
if (isGateway) flag |= TUNNEL_BUILD_RECORD_GATEWAY_FLAG;
|
||||
if (isEndpoint) flag |= TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
|
||||
uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];
|
||||
htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID);
|
||||
memcpy (clearText + BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET, ident->GetIdentHash (), 32);
|
||||
htobe32buf (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID);
|
||||
memcpy (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32);
|
||||
memcpy (clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, layerKey, 32);
|
||||
memcpy (clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, ivKey, 32);
|
||||
memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET, replyKey, 32);
|
||||
memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, replyIV, 16);
|
||||
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag;
|
||||
htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ());
|
||||
htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID);
|
||||
RAND_bytes (clearText + BUILD_REQUEST_RECORD_PADDING_OFFSET, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - BUILD_REQUEST_RECORD_PADDING_OFFSET);
|
||||
// encrypt
|
||||
uint8_t * record = records + recordIndex*TUNNEL_BUILD_RECORD_SIZE;
|
||||
auto encryptor = ident->CreateEncryptor (nullptr);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, false);
|
||||
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16);
|
||||
}
|
||||
|
||||
bool ElGamalTunnelHopConfig::DecryptBuildResponseRecord (uint8_t * records) const
|
||||
{
|
||||
uint8_t * record = records + recordIndex*TUNNEL_BUILD_RECORD_SIZE;
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (replyKey);
|
||||
decryption.SetIV (replyIV);
|
||||
decryption.Decrypt (record, TUNNEL_BUILD_RECORD_SIZE, record);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ECIESTunnelHopConfig::EncryptECIES (const uint8_t * plainText, size_t len, uint8_t * encrypted)
|
||||
{
|
||||
if (!ident) return;
|
||||
@ -261,5 +219,32 @@ namespace tunnel
|
||||
memcpy (key, m_CK + 32, 32);
|
||||
return tag;
|
||||
}
|
||||
|
||||
void TunnelConfig::CreatePeers (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers)
|
||||
{
|
||||
TunnelHopConfig * prev = nullptr;
|
||||
for (const auto& it: peers)
|
||||
{
|
||||
TunnelHopConfig * hop = nullptr;
|
||||
if (m_IsShort)
|
||||
hop = new ShortECIESTunnelHopConfig (it);
|
||||
else
|
||||
{
|
||||
if (it->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
||||
hop = new LongECIESTunnelHopConfig (it);
|
||||
else
|
||||
LogPrint (eLogError, "Tunnel: ElGamal router is not supported");
|
||||
}
|
||||
if (hop)
|
||||
{
|
||||
if (prev)
|
||||
prev->SetNext (hop);
|
||||
else
|
||||
m_FirstHop = hop;
|
||||
prev = hop;
|
||||
}
|
||||
}
|
||||
m_LastHop = prev;
|
||||
}
|
||||
}
|
||||
}
|
@ -47,16 +47,6 @@ namespace tunnel
|
||||
virtual uint64_t GetGarlicKey (uint8_t * key) const { return 0; }; // return tag
|
||||
};
|
||||
|
||||
struct ElGamalTunnelHopConfig: public TunnelHopConfig
|
||||
{
|
||||
ElGamalTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r):
|
||||
TunnelHopConfig (r) {};
|
||||
uint8_t GetRetCode (const uint8_t * records) const
|
||||
{ return (records + recordIndex*TUNNEL_BUILD_RECORD_SIZE)[BUILD_RESPONSE_RECORD_RET_OFFSET]; };
|
||||
void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID);
|
||||
bool DecryptBuildResponseRecord (uint8_t * records) const;
|
||||
};
|
||||
|
||||
struct ECIESTunnelHopConfig: public TunnelHopConfig, public i2p::crypto::NoiseSymmetricState
|
||||
{
|
||||
ECIESTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r):
|
||||
@ -194,29 +184,7 @@ namespace tunnel
|
||||
|
||||
private:
|
||||
|
||||
void CreatePeers (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers)
|
||||
{
|
||||
TunnelHopConfig * prev = nullptr;
|
||||
for (const auto& it: peers)
|
||||
{
|
||||
TunnelHopConfig * hop;
|
||||
if (m_IsShort)
|
||||
hop = new ShortECIESTunnelHopConfig (it);
|
||||
else
|
||||
{
|
||||
if (it->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
||||
hop = new LongECIESTunnelHopConfig (it);
|
||||
else
|
||||
hop = new ElGamalTunnelHopConfig (it);
|
||||
}
|
||||
if (prev)
|
||||
prev->SetNext (hop);
|
||||
else
|
||||
m_FirstHop = hop;
|
||||
prev = hop;
|
||||
}
|
||||
m_LastHop = prev;
|
||||
}
|
||||
void CreatePeers (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -453,7 +453,7 @@ namespace tunnel
|
||||
(inbound && i2p::transport::transports.GetNumPeers () > 25))
|
||||
{
|
||||
auto r = i2p::transport::transports.GetRandomPeer ();
|
||||
if (r && !r->GetProfile ()->IsBad () &&
|
||||
if (r && r->IsECIES () && !r->GetProfile ()->IsBad () &&
|
||||
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable
|
||||
{
|
||||
prevHop = r;
|
||||
@ -469,6 +469,7 @@ namespace tunnel
|
||||
{
|
||||
LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected");
|
||||
hop = i2p::transport::transports.GetRandomPeer ();
|
||||
if (!hop->IsECIES ()) hop = nullptr;
|
||||
}
|
||||
if (!hop)
|
||||
{
|
||||
@ -513,7 +514,15 @@ namespace tunnel
|
||||
auto& ident = (*m_ExplicitPeers)[i];
|
||||
auto r = i2p::data::netdb.FindRouter (ident);
|
||||
if (r)
|
||||
path.Add (r);
|
||||
{
|
||||
if (r->IsECIES ())
|
||||
path.Add (r);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "Tunnels: ElGamal router ", ident.ToBase64 (), " is not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogInfo, "Tunnels: Can't find router for ", ident.ToBase64 ());
|
||||
|
Loading…
Reference in New Issue
Block a user