mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-27 11:17:49 +02:00
Merge remote-tracking branch 'purple/openssl' into fix-ntcp-threading-race
This commit is contained in:
commit
ff5c26adf2
25 changed files with 501 additions and 85 deletions
|
@ -373,7 +373,7 @@ namespace crypto
|
|||
}
|
||||
|
||||
// ECIES
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
BN_CTX_start (ctx);
|
||||
BIGNUM * q = BN_CTX_get (ctx);
|
||||
|
@ -386,10 +386,19 @@ 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);
|
||||
encrypted[0] = 0;
|
||||
bn2buf (x, encrypted + 1, len);
|
||||
bn2buf (y, encrypted + 1 + len, len);
|
||||
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
|
||||
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);
|
||||
}
|
||||
// ecryption key and iv
|
||||
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
|
||||
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
||||
|
@ -403,16 +412,21 @@ namespace crypto
|
|||
memcpy (m+33, data, 222);
|
||||
SHA256 (m+33, 222, m+1);
|
||||
// encrypt
|
||||
encrypted[257] = 0;
|
||||
CBCEncryption encryption;
|
||||
encryption.SetKey (shared);
|
||||
encryption.SetIV (iv);
|
||||
encryption.Encrypt (m, 256, encrypted + 258);
|
||||
if (zeroPadding)
|
||||
{
|
||||
encrypted[257] = 0;
|
||||
encryption.Encrypt (m, 256, encrypted + 258);
|
||||
}
|
||||
else
|
||||
encryption.Encrypt (m, 256, encrypted + 256);
|
||||
EC_POINT_free (p);
|
||||
BN_CTX_end (ctx);
|
||||
}
|
||||
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
bool ret = true;
|
||||
BN_CTX_start (ctx);
|
||||
|
@ -421,8 +435,16 @@ namespace crypto
|
|||
int len = BN_num_bytes (q);
|
||||
// point for shared secret
|
||||
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
||||
BN_bin2bn (encrypted + 1, len, x);
|
||||
BN_bin2bn (encrypted + 1 + len, len, y);
|
||||
if (zeroPadding)
|
||||
{
|
||||
BN_bin2bn (encrypted + 1, len, x);
|
||||
BN_bin2bn (encrypted + 1 + len, len, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
BN_bin2bn (encrypted, len, x);
|
||||
BN_bin2bn (encrypted + len, len, y);
|
||||
}
|
||||
auto p = EC_POINT_new (curve);
|
||||
if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr))
|
||||
{
|
||||
|
@ -439,7 +461,10 @@ namespace crypto
|
|||
CBCDecryption decryption;
|
||||
decryption.SetKey (shared);
|
||||
decryption.SetIV (iv);
|
||||
decryption.Decrypt (encrypted + 258, 256, m);
|
||||
if (zeroPadding)
|
||||
decryption.Decrypt (encrypted + 258, 256, m);
|
||||
else
|
||||
decryption.Decrypt (encrypted + 256, 256, m);
|
||||
// verify and copy
|
||||
uint8_t hash[32];
|
||||
SHA256 (m + 33, 222, hash);
|
||||
|
|
|
@ -54,8 +54,8 @@ namespace crypto
|
|||
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, BN_CTX * ctx); // 222 bytes data, 514 bytes encrypted
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false); // 222 bytes data, 514 bytes encrypted with zeropadding, 512 without
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
||||
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
|
||||
|
||||
// HMAC
|
||||
|
|
|
@ -12,9 +12,9 @@ namespace crypto
|
|||
memcpy (m_PublicKey, pub, 256);
|
||||
}
|
||||
|
||||
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, true);
|
||||
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ElGamalDecryptor::ElGamalDecryptor (const uint8_t * priv)
|
||||
|
@ -22,9 +22,9 @@ namespace crypto
|
|||
memcpy (m_PrivateKey, priv, 256);
|
||||
}
|
||||
|
||||
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, true);
|
||||
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ECIESP256Encryptor::ECIESP256Encryptor (const uint8_t * pub)
|
||||
|
@ -44,10 +44,10 @@ namespace crypto
|
|||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||
}
|
||||
|
||||
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_Curve && m_PublicKey)
|
||||
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx);
|
||||
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ECIESP256Decryptor::ECIESP256Decryptor (const uint8_t * priv)
|
||||
|
@ -62,10 +62,10 @@ namespace crypto
|
|||
if (m_PrivateKey) BN_free (m_PrivateKey);
|
||||
}
|
||||
|
||||
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_Curve && m_PrivateKey)
|
||||
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx);
|
||||
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -104,10 +104,10 @@ namespace crypto
|
|||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||
}
|
||||
|
||||
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_PublicKey)
|
||||
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx);
|
||||
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv)
|
||||
|
@ -120,10 +120,10 @@ namespace crypto
|
|||
if (m_PrivateKey) BN_free (m_PrivateKey);
|
||||
}
|
||||
|
||||
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_PrivateKey)
|
||||
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx);
|
||||
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
virtual ~CryptoKeyEncryptor () {};
|
||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) = 0; // 222 bytes data, 512 bytes encrypted
|
||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding) = 0; // 222 bytes data, 512/514 bytes encrypted
|
||||
};
|
||||
|
||||
class CryptoKeyDecryptor
|
||||
|
@ -21,7 +21,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
virtual ~CryptoKeyDecryptor () {};
|
||||
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) = 0; // 512 bytes encrypted, 222 bytes data
|
||||
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding) = 0; // 512/514 bytes encrypted, 222 bytes data
|
||||
};
|
||||
|
||||
// ElGamal
|
||||
|
@ -30,7 +30,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
ElGamalEncryptor (const uint8_t * pub);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
ElGamalDecryptor (const uint8_t * priv);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace crypto
|
|||
|
||||
ECIESP256Encryptor (const uint8_t * pub);
|
||||
~ECIESP256Encryptor ();
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -72,7 +72,7 @@ namespace crypto
|
|||
|
||||
ECIESP256Decryptor (const uint8_t * priv);
|
||||
~ECIESP256Decryptor ();
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -90,7 +90,7 @@ namespace crypto
|
|||
|
||||
ECIESGOSTR3410Encryptor (const uint8_t * pub);
|
||||
~ECIESGOSTR3410Encryptor ();
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -104,7 +104,7 @@ namespace crypto
|
|||
|
||||
ECIESGOSTR3410Decryptor (const uint8_t * priv);
|
||||
~ECIESGOSTR3410Decryptor ();
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -169,6 +169,46 @@ namespace client
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
|
||||
{
|
||||
|
||||
auto itr = params.find("i2cp.dontPublishLeaseSet");
|
||||
if (itr != params.end())
|
||||
{
|
||||
m_IsPublic = itr->second != "true";
|
||||
}
|
||||
|
||||
int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency;
|
||||
std::map<std::string, int&> intOpts = {
|
||||
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
|
||||
{I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen},
|
||||
{I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQuant},
|
||||
{I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, outQuant},
|
||||
{I2CP_PARAM_TAGS_TO_SEND, numTags},
|
||||
{I2CP_PARAM_MIN_TUNNEL_LATENCY, minLatency},
|
||||
{I2CP_PARAM_MAX_TUNNEL_LATENCY, maxLatency}
|
||||
};
|
||||
|
||||
auto pool = GetTunnelPool();
|
||||
inLen = pool->GetNumInboundHops();
|
||||
outLen = pool->GetNumOutboundHops();
|
||||
inQuant = pool->GetNumInboundTunnels();
|
||||
outQuant = pool->GetNumOutboundTunnels();
|
||||
minLatency = 0;
|
||||
maxLatency = 0;
|
||||
|
||||
for (auto & opt : intOpts)
|
||||
{
|
||||
itr = params.find(opt.first);
|
||||
if(itr != params.end())
|
||||
{
|
||||
opt.second = std::stoi(itr->second);
|
||||
}
|
||||
}
|
||||
pool->RequireLatency(minLatency, maxLatency);
|
||||
return pool->Reconfigure(inLen, outLen, inQuant, outQuant);
|
||||
}
|
||||
|
||||
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
||||
{
|
||||
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
|
||||
|
@ -241,8 +281,12 @@ namespace client
|
|||
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
||||
if (m_IsPublic)
|
||||
{
|
||||
m_PublishVerificationTimer.cancel ();
|
||||
Publish ();
|
||||
auto s = shared_from_this ();
|
||||
m_Service.post ([s](void)
|
||||
{
|
||||
s->m_PublishVerificationTimer.cancel ();
|
||||
s->Publish ();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -984,7 +1028,7 @@ namespace client
|
|||
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||
{
|
||||
if (m_Decryptor)
|
||||
return m_Decryptor->Decrypt (encrypted, data, ctx);
|
||||
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
||||
else
|
||||
LogPrint (eLogError, "Destinations: decryptor is not set");
|
||||
return false;
|
||||
|
|
|
@ -96,6 +96,10 @@ namespace client
|
|||
|
||||
virtual bool Start ();
|
||||
virtual bool Stop ();
|
||||
|
||||
/** i2cp reconfigure */
|
||||
virtual bool Reconfigure(std::map<std::string, std::string> i2cpOpts);
|
||||
|
||||
bool IsRunning () const { return m_IsRunning; };
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
||||
|
|
|
@ -327,7 +327,7 @@ namespace i2p
|
|||
{
|
||||
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
|
||||
BN_CTX * ctx = BN_CTX_new ();
|
||||
i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKeys ().GetPrivateKey () , record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
|
||||
i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
|
||||
BN_CTX_free (ctx);
|
||||
// replace record to reply
|
||||
if (i2p::context.AcceptsTunnels () &&
|
||||
|
|
|
@ -212,7 +212,7 @@ namespace data
|
|||
{
|
||||
auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (data, encrypted, ctx);
|
||||
encryptor->Encrypt (data, encrypted, ctx, true);
|
||||
}
|
||||
|
||||
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace transport
|
|||
}
|
||||
// TODO: check for number of pending keys
|
||||
auto work = new NTCPWork{shared_from_this()};
|
||||
m_Server.Work(work->session, [work]() -> std::function<void(void)> {
|
||||
m_Server.Work(work->session, [work, this]() -> std::function<void(void)> {
|
||||
if (!work->session->m_DHKeysPair)
|
||||
work->session->m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||
work->session->CreateAESKey (work->session->m_Establisher->phase1.pubKey);
|
||||
|
@ -250,7 +250,7 @@ namespace transport
|
|||
else
|
||||
{
|
||||
auto work = new NTCPWork{shared_from_this()};
|
||||
m_Server.Work(work->session, [work]() -> std::function<void(void)> {
|
||||
m_Server.Work(work->session, [work, this]() -> std::function<void(void)> {
|
||||
work->session->CreateAESKey (work->session->m_Establisher->phase2.pubKey);
|
||||
return std::bind(&NTCPSession::HandlePhase2, work->session, work);
|
||||
});
|
||||
|
|
|
@ -34,11 +34,7 @@ namespace i2p
|
|||
|
||||
void RouterContext::CreateNewRouter ()
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
|
||||
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519);
|
||||
#else
|
||||
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_DSA_SHA1);
|
||||
#endif
|
||||
SaveKeys ();
|
||||
NewRouterInfo ();
|
||||
}
|
||||
|
@ -482,6 +478,11 @@ namespace i2p
|
|||
|
||||
bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||
{
|
||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx) : false;
|
||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, true) : false;
|
||||
}
|
||||
|
||||
bool RouterContext::DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||
{
|
||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, false) : false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace i2p
|
|||
void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; };
|
||||
int GetNetID () const { return m_NetID; };
|
||||
void SetNetID (int netID) { m_NetID = netID; };
|
||||
bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
|
||||
|
||||
void UpdatePort (int port); // called from Daemon
|
||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||
|
|
|
@ -840,7 +840,7 @@ namespace data
|
|||
{
|
||||
auto encryptor = m_RouterIdentity->CreateEncryptor (nullptr);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (data, encrypted, ctx);
|
||||
encryptor->Encrypt (data, encrypted, ctx, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -670,10 +670,13 @@ namespace tunnel
|
|||
{
|
||||
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
auto pool = tunnel->GetTunnelPool ();
|
||||
if (pool)
|
||||
// let it die if the tunnel pool has been reconfigured and this is old
|
||||
if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops())
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
pool->RecreateOutboundTunnel (tunnel);
|
||||
}
|
||||
}
|
||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
tunnel->SetState (eTunnelStateExpiring);
|
||||
|
@ -721,10 +724,13 @@ namespace tunnel
|
|||
{
|
||||
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
auto pool = tunnel->GetTunnelPool ();
|
||||
if (pool)
|
||||
// let it die if the tunnel pool was reconfigured and has different number of hops
|
||||
if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
pool->RecreateInboundTunnel (tunnel);
|
||||
}
|
||||
}
|
||||
|
||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
|
|
|
@ -105,6 +105,7 @@ namespace tunnel
|
|||
bool IsFailed () const { return m_State == eTunnelStateFailed; };
|
||||
bool IsRecreated () const { return m_IsRecreated; };
|
||||
void SetIsRecreated () { m_IsRecreated = true; };
|
||||
int GetNumHops () const { return m_Hops.size (); };
|
||||
virtual bool IsInbound() const = 0;
|
||||
|
||||
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "Crypto.h"
|
||||
#include "Identity.h"
|
||||
#include "RouterContext.h"
|
||||
#include "Timestamp.h"
|
||||
|
@ -35,6 +34,7 @@ namespace tunnel
|
|||
RAND_bytes (replyKey, 32);
|
||||
RAND_bytes (replyIV, 16);
|
||||
RAND_bytes ((uint8_t *)&tunnelID, 4);
|
||||
if (!tunnelID) tunnelID = 1; // tunnelID can't be zero
|
||||
isGateway = true;
|
||||
isEndpoint = true;
|
||||
ident = r;
|
||||
|
@ -50,6 +50,7 @@ namespace tunnel
|
|||
nextIdent = ident;
|
||||
isEndpoint = false;
|
||||
RAND_bytes ((uint8_t *)&nextTunnelID, 4);
|
||||
if (!nextTunnelID) nextTunnelID = 1; // tunnelID can't be zero
|
||||
}
|
||||
|
||||
void SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent)
|
||||
|
@ -101,7 +102,9 @@ namespace tunnel
|
|||
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);
|
||||
i2p::crypto::ElGamalEncrypt (ident->GetEncryptionPublicKey (), clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx);
|
||||
auto encryptor = ident->CreateEncryptor (nullptr);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx, false);
|
||||
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -69,6 +69,18 @@ namespace tunnel
|
|||
m_Tests.clear ();
|
||||
}
|
||||
|
||||
bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) {
|
||||
if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0)
|
||||
{
|
||||
m_NumInboundHops = inHops;
|
||||
m_NumOutboundHops = outHops;
|
||||
m_NumInboundTunnels = inQuant;
|
||||
m_NumOutboundTunnels = outQuant;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TunnelPool::TunnelCreated (std::shared_ptr<InboundTunnel> createdTunnel)
|
||||
{
|
||||
if (!m_IsActive) return;
|
||||
|
@ -479,11 +491,17 @@ namespace tunnel
|
|||
outboundTunnel = tunnels.GetNextOutboundTunnel ();
|
||||
LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel...");
|
||||
std::shared_ptr<TunnelConfig> config;
|
||||
if (m_NumInboundHops > 0) config = std::make_shared<TunnelConfig>(tunnel->GetPeers ());
|
||||
auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel);
|
||||
newTunnel->SetTunnelPool (shared_from_this());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
if (m_NumInboundHops > 0 && tunnel->GetPeers().size())
|
||||
{
|
||||
config = std::make_shared<TunnelConfig>(tunnel->GetPeers ());
|
||||
}
|
||||
if (m_NumInboundHops == 0 || config)
|
||||
{
|
||||
auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel);
|
||||
newTunnel->SetTunnelPool (shared_from_this());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelPool::CreateOutboundTunnel ()
|
||||
|
@ -521,12 +539,17 @@ namespace tunnel
|
|||
{
|
||||
LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel...");
|
||||
std::shared_ptr<TunnelConfig> config;
|
||||
if (m_NumOutboundHops > 0)
|
||||
if (m_NumOutboundHops > 0 && tunnel->GetPeers().size())
|
||||
{
|
||||
config = std::make_shared<TunnelConfig>(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
|
||||
auto newTunnel = tunnels.CreateOutboundTunnel (config);
|
||||
newTunnel->SetTunnelPool (shared_from_this ());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
}
|
||||
if(m_NumOutboundHops == 0 || config)
|
||||
{
|
||||
auto newTunnel = tunnels.CreateOutboundTunnel (config);
|
||||
newTunnel->SetTunnelPool (shared_from_this ());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found");
|
||||
|
|
|
@ -78,7 +78,12 @@ namespace tunnel
|
|||
|
||||
int GetNumInboundTunnels () const { return m_NumInboundTunnels; };
|
||||
int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; };
|
||||
int GetNumInboundHops() const { return m_NumInboundHops; };
|
||||
int GetNumOutboundHops() const { return m_NumOutboundHops; };
|
||||
|
||||
/** i2cp reconfigure */
|
||||
bool Reconfigure(int inboundHops, int outboundHops, int inboundQuant, int outboundQuant);
|
||||
|
||||
void SetCustomPeerSelector(ITunnelPeerSelector * selector);
|
||||
void UnsetCustomPeerSelector();
|
||||
bool HasCustomPeerSelector();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue