mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-06-03 04:46:23 +02:00
fill phony record for inbound tunnel with x25519 public key
This commit is contained in:
parent
4c6be3b85a
commit
606881898b
4 changed files with 110 additions and 26 deletions
|
@ -29,7 +29,7 @@ namespace i2p
|
|||
{
|
||||
namespace tunnel
|
||||
{
|
||||
Tunnel::Tunnel (std::shared_ptr<const TunnelConfig> config):
|
||||
Tunnel::Tunnel (std::shared_ptr<TunnelConfig> config):
|
||||
TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()),
|
||||
m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr),
|
||||
m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports),
|
||||
|
@ -44,7 +44,13 @@ namespace tunnel
|
|||
void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
||||
{
|
||||
auto numHops = m_Config->GetNumHops ();
|
||||
const int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS;
|
||||
bool insertPhonyRecord = m_Config->IsInbound() && numHops < MAX_NUM_RECORDS;
|
||||
if (insertPhonyRecord)
|
||||
{
|
||||
m_Config->CreatePhonyHop ();
|
||||
numHops++;
|
||||
}
|
||||
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;
|
||||
|
@ -52,8 +58,7 @@ namespace tunnel
|
|||
// shuffle records
|
||||
std::vector<int> recordIndicies;
|
||||
for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i);
|
||||
std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()()));
|
||||
|
||||
std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()()));
|
||||
// create real records
|
||||
uint8_t * records = msg->GetPayload () + 1;
|
||||
TunnelHopConfig * hop = m_Config->GetFirstHop ();
|
||||
|
@ -61,7 +66,7 @@ namespace tunnel
|
|||
while (hop)
|
||||
{
|
||||
uint32_t msgID;
|
||||
if (hop->next) // we set replyMsgID for last hop only
|
||||
if (hop->next && hop->next->ident) // we set replyMsgID for last non-phony hop only
|
||||
RAND_bytes ((uint8_t *)&msgID, 4);
|
||||
else
|
||||
msgID = replyMsgID;
|
||||
|
@ -89,6 +94,9 @@ namespace tunnel
|
|||
}
|
||||
hop = hop->prev;
|
||||
}
|
||||
// delete phony hop after encryption
|
||||
if (insertPhonyRecord) m_Config->DeletePhonyHop ();
|
||||
|
||||
msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild);
|
||||
auto s = shared_from_this ();
|
||||
msg->onDrop = [s]()
|
||||
|
|
|
@ -81,12 +81,12 @@ namespace tunnel
|
|||
/** function for visiting a hops stored in a tunnel */
|
||||
typedef std::function<void(std::shared_ptr<const i2p::data::IdentityEx>)> TunnelHopVisitor;
|
||||
|
||||
Tunnel (std::shared_ptr<const TunnelConfig> config);
|
||||
Tunnel (std::shared_ptr<TunnelConfig> config);
|
||||
~Tunnel ();
|
||||
|
||||
void Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
||||
|
||||
std::shared_ptr<const TunnelConfig> GetTunnelConfig () const { return m_Config; }
|
||||
std::shared_ptr<TunnelConfig> GetTunnelConfig () const { return m_Config; }
|
||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const;
|
||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const;
|
||||
bool IsShortBuildMessage () const { return m_IsShortBuildMessage; };
|
||||
|
@ -125,7 +125,7 @@ namespace tunnel
|
|||
|
||||
private:
|
||||
|
||||
std::shared_ptr<const TunnelConfig> m_Config;
|
||||
std::shared_ptr<TunnelConfig> m_Config;
|
||||
std::vector<TunnelHop> m_Hops;
|
||||
bool m_IsShortBuildMessage;
|
||||
std::shared_ptr<TunnelPool> m_Pool; // pool, tunnel belongs to, or null
|
||||
|
@ -139,7 +139,7 @@ namespace tunnel
|
|||
{
|
||||
public:
|
||||
|
||||
OutboundTunnel (std::shared_ptr<const TunnelConfig> config):
|
||||
OutboundTunnel (std::shared_ptr<TunnelConfig> config):
|
||||
Tunnel (config), m_Gateway (*this), m_EndpointIdentHash (config->GetLastIdentHash ()) {};
|
||||
|
||||
void SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
|
@ -164,7 +164,7 @@ namespace tunnel
|
|||
{
|
||||
public:
|
||||
|
||||
InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
|
||||
InboundTunnel (std::shared_ptr<TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
|
||||
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override;
|
||||
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
||||
bool IsInbound() const override { return true; }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
|
@ -219,6 +219,42 @@ 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;
|
||||
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetIdentHash (), 16);
|
||||
memcpy (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, i2p::transport::transports.GetNextX25519KeysPair ()->GetPublicKey (), 32);
|
||||
RAND_bytes (record + 48, SHORT_TUNNEL_BUILD_RECORD_SIZE - 48);
|
||||
}
|
||||
|
||||
TunnelConfig::TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||
bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports):
|
||||
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
||||
{
|
||||
// inbound
|
||||
CreatePeers (peers);
|
||||
m_LastHop->SetNextIdent (i2p::context.GetIdentHash ());
|
||||
}
|
||||
|
||||
TunnelConfig::TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||
uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort,
|
||||
i2p::data::RouterInfo::CompatibleTransports farEndTransports):
|
||||
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
||||
{
|
||||
// outbound
|
||||
CreatePeers (peers);
|
||||
m_FirstHop->isGateway = false;
|
||||
m_LastHop->SetReplyHop (replyTunnelID, replyIdent);
|
||||
}
|
||||
|
||||
void TunnelConfig::CreatePeers (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers)
|
||||
{
|
||||
TunnelHopConfig * prev = nullptr;
|
||||
|
@ -245,5 +281,35 @@ namespace tunnel
|
|||
}
|
||||
m_LastHop = prev;
|
||||
}
|
||||
|
||||
void TunnelConfig::CreatePhonyHop ()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelConfig::DeletePhonyHop ()
|
||||
{
|
||||
if (m_LastHop && !m_LastHop->ident)
|
||||
{
|
||||
if (m_LastHop->prev) m_LastHop->prev->next = nullptr;
|
||||
else m_FirstHop = nullptr;
|
||||
auto tmp = m_LastHop;
|
||||
m_LastHop = m_LastHop->prev;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
|
@ -77,28 +77,35 @@ namespace tunnel
|
|||
uint64_t GetGarlicKey (uint8_t * key) const override;
|
||||
};
|
||||
|
||||
struct PhonyTunnelHopConfig: public ECIESTunnelHopConfig
|
||||
{
|
||||
PhonyTunnelHopConfig (): ECIESTunnelHopConfig (nullptr) {}
|
||||
uint8_t GetRetCode (const uint8_t * records) const override { return 0; }
|
||||
bool DecryptBuildResponseRecord (uint8_t * records) const override { return true; }
|
||||
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<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||
bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // inbound
|
||||
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
||||
{
|
||||
CreatePeers (peers);
|
||||
m_LastHop->SetNextIdent (i2p::context.GetIdentHash ());
|
||||
}
|
||||
bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // inbound
|
||||
|
||||
TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||
uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort,
|
||||
i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // outbound
|
||||
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
||||
{
|
||||
CreatePeers (peers);
|
||||
m_FirstHop->isGateway = false;
|
||||
m_LastHop->SetReplyHop (replyTunnelID, replyIdent);
|
||||
}
|
||||
|
||||
i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // outbound
|
||||
|
||||
virtual ~TunnelConfig ()
|
||||
{
|
||||
TunnelHopConfig * hop = m_FirstHop;
|
||||
|
@ -182,6 +189,9 @@ namespace tunnel
|
|||
}
|
||||
|
||||
size_t GetRecordSize () const { return m_IsShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; };
|
||||
|
||||
void CreatePhonyHop ();
|
||||
void DeletePhonyHop ();
|
||||
|
||||
protected:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue