diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 6d14bbd7..71af2a90 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -68,11 +68,7 @@ namespace transport // we are Alice if (!session || !relayTag) return false; // find local adddress to introduce - std::shared_ptr localAddress; - if (session->m_Address->IsV4 ()) - localAddress = i2p::context.GetRouterInfo ().GetSSU2V4Address (); - else if (session->m_Address->IsV6 ()) - localAddress = i2p::context.GetRouterInfo ().GetSSU2V6Address (); + auto localAddress = session->FindLocalAddress (); if (localAddress) return false; // create nonce uint32_t nonce; @@ -1361,6 +1357,18 @@ namespace transport return size; } + std::shared_ptr SSU2Session::FindLocalAddress () const + { + if (m_Address) + { + if (m_Address->IsV4 ()) + return i2p::context.GetRouterInfo ().GetSSU2V4Address (); + if (m_Address->IsV6 ()) + return i2p::context.GetRouterInfo ().GetSSU2V6Address (); + } + return nullptr; + } + size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) { if (len < 9) return 0; @@ -1556,6 +1564,30 @@ namespace transport return payloadSize + 3; } + size_t SSU2Session::CreatePeerTestBlock (uint8_t * buf, size_t len) + { + auto localAddress = FindLocalAddress (); + if (localAddress) return 0; + // signed data + uint32_t nonce; + RAND_bytes ((uint8_t *)&nonce, 4); + auto ts = i2p::util::GetSecondsSinceEpoch (); + uint8_t signedData[96]; + signedData[0] = 2; // ver + htobe32buf (signedData + 1, nonce); + htobe32buf (signedData + 5, ts); + size_t asz = CreateEndpoint (signedData + 7, 86, boost::asio::ip::udp::endpoint (localAddress->host, localAddress->port)); + signedData[6] = asz; + // signature + SignedData s; + s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue + s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash + s.Insert (signedData, 7 + asz); // ver, nonce, ts, asz, Alice's endpoint + s.Sign (i2p::context.GetPrivateKeys (), signedData + 7 + asz); + return CreatePeerTestBlock (buf, len, 0, i2p::context.GetIdentHash (), + signedData, 7 + asz + i2p::context.GetIdentity ()->GetSignatureLen ()); + } + std::shared_ptr SSU2Session::ExtractRouterInfo (const uint8_t * buf, size_t size) { if (size < 2) return nullptr; diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index cce60549..f9dff1a3 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -196,6 +196,7 @@ namespace transport void HandleAckRange (uint32_t firstPacketNum, uint32_t lastPacketNum); bool ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep); size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); + std::shared_ptr FindLocalAddress () const; std::shared_ptr ExtractRouterInfo (const uint8_t * buf, size_t size); void CreateNonce (uint64_t seqn, uint8_t * nonce); bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate @@ -217,6 +218,7 @@ namespace transport size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen); size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, uint32_t nonce); // Charlie size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen); + size_t CreatePeerTestBlock (uint8_t * buf, size_t len); // Alice private: