From eb5a808232e22290c597110bfd2a60eda2db1f3a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Mar 2026 20:26:29 -0400 Subject: [PATCH] handle ssu2.version in config and pq in SSU2 address in RouterInfo --- libi2pd/Config.cpp | 1 + libi2pd/RouterInfo.cpp | 31 +++++++++++++++++-------------- libi2pd/SSU2.cpp | 10 +++++++++- libi2pd/SSU2.h | 4 ++++ libi2pd/SSU2OutOfSession.cpp | 6 +++++- libi2pd/SSU2Session.cpp | 23 +++++++++++++++++++---- libi2pd/Transports.cpp | 4 +++- 7 files changed, 58 insertions(+), 21 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 2840be35..3b15fc88 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -339,6 +339,7 @@ namespace config { ("ssu2.proxy", value()->default_value(""), "Socks5 proxy URL for SSU2 transport") ("ssu2.firewalled4", value()->default_value(false), "Set ipv4 network status to Firewalled even if OK (default: disabled)") ("ssu2.firewalled6", value()->default_value(false), "Set ipv6 network status to Firewalled even if OK (default: disabled)") + ("ssu2.version", value()->default_value(2), "Protocol version. 2 - standard, 3,4 - post quantum (default: 2") ; options_description nettime("Time sync options"); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 718c082e..778a7c14 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -219,7 +219,6 @@ namespace data offset++; // cost, ignore address->date = bufbe64toh (buf + offset); offset += 8; // date bool isHost = false, isStaticKey = false, isV2 = false, isIntroKey = false; - int pq = 0; auto transportStyle = ExtractString (buf + offset, len - offset); offset += transportStyle.length () + 1; if (!transportStyle.compare (0, 4, "NTCP")) // NTCP or NTCP2 address->transportStyle = eTransportNTCP2; @@ -308,14 +307,8 @@ namespace data } else if (key == "v") { - if (value.size () == 1 && value[0] >= '2' && value[0] <= '5') // only 2,3,4,5 allowed - { - if (pq >= 3 && pq <= 5) - address->v = pq; - else - address->v = value[0] - '0'; + if (value == "2") // only 2 is allowed isV2 = true; - } else { LogPrint (eLogWarning, "RouterInfo: Unexpected value ", value, " for v"); @@ -324,9 +317,16 @@ namespace data } else if (key == "pq") { - if (address->transportStyle == eTransportNTCP2 && // for NTCP2 only for now - value.size () == 1 && value[0] >= '3' && value[0] <= '5') // only 3,4,5 allowed - pq = value[0] - '0'; + if (address->transportStyle == eTransportNTCP2) + { + if (value.size () == 1 && value[0] >= '3' && value[0] <= '5') // only 3,4,5 allowed + address->v = value[0] - '0'; + } + else if (address->transportStyle == eTransportSSU2) + { + if (value.size () == 1 && value[0] >= '3' && value[0] <= '4') // only 3,4 allowed + address->v = value[0] - '0'; + } } else if (key[0] == 'i') { @@ -1453,10 +1453,13 @@ namespace data WriteString (std::to_string(address.port), properties); properties << ';'; } - if (address.v >= 3 && address.v <= 5 && address.IsNTCP2 ()) // post quantum + if (address.v >= 3) // post quantum { - WriteString ("pq", properties); properties << '='; - WriteString (std::to_string (address.v), properties); properties << ';'; + if (address.v <= 4 || (address.v == 5 && address.IsNTCP2 ())) + { + WriteString ("pq", properties); properties << '='; + WriteString (std::to_string (address.v), properties); properties << ';'; + } } if (address.IsNTCP2 () || address.IsSSU2 ()) { diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 895a585e..7fe2064f 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -26,7 +26,7 @@ namespace transport m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), m_IsPublished (true), m_IsSyncClockFromPeers (true), m_PendingTimeOffset (0), m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL), m_IsForcedFirewalled4 (false), - m_IsForcedFirewalled6 (false), m_IsThroughProxy (false) + m_IsForcedFirewalled6 (false), m_Version (2), m_IsThroughProxy (false) { } @@ -784,6 +784,7 @@ namespace transport { auto session = std::make_shared (*this); session->SetRemoteEndpoint (senderEndpoint); + session->SetVersion (m_Version); session->ProcessFirstIncomingMessage (connID, buf, len); } else @@ -1559,6 +1560,13 @@ namespace transport m_ChaCha20 (msg, msgLen, key, nonce, out); } + void SSU2Server::SetVersion (int version) + { +#if OPENSSL_PQ + m_Version = version; +#endif + } + void SSU2Server::SendThroughProxy (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to) { diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index d1ec2aaa..5729051e 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -139,6 +139,9 @@ namespace transport i2p::util::MemoryPool& GetIncompleteMessagesPool () { return m_IncompleteMessagesPool; }; i2p::util::MemoryPool& GetFragmentsPool () { return m_FragmentsPool; }; + void SetVersion (int version); + int GetVersion () const { return m_Version; } + private: boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint); @@ -215,6 +218,7 @@ namespace transport i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor; i2p::crypto::ChaCha20Context m_ChaCha20; bool m_IsForcedFirewalled4, m_IsForcedFirewalled6; + int m_Version; // proxy bool m_IsThroughProxy; diff --git a/libi2pd/SSU2OutOfSession.cpp b/libi2pd/SSU2OutOfSession.cpp index ba9ae244..123cfc8f 100644 --- a/libi2pd/SSU2OutOfSession.cpp +++ b/libi2pd/SSU2OutOfSession.cpp @@ -165,7 +165,7 @@ namespace transport header.h.connID = GetDestConnID (); // dest id RAND_bytes (header.buf + 8, 4); // random packet num header.h.type = eSSU2PeerTest; - header.h.flags[0] = GetVersion (); // ver + header.h.flags[0] = 2; // ver, always 2 even for post-quantum header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID header.h.flags[2] = 0; // flag memcpy (h, header.buf, 16); @@ -263,6 +263,10 @@ namespace transport SetState (eSSU2SessionStateHolePunch); SetRemoteEndpoint (remoteEndpoint); SetAddress (addr); +#if OPENSSL_PQ + if (server.GetVersion () > 2) // we support post quantum in config + SetVersion (addr->v); +#endif SetTerminationTimeout (SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT); } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 83039cc3..16f75f57 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -710,6 +710,10 @@ namespace transport bool SSU2Session::SendSessionRequest (uint64_t token) { // we are Alice +#if OPENSSL_PQ + if (m_Server.GetVersion () > 2) // we support post quantum in config + SetVersion (m_Address->v); +#endif m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); m_SentHandshakePacket.reset (new HandshakePacket); auto ts = i2p::util::GetMillisecondsSinceEpoch (); @@ -823,9 +827,16 @@ namespace transport LogPrint (eLogWarning, "SSU2: SessionRequest message too short ", len); return; } - if (header.h.flags[0] <= m_Version) // ver - SetVersion (header.h.flags[0]); +#if OPENSSL_PQ + if (header.h.flags[0] >= 2 && header.h.flags[0] <= 4) // ver + { + if (m_Version > 2) + SetVersion (header.h.flags[0]); + } else +#else + if (header.h.flags[0] != 2) // ver +#endif { LogPrint (eLogWarning, "SSU2: SessionRequest protocol version ", header.h.flags[0], " is not supported"); return; @@ -1423,13 +1434,17 @@ namespace transport void SSU2Session::SendTokenRequest () { // we are Alice +#if OPENSSL_PQ + if (m_Server.GetVersion () > 2) // we support post quantum in config + SetVersion (m_Address->v); +#endif Header header; uint8_t h[32], payload[41]; // fill packet header.h.connID = m_DestConnID; // dest id RAND_bytes (header.buf + 8, 4); // random packet num header.h.type = eSSU2TokenRequest; - header.h.flags[0] = 2; // ver + header.h.flags[0] = GetVersion (); // ver header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID header.h.flags[2] = 0; // flag memcpy (h, header.buf, 16); @@ -1497,7 +1512,7 @@ namespace transport header.h.connID = m_DestConnID; // dest id RAND_bytes (header.buf + 8, 4); // random packet num header.h.type = eSSU2Retry; - header.h.flags[0] = 2; // ver + header.h.flags[0] = GetVersion (); // ver header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID header.h.flags[2] = 0; // flag memcpy (h, header.buf, 16); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 0d920b80..1337fb95 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -197,9 +197,10 @@ namespace transport m_IsRunning = true; m_Thread = new std::thread (std::bind (&Transports::Run, this)); std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); - int ntcp2version = 2; + int ntcp2version = 2, ssu2version = 2; #if OPENSSL_PQ i2p::config::GetOption("ntcp2.version", ntcp2version); + i2p::config::GetOption("ssu2.version", ssu2version); #endif i2p::http::URL proxyurl; // create NTCP2. TODO: move to acceptor @@ -237,6 +238,7 @@ namespace transport if (enableSSU2) { m_SSU2Server = new SSU2Server (); + m_SSU2Server->SetVersion (ssu2version); std::string ssu2proxy; i2p::config::GetOption("ssu2.proxy", ssu2proxy); if (!ssu2proxy.empty()) {