diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 37b0abda..7c067080 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -31,7 +31,7 @@ namespace tunnel { Tunnel::Tunnel (std::shared_ptr config): TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()), - m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr), + m_Config (config), m_Pool (nullptr), m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports), m_IsRecreated (false), m_Latency (UNKNOWN_LATENCY) { @@ -53,7 +53,7 @@ namespace tunnel int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS; auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage (); *msg->GetPayload () = numRecords; - const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; + const size_t recordSize = SHORT_TUNNEL_BUILD_RECORD_SIZE; msg->len += numRecords*recordSize + 1; // shuffle records std::vector recordIndicies; @@ -97,7 +97,7 @@ namespace tunnel // delete phony hop after encryption if (insertPhonyRecord) m_Config->DeletePhonyHop (); - msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild); + msg->FillI2NPMessageHeader (eI2NPShortTunnelBuild); auto s = shared_from_this (); msg->onDrop = [s]() { @@ -108,21 +108,17 @@ namespace tunnel // send message if (outboundTunnel) { - if (m_Config->IsShort ()) + auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr; + if (ident && ident->GetIdentHash () != outboundTunnel->GetEndpointIdentHash ()) // don't encrypt if IBGW = OBEP { - auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr; - if (ident && ident->GetIdentHash () != outboundTunnel->GetEndpointIdentHash ()) // don't encrypt if IBGW = OBEP - { - auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ()); - if (msg1) msg = msg1; - } + auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ()); + if (msg1) msg = msg1; } outboundTunnel->SendTunnelDataMsgTo (GetNextIdentHash (), 0, msg); } else { - if (m_Config->IsShort () && m_Config->GetLastHop () && - m_Config->GetLastHop ()->ident->GetIdentHash () != m_Config->GetLastHop ()->nextIdent) + if (m_Config->GetLastHop () && m_Config->GetLastHop ()->ident->GetIdentHash () != m_Config->GetLastHop ()->nextIdent) { // add garlic key/tag for reply uint8_t key[32]; @@ -212,7 +208,6 @@ namespace tunnel hop = hop->prev; i++; } - m_IsShortBuildMessage = m_Config->IsShort (); m_FarEndTransports = m_Config->GetFarEndTransports (); m_Config = nullptr; } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 0e90c6e0..f2f877ef 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -89,7 +89,6 @@ namespace tunnel std::shared_ptr GetTunnelConfig () const { return m_Config; } std::vector > GetPeers () const; std::vector > GetInvertedPeers () const; - bool IsShortBuildMessage () const { return m_IsShortBuildMessage; }; i2p::data::RouterInfo::CompatibleTransports GetFarEndTransports () const { return m_FarEndTransports; }; TunnelState GetState () const { return m_State; }; void SetState (TunnelState state); @@ -127,7 +126,6 @@ namespace tunnel std::shared_ptr m_Config; std::vector m_Hops; - bool m_IsShortBuildMessage; std::shared_ptr m_Pool; // pool, tunnel belongs to, or null std::atomic m_State; i2p::data::RouterInfo::CompatibleTransports m_FarEndTransports; diff --git a/libi2pd/TunnelConfig.cpp b/libi2pd/TunnelConfig.cpp index fbbfc8de..ace282cc 100644 --- a/libi2pd/TunnelConfig.cpp +++ b/libi2pd/TunnelConfig.cpp @@ -109,50 +109,6 @@ namespace tunnel return i2p::crypto::AEADChaCha20Poly1305 (encrypted, len - 16, m_H, 32, key, nonce, clearText, len - 16, false); // decrypt } - void LongECIESTunnelHopConfig::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[ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; - htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); - htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); - memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32); - memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, layerKey, 32); - memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET, ivKey, 32); - memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET, replyKey, 32); - memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, replyIV, 16); - clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag; - memset (clearText + ECIES_BUILD_REQUEST_RECORD_MORE_FLAGS_OFFSET, 0, 3); // set to 0 for compatibility - htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetMinutesSinceEpoch ()); - htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET, 600); // +10 minutes - htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); - memset (clearText + ECIES_BUILD_REQUEST_RECORD_PADDING_OFFSET, 0, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - ECIES_BUILD_REQUEST_RECORD_PADDING_OFFSET); - // encrypt - uint8_t * record = records + recordIndex*TUNNEL_BUILD_RECORD_SIZE; - EncryptECIES (clearText, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET); - memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); - } - - bool LongECIESTunnelHopConfig::DecryptBuildResponseRecord (uint8_t * records) const - { - uint8_t * record = records + recordIndex*TUNNEL_BUILD_RECORD_SIZE; - uint8_t nonce[12]; - memset (nonce, 0, 12); - if (!DecryptECIES (m_CK, nonce, record, TUNNEL_BUILD_RECORD_SIZE, record)) - { - LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed"); - return false; - } - return true; - } - void ShortECIESTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) { // fill clear text @@ -225,14 +181,6 @@ namespace tunnel return tag; } - void LongPhonyTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) - { - uint8_t * record = records + recordIndex*TUNNEL_BUILD_RECORD_SIZE; - memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetIdentHash (), 16); - memcpy (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, i2p::transport::transports.GetNextX25519KeysPair ()->GetPublicKey (), 32); - RAND_bytes (record + 48, TUNNEL_BUILD_RECORD_SIZE - 48); - } - void ShortPhonyTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) { uint8_t * record = records + recordIndex*SHORT_TUNNEL_BUILD_RECORD_SIZE; @@ -242,8 +190,8 @@ namespace tunnel } TunnelConfig::TunnelConfig (const std::vector >& peers, - bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports): - m_IsShort (isShort), m_FarEndTransports (farEndTransports) + i2p::data::RouterInfo::CompatibleTransports farEndTransports): + m_FarEndTransports (farEndTransports) { // inbound CreatePeers (peers); @@ -251,9 +199,9 @@ namespace tunnel } TunnelConfig::TunnelConfig (const std::vector >& peers, - uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort, + uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, i2p::data::RouterInfo::CompatibleTransports farEndTransports): - m_IsShort (isShort), m_FarEndTransports (farEndTransports) + m_FarEndTransports (farEndTransports) { // outbound CreatePeers (peers); @@ -266,24 +214,12 @@ namespace tunnel TunnelHopConfig * prev = nullptr; for (const auto& it: peers) { - TunnelHopConfig * hop = nullptr; - if (m_IsShort) - hop = new ShortECIESTunnelHopConfig (it); + TunnelHopConfig * hop = new ShortECIESTunnelHopConfig (it); + if (prev) + prev->SetNext (hop); 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_FirstHop = hop; + prev = hop; } m_LastHop = prev; } @@ -292,17 +228,10 @@ namespace tunnel { if (m_LastHop && m_LastHop->ident) { - TunnelHopConfig * hop = nullptr; - if (m_IsShort) - hop = new ShortPhonyTunnelHopConfig (); - else - hop = new LongPhonyTunnelHopConfig (); - if (hop) - { - hop->prev = m_LastHop; - m_LastHop->next = hop; - m_LastHop = hop; - } + TunnelHopConfig * hop = new ShortPhonyTunnelHopConfig (); + hop->prev = m_LastHop; + m_LastHop->next = hop; + m_LastHop = hop; } } diff --git a/libi2pd/TunnelConfig.h b/libi2pd/TunnelConfig.h index a024f359..2ec6c91f 100644 --- a/libi2pd/TunnelConfig.h +++ b/libi2pd/TunnelConfig.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2025, The PurpleI2P Project +* Copyright (c) 2013-2026, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -55,16 +55,6 @@ namespace tunnel bool DecryptECIES (const uint8_t * key, const uint8_t * nonce, const uint8_t * encrypted, size_t len, uint8_t * clearText) const; }; - struct LongECIESTunnelHopConfig: public ECIESTunnelHopConfig - { - LongECIESTunnelHopConfig (std::shared_ptr r): - ECIESTunnelHopConfig (r) {}; - uint8_t GetRetCode (const uint8_t * records) const override - { return (records + recordIndex*TUNNEL_BUILD_RECORD_SIZE)[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET]; }; - void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) override; - bool DecryptBuildResponseRecord (uint8_t * records) const override; - }; - struct ShortECIESTunnelHopConfig: public ECIESTunnelHopConfig { ShortECIESTunnelHopConfig (std::shared_ptr r): @@ -85,27 +75,22 @@ namespace tunnel void DecryptRecord (uint8_t * records, int index) const override {} // do nothing }; - struct LongPhonyTunnelHopConfig: public PhonyTunnelHopConfig - { - void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) override; - }; - struct ShortPhonyTunnelHopConfig: public PhonyTunnelHopConfig { void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) override; }; - + class TunnelConfig { public: TunnelConfig (const std::vector >& peers, - bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // inbound + i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // inbound TunnelConfig (const std::vector >& peers, - uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort, + uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // outbound - + virtual ~TunnelConfig () { TunnelHopConfig * hop = m_FirstHop; @@ -118,8 +103,6 @@ namespace tunnel } } - bool IsShort () const { return m_IsShort; } - i2p::data::RouterInfo::CompatibleTransports GetFarEndTransports () const { return m_FarEndTransports; @@ -188,15 +171,15 @@ namespace tunnel return peers; } - size_t GetRecordSize () const { return m_IsShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; }; + size_t GetRecordSize () const { return SHORT_TUNNEL_BUILD_RECORD_SIZE; }; void CreatePhonyHop (); void DeletePhonyHop (); - + protected: // this constructor can't be called from outside - TunnelConfig (): m_FirstHop (nullptr), m_LastHop (nullptr), m_IsShort (false), + TunnelConfig (): m_FirstHop (nullptr), m_LastHop (nullptr), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports) { } @@ -208,7 +191,6 @@ namespace tunnel private: TunnelHopConfig * m_FirstHop, * m_LastHop; - bool m_IsShort; i2p::data::RouterInfo::CompatibleTransports m_FarEndTransports; }; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index d86fe604..2d562823 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -27,12 +27,7 @@ namespace tunnel void Path::Add (std::shared_ptr r) { if (r) - { peers.push_back (r->GetRouterIdentity ()); - if (r->GetVersion () < i2p::data::NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION || - r->GetRouterIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - isShort = false; - } } void Path::Reverse () @@ -751,7 +746,7 @@ namespace tunnel if (m_NumInboundHops > 0) { path.Reverse (); - config = std::make_shared (path.peers, path.isShort, path.farEndTransports); + config = std::make_shared (path.peers, path.farEndTransports); } auto tunnel = tunnels.CreateInboundTunnel (config, shared_from_this (), outboundTunnel); if (tunnel->IsEstablished ()) // zero hops @@ -777,8 +772,7 @@ namespace tunnel { auto peers = tunnel->GetPeers(); if (peers.size ()&& ValidatePeers (peers)) - config = std::make_shared(tunnel->GetPeers (), - tunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + config = std::make_shared(tunnel->GetPeers (), tunnel->GetFarEndTransports ()); } if (!m_NumInboundHops || config) { @@ -811,19 +805,17 @@ namespace tunnel std::shared_ptr config; if (m_NumOutboundHops > 0) config = std::make_shared(path.peers, inboundTunnel->GetNextTunnelID (), - inboundTunnel->GetNextIdentHash (), path.isShort, path.farEndTransports); + inboundTunnel->GetNextIdentHash (), path.farEndTransports); std::shared_ptr tunnel; - if (path.isShort) + // TODO: implement it better + tunnel = tunnels.CreateOutboundTunnel (config, inboundTunnel->GetTunnelPool ()); + if (tunnel) { - // TODO: implement it better - tunnel = tunnels.CreateOutboundTunnel (config, inboundTunnel->GetTunnelPool ()); tunnel->SetTunnelPool (shared_from_this ()); + if (tunnel->IsEstablished ()) // zero hops + TunnelCreated (tunnel); } - else - tunnel = tunnels.CreateOutboundTunnel (config, shared_from_this ()); - if (tunnel && tunnel->IsEstablished ()) // zero hops - TunnelCreated (tunnel); } else LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no peers available"); @@ -848,7 +840,7 @@ namespace tunnel auto peers = tunnel->GetPeers(); if (peers.size () && ValidatePeers (peers)) config = std::make_shared(peers, inboundTunnel->GetNextTunnelID (), - inboundTunnel->GetNextIdentHash (), inboundTunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + inboundTunnel->GetNextIdentHash (), tunnel->GetFarEndTransports ()); } if (!m_NumOutboundHops || config) { @@ -865,8 +857,7 @@ namespace tunnel { LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel..."); auto tunnel = tunnels.CreateInboundTunnel ( - m_NumOutboundHops > 0 ? std::make_shared(outboundTunnel->GetInvertedPeers (), - outboundTunnel->IsShortBuildMessage ()) : nullptr, + m_NumOutboundHops > 0 ? std::make_shared(outboundTunnel->GetInvertedPeers ()) : nullptr, shared_from_this (), outboundTunnel); if (tunnel->IsEstablished ()) // zero hops TunnelCreated (tunnel); diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 99b61994..5b7b4337 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -44,7 +44,6 @@ namespace tunnel struct Path { std::vector peers; - bool isShort = true; i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports; void Add (std::shared_ptr r);