From 706b976a28c01ba00e147ce5a3dfbe59baa112e7 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 15 Jun 2018 12:52:43 -0400 Subject: [PATCH] handle and publish NTCP2 address --- libi2pd/RouterContext.cpp | 24 +++++++++++---- libi2pd/RouterContext.h | 6 +++- libi2pd/RouterInfo.cpp | 61 ++++++++++++++++++++++++++++++--------- libi2pd/RouterInfo.h | 7 +++-- 4 files changed, 77 insertions(+), 21 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b0f1aa51..862352ba 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -2,6 +2,7 @@ #include #include "Config.h" #include "Crypto.h" +#include "Ed25519.h" #include "Timestamp.h" #include "I2NPProtocol.h" #include "NetDb.hpp" @@ -36,7 +37,7 @@ namespace i2p void RouterContext::CreateNewRouter () { m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); - SaveKeys (); + SaveKeys (); NewRouterInfo (); } @@ -49,7 +50,8 @@ namespace i2p port = rand () % (30777 - 9111) + 9111; // I2P network ports range bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv6; i2p::config::GetOption("ipv6", ipv6); - bool nat; i2p::config::GetOption("nat", nat); + bool ntcp2; i2p::config::GetOption("ntcp2", ntcp2); + bool nat; i2p::config::GetOption("nat", nat); std::string ifname; i2p::config::GetOption("ifname", ifname); std::string ifname4; i2p::config::GetOption("ifname4", ifname4); std::string ifname6; i2p::config::GetOption("ifname6", ifname6); @@ -82,6 +84,11 @@ namespace i2p routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); routerInfo.AddNTCPAddress (host.c_str(), port); } + if (ntcp2) + { + NewNTCP2Keys (); + routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); + } routerInfo.SetCaps (i2p::data::RouterInfo::eReachable | i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC @@ -102,11 +109,14 @@ namespace i2p void RouterContext::NewNTCP2Keys () { m_NTCP2Keys.reset (new NTCP2PrivateKeys ()); - RAND_bytes (m_NTCP2Keys->staticKey, 32); + RAND_bytes (m_NTCP2Keys->staticPrivateKey, 32); RAND_bytes (m_NTCP2Keys->iv, 16); + BN_CTX * ctx = BN_CTX_new (); + i2p::crypto::GetEd25519 ()->ScalarMulB (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey, ctx); + BN_CTX_free (ctx); // save std::ofstream fk (i2p::fs::DataDirPath (NTCP2_KEYS), std::ofstream::binary | std::ofstream::out); - fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys)); + fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys)); } void RouterContext::SetStatus (RouterStatus status) @@ -455,9 +465,13 @@ namespace i2p m_NTCP2Keys.reset (new NTCP2PrivateKeys ()); n2k.read ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys)); } + n2k.close (); } - if (!m_NTCP2Keys) + if (!m_NTCP2Keys) + { NewNTCP2Keys (); + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); + } } return true; diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 02c0156b..ae4aa17e 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -37,7 +37,8 @@ namespace i2p struct NTCP2PrivateKeys { - uint8_t staticKey[32]; + uint8_t staticPublicKey[32]; + uint8_t staticPrivateKey[32]; uint8_t iv[16]; }; @@ -58,6 +59,9 @@ namespace i2p return std::shared_ptr (this, [](i2p::garlic::GarlicDestination *) {}); } + const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; }; + const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; }; + const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; }; uint32_t GetUptime () const; uint32_t GetStartupTime () const { return m_StartupTime; }; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 87f16346..088ba154 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -176,10 +176,14 @@ namespace data auto address = std::make_shared
(); s.read ((char *)&address->cost, sizeof (address->cost)); s.read ((char *)&address->date, sizeof (address->date)); - char transportStyle[5]; - ReadString (transportStyle, 5, s); - if (!strcmp (transportStyle, "NTCP")) + bool isNtcp2 = false; + char transportStyle[6]; + auto transportStyleLen = ReadString (transportStyle, 6, s) - 1; + if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2 + { address->transportStyle = eTransportNTCP; + if (transportStyleLen > 4 || transportStyle[4] == '2') isNtcp2= true; + } else if (!strcmp (transportStyle, "SSU")) { address->transportStyle = eTransportSSU; @@ -288,7 +292,7 @@ namespace data if (!s) return; } if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented - if (supportedTransports) + if (supportedTransports && !isNtcp2) // we ignore NTCP2 addresses for now. TODO: { addresses->push_back(address); m_SupportedTransports |= supportedTransports; @@ -435,7 +439,7 @@ namespace data s.write ((const char *)&address.date, sizeof (address.date)); std::stringstream properties; if (address.transportStyle == eTransportNTCP) - WriteString ("NTCP", s); + WriteString (address.IsNTCP2 () ? "NTCP2" : "NTCP", s); else if (address.transportStyle == eTransportSSU) { WriteString ("SSU", s); @@ -451,10 +455,13 @@ namespace data else WriteString ("", s); - WriteString ("host", properties); - properties << '='; - WriteString (address.host.to_string (), properties); - properties << ';'; + if (!address.IsNTCP2 ()) // we don't publish NTCP2 address fow now. TODO: implement + { + WriteString ("host", properties); + properties << '='; + WriteString (address.host.to_string (), properties); + properties << ';'; + } if (address.transportStyle == eTransportSSU) { // write introducers if any @@ -529,10 +536,23 @@ namespace data properties << ';'; } } - WriteString ("port", properties); - properties << '='; - WriteString (boost::lexical_cast(address.port), properties); - properties << ';'; + + if (!address.IsNTCP2 ()) // we don't publish NTCP2 address fow now. TODO: implement + { + WriteString ("port", properties); + properties << '='; + WriteString (boost::lexical_cast(address.port), properties); + properties << ';'; + } + if (address.IsNTCP2 ()) + { + // publish s and v for NTCP2 + WriteString ("s", properties); properties << '='; + WriteString (address.ntcp2->staticKey.ToBase64 (), properties); properties << ';'; + WriteString ("v", properties); properties << '='; + WriteString ("2", properties); properties << ';'; + // TODO: publish "i" + } uint16_t size = htobe16 (properties.str ().size ()); s.write ((char *)&size, sizeof (size)); @@ -668,6 +688,21 @@ namespace data m_Caps |= eSSUIntroducer; } + void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv) + { + for (const auto& it: *m_Addresses) // don't insert one more NTCP2 + if (it->ntcp2) return; + auto addr = std::make_shared
(); + addr->port = 0; + addr->transportStyle = eTransportNTCP; + addr->cost = 14; + addr->date = 0; + addr->ntcp2.reset (new NTCP2Ext ()); + memcpy (addr->ntcp2->staticKey, staticKey, 32); + memcpy (addr->ntcp2->iv, iv, 32); + m_Addresses->push_back(std::move(addr)); + } + bool RouterInfo::AddIntroducer (const Introducer& introducer) { for (auto& addr : *m_Addresses) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 1125bdef..a12b23e3 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -92,8 +92,8 @@ namespace data struct NTCP2Ext { - uint8_t staticKey[32]; - uint8_t iv[16]; + Tag<32> staticKey; + Tag<16> iv; }; struct Address @@ -122,6 +122,8 @@ namespace data { return !(*this == other); } + + bool IsNTCP2 () const { return (bool)ntcp2; }; }; typedef std::list > Addresses; @@ -143,6 +145,7 @@ namespace data void AddNTCPAddress (const char * host, int port); void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0); + void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv); bool AddIntroducer (const Introducer& introducer); bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); void SetProperty (const std::string& key, const std::string& value); // called from RouterContext only