From 569088eaca25e63ac9c396df6b8c0451f5201a8f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 21 Oct 2019 12:02:43 -0400 Subject: [PATCH 01/51] 2.29.0 --- ChangeLog | 1 + qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0afe2316..07110fe2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ ### Fixed - Failure to start on Windows XP - SAM crash if invalid lookup address +- Possible crash when UPnP enabled on shutdown ## [2.28.0] - 2019-08-27 ### Added diff --git a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml index 2c30a2d6..e6cc81d3 100644 --- a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml +++ b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml @@ -35,7 +35,7 @@ - + From c66f9c8d6ddf43fbc1946f061a822d3c2c11a354 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 06:46:08 -0500 Subject: [PATCH 02/51] reset connection attempts before reconnect --- libi2pd/Transports.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 93db02d8..7e4ab797 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -651,7 +651,10 @@ namespace transport if (it->second.sessions.empty ()) // TODO: why? { if (it->second.delayedMessages.size () > 0) + { + it->second.numAttempts = 0; ConnectToPeer (ident, it->second); + } else { std::unique_lock l(m_PeersMutex); From 60fd3a45428392e75a4f79cd00df91e510409df4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 07:17:57 -0500 Subject: [PATCH 03/51] fixed #1434 use memset inster bzero --- libi2pd/Transports.cpp | 2 +- libi2pd/util.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 7e4ab797..b081439b 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -652,7 +652,7 @@ namespace transport { if (it->second.delayedMessages.size () > 0) { - it->second.numAttempts = 0; + // it->second.numAttempts = 0; // TODO: recognize if connect failed ConnectToPeer (ident, it->second); } else diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 96e8ad4c..76fe6d43 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -312,15 +312,14 @@ namespace net if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af) { // match - char * addr = new char[INET6_ADDRSTRLEN]; - bzero(addr, INET6_ADDRSTRLEN); + char addr[INET6_ADDRSTRLEN]; + memset (addr, 0, INET6_ADDRSTRLEN); if(af == AF_INET) inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN); else inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN); freeifaddrs(addrs); std::string cur_ifaddr(addr); - delete[] addr; return boost::asio::ip::address::from_string(cur_ifaddr); } cur = cur->ifa_next; From 77189bf8e963e6e72b482fcb2e234ebb964244f9 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 09:38:22 -0500 Subject: [PATCH 04/51] start over if an active session got disconnected --- libi2pd/Transports.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index b081439b..34a28fb8 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -647,12 +647,14 @@ namespace transport auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { + auto before = it->second.sessions.size (); it->second.sessions.remove (session); - if (it->second.sessions.empty ()) // TODO: why? + if (it->second.sessions.empty ()) { if (it->second.delayedMessages.size () > 0) { - // it->second.numAttempts = 0; // TODO: recognize if connect failed + if (before > 0) // we had an active session before + it->second.numAttempts = 0; // start over ConnectToPeer (ident, it->second); } else From 651240113c6dc1a133c034c861efb303daefba07 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 10:03:33 -0500 Subject: [PATCH 05/51] mark RI as unreachable if all connections failed --- libi2pd/Transports.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 34a28fb8..42a605a4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -465,6 +465,7 @@ namespace transport } } LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available"); + i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed peer.Done (); std::unique_lock l(m_PeersMutex); m_Peers.erase (ident); From c3e3c091cc667e6fead61e6ada75795461b8a34b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 11:35:59 -0500 Subject: [PATCH 06/51] correct implementation of GetMTUWindows for WindowsXP --- libi2pd/util.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 76fe6d43..ebf977e2 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -61,17 +61,22 @@ namespace net { #ifdef WIN32 bool IsWindowsXPorLater() - { - OSVERSIONINFO osvi; + { + static bool isRequested = false; + static bool isXP = false; + if (!isRequested) + { + // request + OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); - if (osvi.dwMajorVersion <= 5) - return true; - else - return false; + isXP = osvi.dwMajorVersion <= 5; + isRequested = true; + } + return isXP; } int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback) @@ -202,7 +207,7 @@ namespace net std::string localAddressUniversal = localAddress.to_string(); #endif - if (IsWindowsXPorLater()) + bool isXP = IsWindowsXPorLater(); { #define inet_pton inet_pton_xp } @@ -210,13 +215,19 @@ namespace net if(localAddress.is_v4()) { sockaddr_in inputAddress; - inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); + if (isXP) + inet_pton_xp(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); + else + inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); return GetMTUWindowsIpv4(inputAddress, fallback); } else if(localAddress.is_v6()) { - sockaddr_in6 inputAddress; - inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + sockaddr_in6 inputAddress; + if (isXP) + inet_pton_xp(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + else + inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); return GetMTUWindowsIpv6(inputAddress, fallback); } else { LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported"); From a104c9881e2867102e3025c6c6252a5ae97f5696 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 11:57:34 -0500 Subject: [PATCH 07/51] some cleanup --- libi2pd/RouterContext.cpp | 5 ----- libi2pd/RouterContext.h | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 3323de87..baa5a3d0 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -721,12 +721,7 @@ namespace i2p uint32_t RouterContext::GetUptime () const { -#ifdef WIN32 - // for compatibility with WinXP - return i2p::util::GetSecondsSinceEpoch () - m_StartupTime; -#else return std::chrono::duration_cast (std::chrono::steady_clock::now() - m_StartupTime).count (); -#endif } bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 9385e11f..f6aa281f 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -136,12 +136,8 @@ namespace i2p i2p::data::PrivateKeys m_Keys; std::shared_ptr m_Decryptor; uint64_t m_LastUpdateTime; // in seconds - bool m_AcceptsTunnels, m_IsFloodfill; -#ifdef WIN32 - uint64_t m_StartupTime = 0; // in seconds since epoch -#else + bool m_AcceptsTunnels, m_IsFloodfill; std::chrono::time_point m_StartupTime; -#endif uint64_t m_BandwidthLimit; // allowed bandwidth int m_ShareRatio; RouterStatus m_Status; From 34ce06ac17aeb592b85ec3669951c48c69725110 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 14:19:14 -0500 Subject: [PATCH 08/51] some cleanup --- libi2pd/util.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index ebf977e2..8f870ec4 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -61,11 +61,11 @@ namespace net { #ifdef WIN32 bool IsWindowsXPorLater() - { - static bool isRequested = false; - static bool isXP = false; - if (!isRequested) - { + { + static bool isRequested = false; + static bool isXP = false; + if (!isRequested) + { // request OSVERSIONINFO osvi; @@ -73,8 +73,8 @@ namespace net osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); - isXP = osvi.dwMajorVersion <= 5; - isRequested = true; + isXP = osvi.dwMajorVersion <= 5; + isRequested = true; } return isXP; } @@ -208,24 +208,21 @@ namespace net #endif bool isXP = IsWindowsXPorLater(); - { - #define inet_pton inet_pton_xp - } if(localAddress.is_v4()) { sockaddr_in inputAddress; - if (isXP) - inet_pton_xp(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); - else + if (isXP) + inet_pton_xp(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); + else inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); return GetMTUWindowsIpv4(inputAddress, fallback); } else if(localAddress.is_v6()) { - sockaddr_in6 inputAddress; - if (isXP) - inet_pton_xp(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + sockaddr_in6 inputAddress; + if (isXP) + inet_pton_xp(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); else inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); return GetMTUWindowsIpv6(inputAddress, fallback); From 515c0860990c52b185a3fa36ebcad4bcfcf83a74 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 12 Nov 2019 15:06:04 -0500 Subject: [PATCH 09/51] Use GetProcAddress for inet_pton. Fixed build error --- libi2pd/RouterContext.cpp | 30 +++++++++++++----------------- libi2pd/util.cpp | 18 +++++++----------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index baa5a3d0..bf3459d8 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -27,12 +27,8 @@ namespace i2p void RouterContext::Init () { srand (i2p::util::GetMillisecondsSinceEpoch () % 1000); -#ifdef WIN32 - // for compatibility with WinXP - m_StartupTime = i2p::util::GetSecondsSinceEpoch (); -#else - m_StartupTime = std::chrono::steady_clock::now(); -#endif + m_StartupTime = std::chrono::steady_clock::now(); + if (!Load ()) CreateNewRouter (); m_Decryptor = m_Keys.CreateDecryptor (nullptr); @@ -194,11 +190,11 @@ namespace i2p if (address->IsNTCP2 () && (address->port != port || address->ntcp2->isPublished != publish) && (!v4only || address->host.is_v4 ())) { if (!port && !address->port) - { + { // select random port only if address's port is not set port = rand () % (30777 - 9111) + 9111; // I2P network ports range if (port == 9150) port = 9151; // Tor browser - } + } if (port) address->port = port; address->cost = publish ? 3 : 14; address->ntcp2->isPublished = publish; @@ -438,14 +434,14 @@ namespace i2p } // remove NTCP or NTCP2 v4 address bool ntcp; i2p::config::GetOption("ntcp", ntcp); - if (ntcp) + if (ntcp) PublishNTCPAddress (false); else { bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) PublishNTCP2Address (port, false, true); - } + } // update UpdateRouterInfo (); } @@ -495,7 +491,7 @@ namespace i2p void RouterContext::SetSupportsV6 (bool supportsV6) { if (supportsV6) - { + { m_RouterInfo.EnableV6 (); // insert v6 addresses if necessary bool foundSSU = false, foundNTCP = false, foundNTCP2 = false; @@ -513,7 +509,7 @@ namespace i2p } else foundNTCP = true; - } + } port = addr->port; } if (!port) i2p::config::GetOption("port", port); @@ -525,7 +521,7 @@ namespace i2p { std::string host = "::1"; // TODO: read host m_RouterInfo.AddSSUAddress (host.c_str (), port, GetIdentHash ()); - } + } } // NTCP2 if (!foundNTCP2) @@ -534,11 +530,11 @@ namespace i2p bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); if (ntcp2 && ntcp2Published) { - std::string ntcp2Host; + std::string ntcp2Host; if (!i2p::config::IsDefault ("ntcp2.addressv6")) i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); else - ntcp2Host = "::1"; + ntcp2Host = "::1"; uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); if (!ntcp2Port) ntcp2Port = port; m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port); @@ -550,10 +546,10 @@ namespace i2p bool ntcp; i2p::config::GetOption("ntcp", ntcp); if (ntcp) { - std::string host = "::1"; + std::string host = "::1"; m_RouterInfo.AddNTCPAddress (host.c_str (), port); } - } + } } else m_RouterInfo.DisableV6 (); diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 8f870ec4..448d1307 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -22,7 +22,7 @@ #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) -// inet_pton exists Windows since Vista, but XP haven't that function! +// inet_pton exists Windows since Vista, but XP doesn't have that function! // This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found int inet_pton_xp(int af, const char *src, void *dst) { @@ -206,25 +206,21 @@ namespace net #else std::string localAddressUniversal = localAddress.to_string(); #endif - - bool isXP = IsWindowsXPorLater(); + + typedef int (* IPN)(int af, const char *src, void *dst); + IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); + if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found if(localAddress.is_v4()) { sockaddr_in inputAddress; - if (isXP) - inet_pton_xp(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); - else - inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); + inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); return GetMTUWindowsIpv4(inputAddress, fallback); } else if(localAddress.is_v6()) { sockaddr_in6 inputAddress; - if (isXP) - inet_pton_xp(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); - else - inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); return GetMTUWindowsIpv6(inputAddress, fallback); } else { LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported"); From 6cfe4fa580a235920597d09da0392a854d2d2a47 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 18 Nov 2019 14:13:31 -0500 Subject: [PATCH 10/51] handle sending errors --- libi2pd/NTCP2.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 9918efbc..5183bbe6 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1035,7 +1035,9 @@ namespace transport if (ecode) { - LogPrint (eLogWarning, "NTCP2: Couldn't send frame ", ecode.message ()); + if (ecode != boost::asio::error::operation_aborted) + LogPrint (eLogWarning, "NTCP2: Couldn't send frame ", ecode.message ()); + Terminate (); } else { @@ -1260,7 +1262,10 @@ namespace transport bool NTCP2Server::AddNTCP2Session (std::shared_ptr session, bool incoming) { - if (!session || !session->GetRemoteIdentity ()) return false; + if (!session) return false; + if (incoming) + m_PendingIncomingSessions.remove (session); + if (!session->GetRemoteIdentity ()) return false; auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); auto it = m_NTCP2Sessions.find (ident); if (it != m_NTCP2Sessions.end ()) @@ -1270,8 +1275,6 @@ namespace transport return false; } m_NTCP2Sessions.insert (std::make_pair (ident, session)); - if (incoming) - m_PendingIncomingSessions.remove (session); return true; } From dd94b77b2ab05743495c13a8e20b840bb3690540 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 19 Nov 2019 13:50:16 +0300 Subject: [PATCH 11/51] use GetTickCount dll pointer, add USE_WINXP to makefile Signed-off-by: R4SAS --- Makefile.mingw | 4 ++++ Win32/Win32App.cpp | 13 ++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Makefile.mingw b/Makefile.mingw index e2f9e857..17be71eb 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -37,6 +37,10 @@ ifeq ($(USE_WIN32_APP), yes) DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) endif +ifeq ($(USE_WINXP_FLAGS), yes) + CXXFLAGS += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 +endif + # don't change following line to ifeq ($(USE_AESNI),yes) !!! ifeq ($(USE_AESNI),1) CPU_FLAGS += -maes diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 4bf4ab56..df87da3a 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -13,10 +13,6 @@ #include "Win32App.h" #include -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define snprintf _snprintf -#endif - #define ID_ABOUT 2000 #define ID_EXIT 2001 #define ID_CONSOLE 2002 @@ -39,6 +35,9 @@ namespace i2p namespace win32 { static DWORD GracefulShutdownEndtime = 0; + + typedef DWORD (* IPN)(); + IPN GetTickCountLocal = (IPN)GetProcAddress (GetModuleHandle ("KERNEL32.dll"), "GetTickCount"); static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem) { @@ -53,7 +52,7 @@ namespace win32 ID_ACCEPT_TRANSIT, "Accept &transit"); else InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DECLINE_TRANSIT, "Decline &transit"); - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload configs"); + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload tunnels config"); if (!i2p::util::DaemonWin32::Instance ().isGraceful) InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown"); else @@ -161,7 +160,7 @@ namespace win32 s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ()); if (GracefulShutdownEndtime != 0) { - DWORD GracefulTimeLeft = (GracefulShutdownEndtime - GetTickCount()) / 1000; + DWORD GracefulTimeLeft = (GracefulShutdownEndtime - GetTickCountLocal()) / 1000; s << "Graceful shutdown, time left: "; ShowUptime(s, GracefulTimeLeft); } else @@ -239,7 +238,7 @@ namespace win32 i2p::context.SetAcceptsTunnels (false); SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); // check tunnels every second - GracefulShutdownEndtime = GetTickCount() + 10*60*1000; + GracefulShutdownEndtime = GetTickCountLocal() + 10*60*1000; i2p::util::DaemonWin32::Instance ().isGraceful = true; return 0; } From 95debf8c8079cc270dc698b0e00d3c17a9d865a5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 19 Nov 2019 14:29:55 +0300 Subject: [PATCH 12/51] update mingw build script Signed-off-by: R4SAS --- build/build_mingw.cmd | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/build/build_mingw.cmd b/build/build_mingw.cmd index d7fe363d..ec861bb2 100644 --- a/build/build_mingw.cmd +++ b/build/build_mingw.cmd @@ -54,6 +54,14 @@ set bitness=64 call :BUILDING echo. +REM building for WinXP +set "WD=C:\msys64-xp\usr\bin\" +set MSYSTEM=MINGW32 +set bitness=32 +set "xSH=%WD%bash -lc" +call :BUILDING_XP +echo. + del README.txt >> nul echo Build complete... @@ -71,5 +79,11 @@ echo Build AESNI... %xSH% "make DEBUG=no USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip %FILELIST% && make clean" > build/build_win%bitness%_aesni_%tag%.log 2>&1 echo Build without extensions... %xSH% "make DEBUG=no USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST% && make clean" > build/build_win%bitness%_%tag%.log 2>&1 +goto EOF + +:BUILDING_XP +%xSH% "make clean" >> nul +echo Building i2pd %tag% for winxp... +%xSH% "make DEBUG=no USE_UPNP=yes USE_WINXP_FLAGS=yes -j%threads% && zip -r9 build/i2pd_%tag%_winxp_mingw.zip %FILELIST% && make clean" > build/build_winxp_%tag%.log 2>&1 :EOF \ No newline at end of file From 704fca969f82ff81d0002c1122fa0921a3037e3d Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 20 Nov 2019 12:05:32 -0500 Subject: [PATCH 13/51] handle accept errors --- libi2pd/NTCP2.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 5183bbe6..fd20d35c 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1345,15 +1345,19 @@ namespace transport { conn->ServerLogin (); m_PendingIncomingSessions.push_back (conn); + conn = nullptr; } } else LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } + else + LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); if (error != boost::asio::error::operation_aborted) { - conn = std::make_shared (*this); + if (!conn) // connection is used + conn = std::make_shared (*this); m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); } @@ -1409,13 +1413,13 @@ namespace transport // pending for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();) { - if ((*it)->IsEstablished () || (*it)->IsTerminated ()) - it = m_PendingIncomingSessions.erase (it); // established or terminated - else if ((*it)->IsTerminationTimeoutExpired (ts)) + if ((*it)->IsEstablished () || (*it)->IsTerminationTimeoutExpired (ts)) { (*it)->Terminate (); - it = m_PendingIncomingSessions.erase (it); // expired + it = m_PendingIncomingSessions.erase (it); // etsablished of expired } + else if ((*it)->IsTerminated ()) + it = m_PendingIncomingSessions.erase (it); // already terminated else it++; } From 0abb871f3ffe013110920adf70c8e2f9ee17caeb Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 20 Nov 2019 13:00:50 -0500 Subject: [PATCH 14/51] close socket after if accept failed --- libi2pd/NTCP2.cpp | 4 +++- libi2pd/NTCP2.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index fd20d35c..c12c5804 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1356,8 +1356,10 @@ namespace transport if (error != boost::asio::error::operation_aborted) { - if (!conn) // connection is used + if (!conn) // connection is used, create new one conn = std::make_shared (*this); + else // reuse failed + conn->Close (); m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); } diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 10f4f483..d2f1f88d 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -133,6 +133,7 @@ namespace transport void Terminate (); void TerminateByTimeout (); void Done (); + void Close () { m_Socket.close (); }; // for accept boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; From 39300a5bbf7ca4b761292438455bb4005dee7922 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 28 Nov 2019 17:49:36 -0500 Subject: [PATCH 15/51] removed reseed.i2p.net.in --- .../reseed/reseedi2pnetin_at_mail.i2p.crt | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 contrib/certificates/reseed/reseedi2pnetin_at_mail.i2p.crt diff --git a/contrib/certificates/reseed/reseedi2pnetin_at_mail.i2p.crt b/contrib/certificates/reseed/reseedi2pnetin_at_mail.i2p.crt deleted file mode 100644 index b71696a3..00000000 --- a/contrib/certificates/reseed/reseedi2pnetin_at_mail.i2p.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF3DCCA8SgAwIBAgIQPxUlcrbHX/xdyJ09E36rJzANBgkqhkiG9w0BAQsFADB3 -MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK -ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEgMB4GA1UEAwwX -cmVzZWVkaTJwbmV0aW5AbWFpbC5pMnAwHhcNMTgxMjA3MTYzNDIxWhcNMjgxMjA3 -MTYzNDIxWjB3MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhY -MR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEg -MB4GA1UEAwwXcmVzZWVkaTJwbmV0aW5AbWFpbC5pMnAwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQC912NDk6x85uqB4gyQQcded0RVrbWehWOanDRv7kC3 -92jeziPbeMtqrLsfU1MdDtQiGijpNkQ/IIitPw+6vJAIh82gyOUZvsn2XOyb/Fz0 -Fu8OrDghwl39yK8kwtqCFw3VAgafgKxz2oRge9mxFBECi50vYEPIBwNhr4yc/opu -wWUmzmRyX4gD7vKmRU6ZTwX4LXnwdl+5VbW3updcZKsDuTnKvC9FGhDRR9kIk2G9 -43sLN263nCYPykP7DaB1cUdi1vDEMw5dot+eu16qTIbuypEvYNvbB/9FyCQllm1h -vBbSku3IYpcnRPmoeyhoR/MmCySRbK5R4SrSsVD1YBpwxgn0Q4+fzEgFzT9P4oez -HkDGKVP2HdgmXx9j36fEqqvjqzRleWDwEWwIZVRLCFO+hhhT3JAjnNGJTWv1SQGB -8tz9nyYTJuhvyHE/CO5owFeCdeOGMq2KPge9w34T+mvewTEEhGU8yRAt8Xp8s5Y9 -RCUGvuQ79+edRtj7FJg7yVB8pAQ+VB9msNQvzrTnPYC9Wo7chJhBiraMiIabzIhC -f34Gg9lkX1N0dVND5rnZWwzBM6JhNG1iZZCRHVPnXdZRixUlqmFpCP/eekshksj/ -6UP/WeGA6X4HyEsC6QEf7eMhcHYjyyTzYagKrwCHg77fmIjF8rmpP2LqWSQW8bDD -uQIDAQABo2QwYjAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIG -CCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wIAYDVR0OBBkEF3Jlc2VlZGkycG5l -dGluQG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQCWpXs6iuTy/w2R7q7Ua6vl -JYZwbQ+czk5ydzkBgcNkMMMNRT7sZR9xYvV+ftiL4bFQP/3ZJyo7cYz2Q6+M3oAm -YDcZWBkLUVihSlMxhWwmeFTKV2EL+bzwY1V/cy7wgukKnFIes75dLP/v25jgjdlw -Xe6R+fQM0EoHeVzzrWk/qYp6oEwtQXfZnUu/Bf45hRnnHBzzh1wCql41vbEs3Niq -+SVwY1wLT0yC1L8HqjCLX1/L5PAXxbvEGzwnXSkLKK4bPxdmVDZvS9uzXrWmTbNi -HpKIFnOif16zSgyeaOM7HETIJuVzgooUMtt+Vsr1VGdtm6K7I9J5C+rX/ckU8oaX -UjmzhWXudN0VTslogsKUCV6xG2CskeE3wnuT8HYXz9NMw6c/kIGH4hY7LcfU8Teu -QjSy2RRvy6InmZNV5sY9lzzO6romEycSoUlpCa3Ltb/5KKoYZFTsXr8suqJk89lC -e+TVMHqOZdLK/usqQDcafLypHpw9SH2Tg4jrzV/zLqacbjx6bZD5IrpY0Gf7BXg/ -pikwyA9c490G6ZcWrSEP8bzh6LL2rA2AwxaeJJNVyLHCSLrn/7DezM5J/qhd90Qg -kcZGJrUOCSWl6mDvUZn5XiQ955XwOnZQ+wsM85B3CVX22x5bp0SYWHCQBPnthPwP -Q5DD3jExbpwG5n35HEcHYw== ------END CERTIFICATE----- From 29f0e10411aba79d68fdf80fb0fd67b8b101cfa1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Dec 2019 15:37:24 -0500 Subject: [PATCH 16/51] Elligator added --- build/CMakeLists.txt | 1 + libi2pd/Elligator.cpp | 30 ++++++++++++++++++++++++++++++ libi2pd/Elligator.h | 25 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 libi2pd/Elligator.cpp create mode 100644 libi2pd/Elligator.h diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 949f6a46..a9cf3a83 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -82,6 +82,7 @@ set (LIBI2PD_SRC "${LIBI2PD_SRC_DIR}/Ed25519.cpp" "${LIBI2PD_SRC_DIR}/NTCP2.cpp" "${LIBI2PD_SRC_DIR}/Blinding.cpp" + "${LIBI2PD_SRC_DIR}/Elligator.cpp" ) if (WITH_WEBSOCKETS) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp new file mode 100644 index 00000000..cc49adbf --- /dev/null +++ b/libi2pd/Elligator.cpp @@ -0,0 +1,30 @@ +#include "Elligator.h" + +namespace i2p +{ +namespace crypto +{ + Elligator2::Elligator2 () + { + } + + Elligator2::~Elligator2 () + { + } + + static std::unique_ptr g_Elligator; + std::unique_ptr& GetElligator () + { + if (!g_Elligator) + { + auto el = new Elligator2(); + if (!g_Elligator) // make sure it was not created already + g_Elligator.reset (el); + else + delete el; + } + return g_Elligator; + } +} +} + diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h new file mode 100644 index 00000000..7993ccb9 --- /dev/null +++ b/libi2pd/Elligator.h @@ -0,0 +1,25 @@ +#ifndef ELLIGATOR_H__ +#define ELLIGATOR_H__ + +#include + +namespace i2p +{ +namespace crypto +{ + + class Elligator2 + { + public: + + Elligator2 (); + ~Elligator2 (); + }; + + std::unique_ptr& GetElligator (); +} +} + +#endif + + From 5fa2485a7dc03b856b1dd942bd4a6757b5237901 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Dec 2019 17:27:16 -0500 Subject: [PATCH 17/51] removed reseed.i2p.net.in --- libi2pd/Config.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index e6007d5f..e2f4bdd0 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -192,7 +192,6 @@ namespace config { "https://netdb.i2p2.no/," // "https://us.reseed.i2p2.no:444/," // mamoth's shit // "https://uk.reseed.i2p2.no:444/," // mamoth's shit - "https://reseed.i2p.net.in/," "https://download.xxlspeed.com/," "https://reseed-fr.i2pd.xyz/," "https://reseed.memcpy.io/," From df1aa52e087135a25602ed2935fe8a785ff7cd21 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Dec 2019 16:03:11 -0500 Subject: [PATCH 18/51] Elligator's encode --- libi2pd/Elligator.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++ libi2pd/Elligator.h | 8 +++++ 2 files changed, 76 insertions(+) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index cc49adbf..cc38672a 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -1,15 +1,83 @@ +#include "Crypto.h" #include "Elligator.h" namespace i2p { namespace crypto { + static const uint8_t p_[32]= + { + 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f + }; + + static const uint8_t n1_[32] = + { + 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f + }; + + static const uint8_t n2_[32] = + { + 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f + }; + + static const uint8_t A_[32] = + { + 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + static const uint8_t u_[32] = + { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + #define decode_bytes(x) { x = BN_new (); BN_bin2bn (x##_, 32, x); } Elligator2::Elligator2 () { + decode_bytes (p); + decode_bytes (n1); + decode_bytes (n2); + decode_bytes (A); + decode_bytes (u); + + BN_CTX * ctx = BN_CTX_new (); + BN_mod_inverse (iu, u, p, ctx); + BN_CTX_free (ctx); } Elligator2::~Elligator2 () { + BN_free (p); + BN_free (n1); + BN_free (n2); + BN_free (A); + } + + void Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const + { + BN_CTX * ctx = BN_CTX_new (); + BN_CTX_start (ctx); + + BIGNUM * a = BN_CTX_get (ctx); BN_bin2bn (key, 32, a); + BIGNUM * b = BN_CTX_get (ctx); + BN_add (a, A, b); + BIGNUM * c = BN_CTX_get (ctx); + BN_mod_exp (c, b, n2, p, ctx); + BN_mod_mul (b, c, a, p, ctx); + BN_sub (b, p, b); + + //BN_mod_exp (c, b, n2, p, ctx); + + BN_mod_mul (c, b, iu, p, ctx); + // TODO: + bn2buf (b, encoded, 32); + + BN_CTX_end (ctx); + BN_CTX_free (ctx); } static std::unique_ptr g_Elligator; diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h index 7993ccb9..09f46888 100644 --- a/libi2pd/Elligator.h +++ b/libi2pd/Elligator.h @@ -1,7 +1,9 @@ #ifndef ELLIGATOR_H__ #define ELLIGATOR_H__ +#include #include +#include namespace i2p { @@ -14,6 +16,12 @@ namespace crypto Elligator2 (); ~Elligator2 (); + + void Encode (const uint8_t * key, uint8_t * encoded) const; + + private: + + BIGNUM * p, * n1, * n2, * A, * u, * iu; }; std::unique_ptr& GetElligator (); From 28779002335b9758ef9a3bf23706f1b96c65f32d Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Dec 2019 16:13:59 -0500 Subject: [PATCH 19/51] use 486662 for A --- libi2pd/Elligator.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index cc38672a..213345b9 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -23,11 +23,6 @@ namespace crypto 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }; - static const uint8_t A_[32] = - { - 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; static const uint8_t u_[32] = { @@ -35,17 +30,18 @@ namespace crypto 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - #define decode_bytes(x) { x = BN_new (); BN_bin2bn (x##_, 32, x); } + #define decode_bytes(x) { x = BN_new (); BN_bin2bn (x##_, 32, x); } // TODO: endianess Elligator2::Elligator2 () { decode_bytes (p); decode_bytes (n1); - decode_bytes (n2); - decode_bytes (A); + decode_bytes (n2); decode_bytes (u); + A = BN_new (); BN_set_word (A, 486662); + BN_CTX * ctx = BN_CTX_new (); - BN_mod_inverse (iu, u, p, ctx); + iu = BN_new (); BN_mod_inverse (iu, u, p, ctx); BN_CTX_free (ctx); } From e6956d9bb044e92dfcd0a1b59e79353d8db09985 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 6 Dec 2019 14:54:15 -0500 Subject: [PATCH 20/51] calculate constants --- libi2pd/Elligator.cpp | 70 ++++++++++++++++++++++++------------------- libi2pd/Elligator.h | 2 +- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index 213345b9..1ca48ca6 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -5,52 +5,60 @@ namespace i2p { namespace crypto { - static const uint8_t p_[32]= - { - 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f - }; - - static const uint8_t n1_[32] = - { - 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f - }; - - static const uint8_t n2_[32] = - { - 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f - }; - - static const uint8_t u_[32] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - #define decode_bytes(x) { x = BN_new (); BN_bin2bn (x##_, 32, x); } // TODO: endianess + Elligator2::Elligator2 () { - decode_bytes (p); - decode_bytes (n1); - decode_bytes (n2); - decode_bytes (u); - - A = BN_new (); BN_set_word (A, 486662); + // TODO: share with Ed22519 + p = BN_new (); + // 2^255-19 + BN_set_bit (p, 255); // 2^255 + BN_sub_word (p, 19); + p38 = BN_dup (p); BN_add_word (p38, 3); BN_div_word (p38, 8); // (p+3)/8 + p12 = BN_dup (p); BN_sub_word (p12, 1); BN_div_word (p12, 2); // (p-1)/2 + n1 = BN_dup (p); BN_sub_word (n1, 1); // p-1 + n2 = BN_dup (p); BN_sub_word (n2, 2); // p-2 - BN_CTX * ctx = BN_CTX_new (); + A = BN_new (); BN_set_word (A, 486662); + nA = BN_new (); BN_sub (nA, p, A); + + BN_CTX * ctx = BN_CTX_new (); + // calculate sqrt(-1) + sqrtn1 = BN_new (); + BN_mod_exp (sqrtn1, n1, p38, p, ctx); // (-1)^((p+3)/8) + auto p14 = BN_dup (p); BN_sub_word (p14, 1); BN_div_word (p14, 4); // (p-1)/4 + auto tmp = BN_new (); BN_set_word (tmp, 2); + BN_mod_exp (tmp, tmp, p14, p, ctx); // 2^((p-1)/4 + BN_mod_mul (sqrtn1, tmp, sqrtn1, p, ctx); // 2^((p-1)/4 * (-1)^((p+3)/8) + BN_free (p14); + + u = BN_new (); BN_bin2bn (u_, 32, u); // TODO: endianess iu = BN_new (); BN_mod_inverse (iu, u, p, ctx); + + // calculate d = -121665*inv(121666) + d = BN_new (); + BN_set_word (tmp, 121666); + BN_mod_inverse (tmp, tmp, p, ctx); + BN_set_word (d, 121665); + BN_set_negative (d, 1); + BN_mod_mul (d, d, tmp, p, ctx); + BN_free (tmp); + //printf ("%s\n", BN_bn2hex (d)); + BN_CTX_free (ctx); } Elligator2::~Elligator2 () { - BN_free (p); - BN_free (n1); - BN_free (n2); - BN_free (A); + BN_free (p); BN_free (p38); BN_free (p12); + BN_free (n1);BN_free (n2); BN_free (sqrtn1); + BN_free (A); BN_free (nA); + BN_free (u); BN_free (iu); BN_free (d); } void Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h index 09f46888..da1c2f83 100644 --- a/libi2pd/Elligator.h +++ b/libi2pd/Elligator.h @@ -21,7 +21,7 @@ namespace crypto private: - BIGNUM * p, * n1, * n2, * A, * u, * iu; + BIGNUM * p, * n1, * n2, * p38, * p12, * sqrtn1, * A, * nA, * u, * iu, * d; }; std::unique_ptr& GetElligator (); From 934f1269f53ac6a12a56d54e49e9695f088eb5c5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 7 Dec 2019 00:59:33 +0000 Subject: [PATCH 21/51] appveyor: replace deprecated --force in msys2 --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index fe827ec5..5f314fa6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,9 +18,9 @@ environment: install: - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc" -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force" +- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --overwrite" -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force" +- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --overwrite" - if "%MSYSTEM%" == "MINGW64" ( c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc" From 72492e33a04f462af5b29402537584655729a6df Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 7 Dec 2019 01:02:23 +0000 Subject: [PATCH 22/51] appveyor: drop msys2 overwrite --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5f314fa6..f6eee9ab 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,9 +18,9 @@ environment: install: - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc" -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --overwrite" +- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --overwrite" +- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" - if "%MSYSTEM%" == "MINGW64" ( c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc" From 95df3e4b399fd939304c29f0cb3bdc934068c123 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 6 Dec 2019 20:29:03 -0500 Subject: [PATCH 23/51] encode key --- libi2pd/Elligator.cpp | 73 +++++++++++++++++++------------------------ libi2pd/Elligator.h | 6 +++- 2 files changed, 37 insertions(+), 42 deletions(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index 1ca48ca6..e0f12a85 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -5,12 +5,6 @@ namespace i2p { namespace crypto { - static const uint8_t u_[32] = - { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - Elligator2::Elligator2 () { @@ -21,44 +15,29 @@ namespace crypto BN_sub_word (p, 19); p38 = BN_dup (p); BN_add_word (p38, 3); BN_div_word (p38, 8); // (p+3)/8 p12 = BN_dup (p); BN_sub_word (p12, 1); BN_div_word (p12, 2); // (p-1)/2 - n1 = BN_dup (p); BN_sub_word (n1, 1); // p-1 - n2 = BN_dup (p); BN_sub_word (n2, 2); // p-2 + p14 = BN_dup (p); BN_sub_word (p14, 1); BN_div_word (p14, 4); // (p-1)/4 - A = BN_new (); BN_set_word (A, 486662); + auto A = BN_new (); BN_set_word (A, 486662); nA = BN_new (); BN_sub (nA, p, A); BN_CTX * ctx = BN_CTX_new (); // calculate sqrt(-1) sqrtn1 = BN_new (); - BN_mod_exp (sqrtn1, n1, p38, p, ctx); // (-1)^((p+3)/8) - auto p14 = BN_dup (p); BN_sub_word (p14, 1); BN_div_word (p14, 4); // (p-1)/4 - auto tmp = BN_new (); BN_set_word (tmp, 2); - BN_mod_exp (tmp, tmp, p14, p, ctx); // 2^((p-1)/4 - BN_mod_mul (sqrtn1, tmp, sqrtn1, p, ctx); // 2^((p-1)/4 * (-1)^((p+3)/8) - BN_free (p14); + BN_set_word (sqrtn1, 2); + BN_mod_exp (sqrtn1, sqrtn1, p14, p, ctx); // 2^((p-1)/4 - u = BN_new (); BN_bin2bn (u_, 32, u); // TODO: endianess + u = BN_new (); BN_set_word (u, 2); iu = BN_new (); BN_mod_inverse (iu, u, p, ctx); - - // calculate d = -121665*inv(121666) - d = BN_new (); - BN_set_word (tmp, 121666); - BN_mod_inverse (tmp, tmp, p, ctx); - BN_set_word (d, 121665); - BN_set_negative (d, 1); - BN_mod_mul (d, d, tmp, p, ctx); - BN_free (tmp); - //printf ("%s\n", BN_bn2hex (d)); + //printf ("%s\n", BN_bn2hex (iu)); BN_CTX_free (ctx); } Elligator2::~Elligator2 () { - BN_free (p); BN_free (p38); BN_free (p12); - BN_free (n1);BN_free (n2); BN_free (sqrtn1); - BN_free (A); BN_free (nA); - BN_free (u); BN_free (iu); BN_free (d); + BN_free (p); BN_free (p38); BN_free (p12); BN_free (p14); + BN_free (sqrtn1); BN_free (A); BN_free (nA); + BN_free (u); BN_free (iu); } void Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const @@ -66,24 +45,36 @@ namespace crypto BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); - BIGNUM * a = BN_CTX_get (ctx); BN_bin2bn (key, 32, a); - BIGNUM * b = BN_CTX_get (ctx); - BN_add (a, A, b); - BIGNUM * c = BN_CTX_get (ctx); - BN_mod_exp (c, b, n2, p, ctx); - BN_mod_mul (b, c, a, p, ctx); - BN_sub (b, p, b); + BIGNUM * x = BN_CTX_get (ctx); BN_bin2bn (key, 32, x); + BIGNUM * xA = BN_CTX_get (ctx); BN_add (xA, x, A); // x + A + BN_sub (xA, p, xA); // p - (x + A) - //BN_mod_exp (c, b, n2, p, ctx); + BIGNUM * r = BN_CTX_get (ctx); + BN_mod_inverse (r, xA, p, ctx); + BN_mod_mul (r, r, x, p, ctx); + BN_mod_mul (r, r, iu, p, ctx); - BN_mod_mul (c, b, iu, p, ctx); - // TODO: - bn2buf (b, encoded, 32); + SquareRoot (r, r, ctx); + bn2buf (r, encoded, 32); BN_CTX_end (ctx); BN_CTX_free (ctx); } + void Elligator2::SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const + { + BIGNUM * t = BN_CTX_get (ctx); + BN_mod_exp (t, x, p14, p, ctx); // t = x^((p-1)/4) + BN_mod_exp (r, x, p38, p, ctx); // r = x^((p+3)/8) + BN_add_word (t, 1); + + if (!BN_cmp (t, p)) + BN_mod_mul (r, r, sqrtn1, p, ctx); + + if (BN_cmp (r, p12) > 0) // r > (p-1)/2 + BN_sub (r, p, r); + } + static std::unique_ptr g_Elligator; std::unique_ptr& GetElligator () { diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h index da1c2f83..7d2d2f15 100644 --- a/libi2pd/Elligator.h +++ b/libi2pd/Elligator.h @@ -19,9 +19,13 @@ namespace crypto void Encode (const uint8_t * key, uint8_t * encoded) const; + private: + + void SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const; + private: - BIGNUM * p, * n1, * n2, * p38, * p12, * sqrtn1, * A, * nA, * u, * iu, * d; + BIGNUM * p, * p38, * p12, * p14, * sqrtn1, * A, * nA, * u, * iu; }; std::unique_ptr& GetElligator (); From 3100d587d1100a97a0145f8293f5d5393029e089 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 9 Dec 2019 13:23:17 -0500 Subject: [PATCH 24/51] use d%q --- libi2pd/Ed25519.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Ed25519.cpp b/libi2pd/Ed25519.cpp index 1096b3b7..69fec4e8 100644 --- a/libi2pd/Ed25519.cpp +++ b/libi2pd/Ed25519.cpp @@ -31,7 +31,7 @@ namespace crypto BN_mod_inverse (tmp, tmp, q, ctx); BN_set_word (d, 121665); BN_set_negative (d, 1); - BN_mul (d, d, tmp, ctx); + BN_mod_mul (d, d, tmp, q, ctx); // 2^((q-1)/4) I = BN_new (); From c38298c06e42ae955d893f55cfa7ffe25c605eeb Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 9 Dec 2019 16:11:46 -0500 Subject: [PATCH 25/51] Elligator decode --- libi2pd/Elligator.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++- libi2pd/Elligator.h | 1 + 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index e0f12a85..1f67d641 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -45,7 +45,14 @@ namespace crypto BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); - BIGNUM * x = BN_CTX_get (ctx); BN_bin2bn (key, 32, x); + uint8_t key1[32]; + for (size_t i = 0; i < 16; i++) // from Little Endian + { + key1[i] = key[15 - i]; + key1[15 - i] = key[i]; + } + + BIGNUM * x = BN_CTX_get (ctx); BN_bin2bn (key1, 32, x); BIGNUM * xA = BN_CTX_get (ctx); BN_add (xA, x, A); // x + A BN_sub (xA, p, xA); // p - (x + A) @@ -56,6 +63,64 @@ namespace crypto SquareRoot (r, r, ctx); bn2buf (r, encoded, 32); + + for (size_t i = 0; i < 16; i++) // To Little Endian + { + uint8_t tmp = encoded[i]; + encoded[i] = encoded[15 - i]; + encoded[15 - i] = tmp; + } + + BN_CTX_end (ctx); + BN_CTX_free (ctx); + } + + void Elligator2::Decode (const uint8_t * encoded, uint8_t * key) const + { + BN_CTX * ctx = BN_CTX_new (); + BN_CTX_start (ctx); + + uint8_t encoded1[32]; + for (size_t i = 0; i < 16; i++) // from Little Endian + { + encoded1[i] = encoded[15 - i]; + encoded1[15 - i] = encoded[i]; + } + + BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r); + + // v=-A/(1+u*r^2) + BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx); + BN_mod_mul (v, v, u, p, ctx); + BN_add_word (v, 1); + BN_mod_inverse (v, v, p, ctx); + BN_mod_mul (v, v, nA, p, ctx); + + BIGNUM * vpA = BN_CTX_get (ctx); + BN_add (vpA, v, A); // v + A + // t = v^3+A*v^2+v = v^2*(v+A)+v + BIGNUM * t = BN_CTX_get (ctx); BN_mod_sqr (t, v, p, ctx); + BN_mod_mul (t, t, vpA, p, ctx); + BN_mod_add (t, t, v, p, ctx); + + int legendre = 0; // TODO: + BIGNUM * x = BN_CTX_get (ctx); + if (legendre == 1) + BN_copy (x, v); + else + { + BN_sub (x, p, v); + BN_mod_sub (x, x, A, p, ctx); + } + + bn2buf (x, key, 32); + for (size_t i = 0; i < 16; i++) // To Little Endian + { + uint8_t tmp = key[i]; + key[i] = key[15 - i]; + key[15 - i] = tmp; + } + BN_CTX_end (ctx); BN_CTX_free (ctx); diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h index 7d2d2f15..f2a1c805 100644 --- a/libi2pd/Elligator.h +++ b/libi2pd/Elligator.h @@ -18,6 +18,7 @@ namespace crypto ~Elligator2 (); void Encode (const uint8_t * key, uint8_t * encoded) const; + void Decode (const uint8_t * encoded, uint8_t * key) const; private: From 8d7490525716809c30c2a433dd2e6cfd44f079bc Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2019 10:44:19 -0500 Subject: [PATCH 26/51] 0.9.44 --- libi2pd/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/version.h b/libi2pd/version.h index 3b69a658..2e876fdb 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -21,7 +21,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 43 +#define I2P_VERSION_MICRO 44 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From 7417867d0f974594ebbd56071a914ec46cfb1bbf Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2019 10:45:08 -0500 Subject: [PATCH 27/51] implemented Legendre --- libi2pd/Elligator.cpp | 114 ++++++++++++++++++++++++++---------------- libi2pd/Elligator.h | 5 +- 2 files changed, 75 insertions(+), 44 deletions(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index 1f67d641..07711ae0 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -40,8 +40,9 @@ namespace crypto BN_free (u); BN_free (iu); } - void Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const + bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const { + bool ret = true; BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); @@ -56,27 +57,38 @@ namespace crypto BIGNUM * xA = BN_CTX_get (ctx); BN_add (xA, x, A); // x + A BN_sub (xA, p, xA); // p - (x + A) - BIGNUM * r = BN_CTX_get (ctx); - BN_mod_inverse (r, xA, p, ctx); - BN_mod_mul (r, r, x, p, ctx); - BN_mod_mul (r, r, iu, p, ctx); + BIGNUM * uxxA = BN_CTX_get (ctx); // u*x*xA + BN_mod_mul (uxxA, u, x, p, ctx); + BN_mod_mul (uxxA, uxxA, xA, p, ctx); - SquareRoot (r, r, ctx); - bn2buf (r, encoded, 32); - - for (size_t i = 0; i < 16; i++) // To Little Endian + if (Legendre (uxxA, ctx) != -1) { - uint8_t tmp = encoded[i]; - encoded[i] = encoded[15 - i]; - encoded[15 - i] = tmp; + BIGNUM * r = BN_CTX_get (ctx); + BN_mod_inverse (r, xA, p, ctx); + BN_mod_mul (r, r, x, p, ctx); + BN_mod_mul (r, r, iu, p, ctx); + + SquareRoot (r, r, ctx); + bn2buf (r, encoded, 32); + + for (size_t i = 0; i < 16; i++) // To Little Endian + { + uint8_t tmp = encoded[i]; + encoded[i] = encoded[15 - i]; + encoded[15 - i] = tmp; + } } + else + ret = false; BN_CTX_end (ctx); BN_CTX_free (ctx); + return ret; } - void Elligator2::Decode (const uint8_t * encoded, uint8_t * key) const + bool Elligator2::Decode (const uint8_t * encoded, uint8_t * key) const { + bool ret = true; BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); @@ -89,41 +101,47 @@ namespace crypto BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r); - // v=-A/(1+u*r^2) - BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx); - BN_mod_mul (v, v, u, p, ctx); - BN_add_word (v, 1); - BN_mod_inverse (v, v, p, ctx); - BN_mod_mul (v, v, nA, p, ctx); - - BIGNUM * vpA = BN_CTX_get (ctx); - BN_add (vpA, v, A); // v + A - // t = v^3+A*v^2+v = v^2*(v+A)+v - BIGNUM * t = BN_CTX_get (ctx); BN_mod_sqr (t, v, p, ctx); - BN_mod_mul (t, t, vpA, p, ctx); - BN_mod_add (t, t, v, p, ctx); - - int legendre = 0; // TODO: - BIGNUM * x = BN_CTX_get (ctx); - if (legendre == 1) - BN_copy (x, v); - else + if (BN_cmp (r, p12) < 0) // r < (p-1)/2 { - BN_sub (x, p, v); - BN_mod_sub (x, x, A, p, ctx); - } + // v = -A/(1+u*r^2) + BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx); + BN_mod_mul (v, v, u, p, ctx); + BN_add_word (v, 1); + BN_mod_inverse (v, v, p, ctx); + BN_mod_mul (v, v, nA, p, ctx); + + BIGNUM * vpA = BN_CTX_get (ctx); + BN_add (vpA, v, A); // v + A + // t = v^3+A*v^2+v = v^2*(v+A)+v + BIGNUM * t = BN_CTX_get (ctx); BN_mod_sqr (t, v, p, ctx); + BN_mod_mul (t, t, vpA, p, ctx); + BN_mod_add (t, t, v, p, ctx); + + int legendre = Legendre (t, ctx); + BIGNUM * x = BN_CTX_get (ctx); + if (legendre == 1) + BN_copy (x, v); + else + { + BN_sub (x, p, v); + BN_mod_sub (x, x, A, p, ctx); + } - bn2buf (x, key, 32); - for (size_t i = 0; i < 16; i++) // To Little Endian - { - uint8_t tmp = key[i]; - key[i] = key[15 - i]; - key[15 - i] = tmp; + bn2buf (x, key, 32); + for (size_t i = 0; i < 16; i++) // To Little Endian + { + uint8_t tmp = key[i]; + key[i] = key[15 - i]; + key[15 - i] = tmp; + } } - + else + ret = false; BN_CTX_end (ctx); BN_CTX_free (ctx); + + return ret; } void Elligator2::SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const @@ -140,6 +158,18 @@ namespace crypto BN_sub (r, p, r); } + int Elligator2::Legendre (const BIGNUM * a, BN_CTX * ctx) const + { + // assume a < p, so don't check for a % p = 0 + BIGNUM * r = BN_CTX_get (ctx); + BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p + if (BN_is_word(r, 1)) + return 1; + else if (BN_is_zero(r)) + return 0; + return -1; + } + static std::unique_ptr g_Elligator; std::unique_ptr& GetElligator () { diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h index f2a1c805..6f9eaf2a 100644 --- a/libi2pd/Elligator.h +++ b/libi2pd/Elligator.h @@ -17,12 +17,13 @@ namespace crypto Elligator2 (); ~Elligator2 (); - void Encode (const uint8_t * key, uint8_t * encoded) const; - void Decode (const uint8_t * encoded, uint8_t * key) const; + bool Encode (const uint8_t * key, uint8_t * encoded) const; + bool Decode (const uint8_t * encoded, uint8_t * key) const; private: void SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const; + int Legendre (const BIGNUM * a, BN_CTX * ctx) const; // a/p private: From d7b819267fccc817ff0005790aed04f75162f1f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2019 10:53:39 -0500 Subject: [PATCH 28/51] check a for 0 in Legendre --- libi2pd/Elligator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index 07711ae0..febece03 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -160,7 +160,8 @@ namespace crypto int Elligator2::Legendre (const BIGNUM * a, BN_CTX * ctx) const { - // assume a < p, so don't check for a % p = 0 + // assume a < p, so don't check for a % p = 0, but a = 0 only + if (BN_is_zero(a)) return 0; BIGNUM * r = BN_CTX_get (ctx); BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p if (BN_is_word(r, 1)) From 5faf84c73206be3e9f2609dc6f381aac3be3c2e4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2019 12:51:39 -0500 Subject: [PATCH 29/51] correct conversion from Little Endian --- libi2pd/Elligator.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index febece03..9be0a610 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -17,8 +17,8 @@ namespace crypto p12 = BN_dup (p); BN_sub_word (p12, 1); BN_div_word (p12, 2); // (p-1)/2 p14 = BN_dup (p); BN_sub_word (p14, 1); BN_div_word (p14, 4); // (p-1)/4 - auto A = BN_new (); BN_set_word (A, 486662); - nA = BN_new (); BN_sub (nA, p, A); + A = BN_new (); BN_set_word (A, 486662); + nA = BN_new (); BN_sub (nA, p, A); BN_CTX * ctx = BN_CTX_new (); // calculate sqrt(-1) @@ -28,8 +28,7 @@ namespace crypto u = BN_new (); BN_set_word (u, 2); iu = BN_new (); BN_mod_inverse (iu, u, p, ctx); - //printf ("%s\n", BN_bn2hex (iu)); - + BN_CTX_free (ctx); } @@ -49,8 +48,8 @@ namespace crypto uint8_t key1[32]; for (size_t i = 0; i < 16; i++) // from Little Endian { - key1[i] = key[15 - i]; - key1[15 - i] = key[i]; + key1[i] = key[31 - i]; + key1[31 - i] = key[i]; } BIGNUM * x = BN_CTX_get (ctx); BN_bin2bn (key1, 32, x); @@ -62,7 +61,7 @@ namespace crypto BN_mod_mul (uxxA, uxxA, xA, p, ctx); if (Legendre (uxxA, ctx) != -1) - { + { BIGNUM * r = BN_CTX_get (ctx); BN_mod_inverse (r, xA, p, ctx); BN_mod_mul (r, r, x, p, ctx); @@ -74,8 +73,8 @@ namespace crypto for (size_t i = 0; i < 16; i++) // To Little Endian { uint8_t tmp = encoded[i]; - encoded[i] = encoded[15 - i]; - encoded[15 - i] = tmp; + encoded[i] = encoded[31 - i]; + encoded[31 - i] = tmp; } } else @@ -95,8 +94,8 @@ namespace crypto uint8_t encoded1[32]; for (size_t i = 0; i < 16; i++) // from Little Endian { - encoded1[i] = encoded[15 - i]; - encoded1[15 - i] = encoded[i]; + encoded1[i] = encoded[31 - i]; + encoded1[31 - i] = encoded[i]; } BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r); @@ -131,8 +130,8 @@ namespace crypto for (size_t i = 0; i < 16; i++) // To Little Endian { uint8_t tmp = key[i]; - key[i] = key[15 - i]; - key[15 - i] = tmp; + key[i] = key[31 - i]; + key[31 - i] = tmp; } } else From 4d7b86ca266df7166e0cf9d496e58f5028b6db5d Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2019 13:20:23 -0500 Subject: [PATCH 30/51] elligator test added --- tests/Makefile | 5 +++- tests/test-elligator.cpp | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/test-elligator.cpp diff --git a/tests/Makefile b/tests/Makefile index 2a12472a..4c80c37c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,6 @@ CXXFLAGS += -Wall -Wextra -pedantic -O0 -g -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -I../libi2pd/ -pthread -Wl,--unresolved-symbols=ignore-in-object-files -TESTS = test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding +TESTS = test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding test-elligator all: $(TESTS) run @@ -25,6 +25,9 @@ test-aeadchacha20poly1305: ../libi2pd/Crypto.cpp ../libi2pd/ChaCha20.cpp ../libi test-blinding: ../libi2pd/Crypto.cpp ../libi2pd/Blinding.cpp ../libi2pd/Ed25519.cpp ../libi2pd/I2PEndian.cpp ../libi2pd/Log.cpp ../libi2pd/util.cpp ../libi2pd/Identity.cpp ../libi2pd/Signature.cpp ../libi2pd/Timestamp.cpp test-blinding.cpp $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system +test-elligator: ../libi2pd/Elligator.cpp ../libi2pd/Crypto.cpp test-elligator.cpp + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^ -lcrypto -lssl -lboost_system + run: $(TESTS) @for TEST in $(TESTS); do ./$$TEST ; done diff --git a/tests/test-elligator.cpp b/tests/test-elligator.cpp new file mode 100644 index 00000000..ec9ccdbc --- /dev/null +++ b/tests/test-elligator.cpp @@ -0,0 +1,56 @@ +#include +#include +#include + +#include "Elligator.h" + +const uint8_t key[32] = +{ + 0x33, 0x95, 0x19, 0x64, 0x00, 0x3c, 0x94, 0x08, 0x78, 0x06, 0x3c, 0xcf, 0xd0, 0x34, 0x8a, 0xf4, + 0x21, 0x50, 0xca, 0x16, 0xd2, 0x64, 0x6f, 0x2c, 0x58, 0x56, 0xe8, 0x33, 0x83, 0x77, 0xd8, 0x80 +}; + +const uint8_t encoded_key[32] = +{ + 0x28, 0x20, 0xb6, 0xb2, 0x41, 0xe0, 0xf6, 0x8a, 0x6c, 0x4a, 0x7f, 0xee, 0x3d, 0x97, 0x82, 0x28, + 0xef, 0x3a, 0xe4, 0x55, 0x33, 0xcd, 0x41, 0x0a, 0xa9, 0x1a, 0x41, 0x53, 0x31, 0xd8, 0x61, 0x2d +}; + +const uint8_t encoded1[32] = +{ + 0xe7, 0x35, 0x07, 0xd3, 0x8b, 0xae, 0x63, 0x99, 0x2b, 0x3f, 0x57, 0xaa, 0xc4, 0x8c, 0x0a, 0xbc, + 0x14, 0x50, 0x95, 0x89, 0x28, 0x84, 0x57, 0x99, 0x5a, 0x2b, 0x4c, 0xa3, 0x49, 0x0a, 0xa2, 0x07 +}; + +const uint8_t key1[32] = +{ + 0x1e, 0x8a, 0xff, 0xfe, 0xd6, 0xbf, 0x53, 0xfe, 0x27, 0x1a, 0xd5, 0x72, 0x47, 0x32, 0x62, 0xde, + 0xd8, 0xfa, 0xec, 0x68, 0xe5, 0xe6, 0x7e, 0xf4, 0x5e, 0xbb, 0x82, 0xee, 0xba, 0x52, 0x60, 0x4f +}; + +const uint8_t encoded2[32] = +{ + 0x95, 0xa1, 0x60, 0x19, 0x04, 0x1d, 0xbe, 0xfe, 0xd9, 0x83, 0x20, 0x48, 0xed, 0xe1, 0x19, 0x28, + 0xd9, 0x03, 0x65, 0xf2, 0x4a, 0x38, 0xaa, 0x7a, 0xef, 0x1b, 0x97, 0xe2, 0x39, 0x54, 0x10, 0x1b +}; + +const uint8_t key2[32] = +{ + 0x79, 0x4f, 0x05, 0xba, 0x3e, 0x3a, 0x72, 0x95, 0x80, 0x22, 0x46, 0x8c, 0x88, 0x98, 0x1e, 0x0b, + 0xe5, 0x78, 0x2b, 0xe1, 0xe1, 0x14, 0x5c, 0xe2, 0xc3, 0xc6, 0xfd, 0xe1, 0x6d, 0xed, 0x53, 0x63 +}; + + +int main () +{ + uint8_t buf[32]; + i2p::crypto::Elligator2 el; + // encoding test + el.Encode (key, buf); + assert(memcmp (buf, encoded_key, 32) == 0); + // decoding test + el.Decode (encoded1, buf); + assert(memcmp (buf, key1, 32) == 0); + el.Decode (encoded2, buf); + assert(memcmp (buf, key2, 32) == 0); +} From 36eaaa748c02e43bc2692cbe95aa5e62e4d3b4c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2019 13:40:04 -0500 Subject: [PATCH 31/51] handle case when encoded key is (p-1)/2 --- libi2pd/Elligator.cpp | 2 +- tests/test-elligator.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index 9be0a610..9821afa1 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -100,7 +100,7 @@ namespace crypto BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r); - if (BN_cmp (r, p12) < 0) // r < (p-1)/2 + if (BN_cmp (r, p12) <= 0) // r < (p-1)/2 { // v = -A/(1+u*r^2) BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx); diff --git a/tests/test-elligator.cpp b/tests/test-elligator.cpp index ec9ccdbc..1647c349 100644 --- a/tests/test-elligator.cpp +++ b/tests/test-elligator.cpp @@ -40,6 +40,17 @@ const uint8_t key2[32] = 0xe5, 0x78, 0x2b, 0xe1, 0xe1, 0x14, 0x5c, 0xe2, 0xc3, 0xc6, 0xfd, 0xe1, 0x6d, 0xed, 0x53, 0x63 }; +const uint8_t encoded3[32] = +{ + 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f +}; + +const uint8_t key3[32] = +{ + 0x9c, 0xdb, 0x52, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 +}; int main () { @@ -53,4 +64,6 @@ int main () assert(memcmp (buf, key1, 32) == 0); el.Decode (encoded2, buf); assert(memcmp (buf, key2, 32) == 0); + el.Decode (encoded3, buf); + assert(memcmp (buf, key3, 32) == 0); } From 9ed58e5186f7bef037cf535f16fe0a1c8f48c260 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2019 14:10:12 -0500 Subject: [PATCH 32/51] encode with highY --- libi2pd/Elligator.cpp | 14 +++++++++++--- libi2pd/Elligator.h | 2 +- tests/test-elligator.cpp | 12 ++++++++++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index 9821afa1..b9471512 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -39,7 +39,7 @@ namespace crypto BN_free (u); BN_free (iu); } - bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const + bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY) const { bool ret = true; BN_CTX * ctx = BN_CTX_new (); @@ -63,8 +63,16 @@ namespace crypto if (Legendre (uxxA, ctx) != -1) { BIGNUM * r = BN_CTX_get (ctx); - BN_mod_inverse (r, xA, p, ctx); - BN_mod_mul (r, r, x, p, ctx); + if (highY) + { + BN_mod_inverse (r, x, p, ctx); + BN_mod_mul (r, r, xA, p, ctx); + } + else + { + BN_mod_inverse (r, xA, p, ctx); + BN_mod_mul (r, r, x, p, ctx); + } BN_mod_mul (r, r, iu, p, ctx); SquareRoot (r, r, ctx); diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h index 6f9eaf2a..ca463568 100644 --- a/libi2pd/Elligator.h +++ b/libi2pd/Elligator.h @@ -17,7 +17,7 @@ namespace crypto Elligator2 (); ~Elligator2 (); - bool Encode (const uint8_t * key, uint8_t * encoded) const; + bool Encode (const uint8_t * key, uint8_t * encoded, bool highY = false) const; bool Decode (const uint8_t * encoded, uint8_t * key) const; private: diff --git a/tests/test-elligator.cpp b/tests/test-elligator.cpp index 1647c349..94798e80 100644 --- a/tests/test-elligator.cpp +++ b/tests/test-elligator.cpp @@ -16,6 +16,12 @@ const uint8_t encoded_key[32] = 0xef, 0x3a, 0xe4, 0x55, 0x33, 0xcd, 0x41, 0x0a, 0xa9, 0x1a, 0x41, 0x53, 0x31, 0xd8, 0x61, 0x2d }; +const uint8_t encoded_key_high_y[32] = +{ + 0x3c, 0xfb, 0x87, 0xc4, 0x6c, 0x0b, 0x45, 0x75, 0xca, 0x81, 0x75, 0xe0, 0xed, 0x1c, 0x0a, 0xe9, + 0xda, 0xe7, 0x9d, 0xb7, 0x8d, 0xf8, 0x69, 0x97, 0xc4, 0x84, 0x7b, 0x9f, 0x20, 0xb2, 0x77, 0x18 +}; + const uint8_t encoded1[32] = { 0xe7, 0x35, 0x07, 0xd3, 0x8b, 0xae, 0x63, 0x99, 0x2b, 0x3f, 0x57, 0xaa, 0xc4, 0x8c, 0x0a, 0xbc, @@ -56,10 +62,12 @@ int main () { uint8_t buf[32]; i2p::crypto::Elligator2 el; - // encoding test + // encoding tests el.Encode (key, buf); assert(memcmp (buf, encoded_key, 32) == 0); - // decoding test + el.Encode (key, buf, true); // with highY + assert(memcmp (buf, encoded_key_high_y, 32) == 0); + // decoding tests el.Decode (encoded1, buf); assert(memcmp (buf, key1, 32) == 0); el.Decode (encoded2, buf); From 553d59c32b037cb0d9561100be57c0dde05f6cef Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 11 Dec 2019 13:38:36 -0500 Subject: [PATCH 33/51] decryptor for ECIES-X25519-AEAD-Ratchet --- libi2pd/CryptoKey.cpp | 17 +++++++++++++++++ libi2pd/CryptoKey.h | 19 +++++++++++++++++++ libi2pd/Identity.cpp | 6 ++++++ libi2pd/Identity.h | 1 + 4 files changed, 43 insertions(+) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index 711d4ce6..1c362c3b 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -1,6 +1,7 @@ #include #include "Log.h" #include "Gost.h" +#include "Elligator.h" #include "CryptoKey.h" namespace i2p @@ -146,6 +147,22 @@ namespace crypto BN_free (x); BN_free (y); } + + bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * keyMaterial, BN_CTX * ctx, bool zeroPadding) + { + uint8_t key[32]; + if (!GetElligator ()->Decode (epub, key)) return false; + m_StaticKeys.Agree (key, keyMaterial); + return true; + } + + void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub) + { + X25519Keys k; + k.GenerateKeys (); + k.GetPrivateKey (priv); + memcpy (pub, k.GetPublicKey (), 32); + } } } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 5584b687..c4788959 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -116,6 +116,25 @@ namespace crypto }; void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub); + +// ECIES-X25519-AEAD-Ratchet + + class ECIESX25519AEADRatchetDecryptor: public CryptoKeyDecryptor + { + public: + + ECIESX25519AEADRatchetDecryptor (const uint8_t * priv): m_StaticKeys (priv, nullptr) {}; + ~ECIESX25519AEADRatchetDecryptor () {}; + bool Decrypt (const uint8_t * epub, uint8_t * keyMaterial, BN_CTX * ctx, bool zeroPadding); + // take elligator encoded ephemeral pub (32 bytes), agree with static and return in keyMaterial (32 bytes) + size_t GetPublicKeyLen () const { return 32; }; + + private: + + X25519Keys m_StaticKeys; + }; + + void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub); } } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index f088d3f2..d217f41d 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -674,6 +674,9 @@ namespace data case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: return std::make_shared(key); break; + case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET: + return std::make_shared(key); + break; default: LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType); }; @@ -750,6 +753,9 @@ namespace data case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: i2p::crypto::CreateECIESGOSTR3410RandomKeys (priv, pub); break; + case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET: + i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub); + break; default: LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported"); } diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 72fd14c5..2fecc28a 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -55,6 +55,7 @@ namespace data const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1; + const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET = 4; const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST = 65280; // TODO: remove later const uint16_t CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES From 521fb83e382d0aedd2b3f2db1320ff1016ebbe7b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Dec 2019 16:18:40 -0500 Subject: [PATCH 34/51] initial code for ECIES-X25519-AEAD-Ratchet KDF --- libi2pd/CryptoKey.cpp | 7 ++----- libi2pd/CryptoKey.h | 4 ++-- libi2pd/Destination.h | 2 ++ libi2pd/Garlic.cpp | 36 ++++++++++++++++++++++++++++++++++++ libi2pd/Garlic.h | 3 +++ libi2pd/Identity.h | 2 ++ 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index 1c362c3b..f247f37e 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -1,7 +1,6 @@ #include #include "Log.h" #include "Gost.h" -#include "Elligator.h" #include "CryptoKey.h" namespace i2p @@ -148,11 +147,9 @@ namespace crypto } - bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * keyMaterial, BN_CTX * ctx, bool zeroPadding) + bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding) { - uint8_t key[32]; - if (!GetElligator ()->Decode (epub, key)) return false; - m_StaticKeys.Agree (key, keyMaterial); + m_StaticKeys.Agree (epub, sharedSecret); return true; } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index c4788959..e7cde780 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -125,8 +125,8 @@ namespace crypto ECIESX25519AEADRatchetDecryptor (const uint8_t * priv): m_StaticKeys (priv, nullptr) {}; ~ECIESX25519AEADRatchetDecryptor () {}; - bool Decrypt (const uint8_t * epub, uint8_t * keyMaterial, BN_CTX * ctx, bool zeroPadding); - // take elligator encoded ephemeral pub (32 bytes), agree with static and return in keyMaterial (32 bytes) + bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding); + // agree with static and return in sharedSecret (32 bytes) size_t GetPublicKeyLen () const { return 32; }; private: diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index a32d3ed1..e4489fe0 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -237,6 +237,8 @@ namespace client // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const; std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; + i2p::data::CryptoKeyType GetEncryptionType () const { return m_EncryptionKeyType; }; + const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; protected: diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 888e988c..823f61ea 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1,8 +1,10 @@ #include +#include #include "I2PEndian.h" #include #include #include "Crypto.h" +#include "Elligator.h" #include "RouterContext.h" #include "I2NPProtocol.h" #include "Tunnel.h" @@ -433,6 +435,12 @@ namespace garlic return; } buf += 4; // length + if (GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET) + { + HandleECIESx25519 (buf, length - 4); + return; + } + // otherwise assume ElGamal/AES auto it = m_Tags.find (SessionTag(buf)); if (it != m_Tags.end ()) { @@ -821,5 +829,33 @@ namespace garlic if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT) i2p::fs::Remove (it); } + + void GarlicDestination::HandleECIESx25519 (const uint8_t * buf, size_t len) + { + // KDF + // TODO : use precalculated hashes + static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes + uint8_t h[64], ck[32]; + SHA256 ((const uint8_t *)protocolName, 40, h); + memcpy (ck, h, 32); + SHA256 (h, 32, h); + // we are Bob + memcpy (h + 32, GetEncryptionPublicKey (), 32); + SHA256 (h, 64, h); // h = SHA256(h || bpk) + + uint8_t aepk[32]; + if (!i2p::crypto::GetElligator ()->Decode (buf, aepk)) + { + LogPrint (eLogError, "Garlic: Can't decode elligator"); + return; + } + memcpy (h + 32, aepk, 32); + SHA256 (h, 64, h); // h = SHA256(h || aepk) + + uint8_t sharedSecret[32], keyData[64]; + Decrypt (aepk, sharedSecret, m_Ctx); // x25519 + i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) + memcpy (ck, keyData, 32); // chainKey = keydata[0:31] + } } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index c5236c90..b34fc00f 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -206,6 +206,9 @@ namespace garlic std::shared_ptr from); void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr from); + // ECIES-X25519-AEAD-Ratchet + void HandleECIESx25519 (const uint8_t * buf, size_t len); + private: BN_CTX * m_Ctx; // incoming diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 2fecc28a..3bacf5da 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -227,6 +227,8 @@ namespace data virtual std::shared_ptr GetIdentity () const = 0; const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); }; + virtual CryptoKeyType GetEncryptionType () const { return GetIdentity ()->GetCryptoKeyType (); }; // override for LeaseSet + virtual const uint8_t * GetEncryptionPublicKey () const { return GetIdentity ()->GetEncryptionPublicKey (); }; // override for LeaseSet }; } } From b5d55e1ffbff37f3ff8c3427b69655054149fcd2 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Dec 2019 16:34:47 -0500 Subject: [PATCH 35/51] decrypt flags/static section --- libi2pd/Garlic.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 823f61ea..371aabff 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -849,6 +849,7 @@ namespace garlic LogPrint (eLogError, "Garlic: Can't decode elligator"); return; } + buf += 32; memcpy (h + 32, aepk, 32); SHA256 (h, 64, h); // h = SHA256(h || aepk) @@ -856,6 +857,16 @@ namespace garlic Decrypt (aepk, sharedSecret, m_Ctx); // x25519 i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) memcpy (ck, keyData, 32); // chainKey = keydata[0:31] + + // decrypt flags/static + uint8_t nonce[12], fs[32]; + memset (nonce, 0, 12); // n = 0 + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, h, 32, keyData + 32, nonce, fs, 32, false)) // decrypt + { + LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); + return; + } + buf += 48; // 32 data + 16 poly } } } From 19a88300c6d80a573c2a16fd7abf9b6d24f36b46 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Dec 2019 14:44:02 -0500 Subject: [PATCH 36/51] decrypt payload section --- libi2pd/Garlic.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++-- libi2pd/Garlic.h | 12 ++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 371aabff..3c255d0d 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -832,7 +832,7 @@ namespace garlic void GarlicDestination::HandleECIESx25519 (const uint8_t * buf, size_t len) { - // KDF + // KDF1 // TODO : use precalculated hashes static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes uint8_t h[64], ck[32]; @@ -849,7 +849,7 @@ namespace garlic LogPrint (eLogError, "Garlic: Can't decode elligator"); return; } - buf += 32; + buf += 32; len -= 32; memcpy (h + 32, aepk, 32); SHA256 (h, 64, h); // h = SHA256(h || aepk) @@ -866,7 +866,69 @@ namespace garlic LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); return; } - buf += 48; // 32 data + 16 poly + memcpy (h + 32, buf, 32); + SHA256 (h, 64, h); // h = SHA256(h || ciphertext) + buf += 48; len -= 48; // 32 data + 16 poly + // decrypt payload + std::vector payload (len + 32); uint8_t h1[32]; + // KDF2 for payload + bool isStatic = !i2p::data::Tag<32> (fs).IsZero (); + if (isStatic) + { + // static key, fs is apk + Decrypt (fs, sharedSecret, m_Ctx); // DH(bsk, apk) + i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) + memcpy (ck, keyData, 32); // chainKey = keydata[0:31] + memcpy (payload.data (), h, 32); + memcpy (payload.data () + 32, buf, len); // h || ciphertext + SHA256 (payload.data (), len + 32, h1); + } + else // all zeros flags + htole64buf (nonce + 4, 1); // n = 1 + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, h, 32, keyData + 32, nonce, payload.data () + 32, len - 16, false)) // decrypt + { + LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); + return; + } + if (isStatic) memcpy (h, h1, 32); // h = SHA256(h || ciphertext) + HandleECIESx25519Payload (payload.data () + 32, len - 16); } + + void GarlicDestination::HandleECIESx25519Payload (const uint8_t * buf, size_t len) + { + size_t offset = 0; + while (offset < len) + { + uint8_t blk = buf[offset]; + offset++; + auto size = bufbe16toh (buf + offset); + offset += 2; + LogPrint (eLogDebug, "Garlic: Block type ", (int)blk, " of size ", size); + if (size > len) + { + LogPrint (eLogError, "Garlic: Unexpected block length ", size); + break; + } + switch (blk) + { + case eECIESx25519BlkGalicClove: + // TODO: + break; + case eECIESx25519BlkDateTime: + LogPrint (eLogDebug, "Garlic: datetime"); + break; + case eECIESx25519BlkOptions: + LogPrint (eLogDebug, "Garlic: options"); + break; + case eECIESx25519BlkPadding: + LogPrint (eLogDebug, "NTCP2: padding"); + break; + default: + LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk); + } + offset += size; + } + } + } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index b34fc00f..4054d88c 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -165,6 +165,17 @@ namespace garlic //using GarlicRoutingSessionPtr = std::shared_ptr; typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 + enum ECIESx25519BlockType + { + eECIESx25519BlkDateTime = 0, + eECIESx25519BlkSessionID = 1, + eECIESx25519BlkTermination = 4, + eECIESx25519BlkOptions = 5, + eECIESx25519BlkNextSessionKey = 7, + eECIESx25519BlkGalicClove = 11, + eECIESx25519BlkPadding = 254 + }; + class GarlicDestination: public i2p::data::LocalDestination { public: @@ -208,6 +219,7 @@ namespace garlic // ECIES-X25519-AEAD-Ratchet void HandleECIESx25519 (const uint8_t * buf, size_t len); + void HandleECIESx25519Payload (const uint8_t * buf, size_t len); private: From 599ec62bb0b7aca3cc99ddd95edcc35e43d808d2 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Dec 2019 20:45:47 -0500 Subject: [PATCH 37/51] use HKDF for NTCP2 key derivation data phase --- libi2pd/Crypto.cpp | 30 ++++++++++++++++++++++-------- libi2pd/Crypto.h | 2 +- libi2pd/NTCP2.cpp | 22 ++++++++-------------- libi2pd/NTCP2.h | 2 +- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 3c51a033..1c3f0b7b 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1259,18 +1259,29 @@ namespace crypto #endif } - void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out) + void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, + uint8_t * out, size_t outLen) { #if OPENSSL_HKDF - EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, NULL); + EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, nullptr); EVP_PKEY_derive_init (pctx); EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256()); - EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32); - EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen); + if (key && keyLen) + { + EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32); + EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen); + } + else + { + // zerolen + EVP_PKEY_CTX_hkdf_mode (pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); + uint8_t tempKey[32]; unsigned int len; + HMAC(EVP_sha256(), salt, 32, nullptr, 0, tempKey, &len); + EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len); + } if (info.length () > 0) EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ()); - size_t outlen = 64; - EVP_PKEY_derive (pctx, out, &outlen); + EVP_PKEY_derive (pctx, out, &outLen); EVP_PKEY_CTX_free (pctx); #else uint8_t prk[32]; unsigned int len; @@ -1278,8 +1289,11 @@ namespace crypto auto l = info.length (); memcpy (out, info.c_str (), l); out[l] = 0x01; HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len); - memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02; - HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len); + if (outLen > 32) // 64 + { + memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02; + HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len); + } #endif } diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index a4b6c2de..785c0b9d 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -296,7 +296,7 @@ namespace crypto // HKDF - void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out); // salt - 32, out - 64, info <= 32 + void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32 // init and terminate void InitCrypto (bool precomputation); diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index c12c5804..ce26794c 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -441,23 +441,17 @@ namespace transport void NTCP2Session::KeyDerivationFunctionDataPhase () { - uint8_t tempKey[32]; unsigned int len; - HMAC(EVP_sha256(), m_Establisher->GetCK (), 32, nullptr, 0, tempKey, &len); // temp_key = HMAC-SHA256(ck, zerolen) - static uint8_t one[1] = { 1 }; - HMAC(EVP_sha256(), tempKey, 32, one, 1, m_Kab, &len); // k_ab = HMAC-SHA256(temp_key, byte(0x01)). - m_Kab[32] = 2; - HMAC(EVP_sha256(), tempKey, 32, m_Kab, 33, m_Kba, &len); // k_ba = HMAC-SHA256(temp_key, k_ab || byte(0x02)) - static uint8_t ask[4] = { 'a', 's', 'k', 1 }, master[32]; - HMAC(EVP_sha256(), tempKey, 32, ask, 4, master, &len); // ask_master = HMAC-SHA256(temp_key, "ask" || byte(0x01)) + uint8_t k[64]; + i2p::crypto::HKDF (m_Establisher->GetCK (), nullptr, 0, "", k); // k_ab, k_ba = HKDF(ck, zerolen) + memcpy (m_Kab, k, 32); memcpy (m_Kba, k + 32, 32); + uint8_t master[32]; + i2p::crypto::HKDF (m_Establisher->GetCK (), nullptr, 0, "ask", master, 32); // ask_master = HKDF(ck, zerolen, info="ask") uint8_t h[39]; memcpy (h, m_Establisher->GetH (), 32); memcpy (h + 32, "siphash", 7); - HMAC(EVP_sha256(), master, 32, h, 39, tempKey, &len); // temp_key = HMAC-SHA256(ask_master, h || "siphash") - HMAC(EVP_sha256(), tempKey, 32, one, 1, master, &len); // sip_master = HMAC-SHA256(temp_key, byte(0x01)) - HMAC(EVP_sha256(), master, 32, nullptr, 0, tempKey, &len); // temp_key = HMAC-SHA256(sip_master, zerolen) - HMAC(EVP_sha256(), tempKey, 32, one, 1, m_Sipkeysab, &len); // sipkeys_ab = HMAC-SHA256(temp_key, byte(0x01)). - m_Sipkeysab[32] = 2; - HMAC(EVP_sha256(), tempKey, 32, m_Sipkeysab, 33, m_Sipkeysba, &len); // sipkeys_ba = HMAC-SHA256(temp_key, sipkeys_ab || byte(0x02)) + i2p::crypto::HKDF (master, h, 39, "", master, 32); // sip_master = HKDF(ask_master, h || "siphash") + i2p::crypto::HKDF (master, nullptr, 0, "", k, 64); // sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen) + memcpy (m_Sipkeysab, k, 32); memcpy (m_Sipkeysba, k + 32, 32); } diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index d2f1f88d..c66ff697 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -195,7 +195,7 @@ namespace transport std::unique_ptr m_Establisher; // data phase - uint8_t m_Kab[33], m_Kba[32], m_Sipkeysab[33], m_Sipkeysba[32]; + uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32]; const uint8_t * m_SendKey, * m_ReceiveKey; #if OPENSSL_SIPHASH EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey; From db84be248835aff65aa84e98979e14fdcbe1985a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Dec 2019 20:48:30 -0500 Subject: [PATCH 38/51] use HKDF for NTCP2 key derivation data phase --- libi2pd/NTCP2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index ce26794c..e2c4ae43 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -450,7 +450,7 @@ namespace transport memcpy (h, m_Establisher->GetH (), 32); memcpy (h + 32, "siphash", 7); i2p::crypto::HKDF (master, h, 39, "", master, 32); // sip_master = HKDF(ask_master, h || "siphash") - i2p::crypto::HKDF (master, nullptr, 0, "", k, 64); // sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen) + i2p::crypto::HKDF (master, nullptr, 0, "", k); // sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen) memcpy (m_Sipkeysab, k, 32); memcpy (m_Sipkeysba, k + 32, 32); } From 9f79bdae9bf8a9eaba52f6f61ba31157cc996fb5 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Dec 2019 15:59:15 -0500 Subject: [PATCH 39/51] encryptor for ECIES-X25519-AEAD-Ratchet --- libi2pd/Crypto.cpp | 12 ++++++++++++ libi2pd/Crypto.h | 1 + libi2pd/CryptoKey.cpp | 16 ++++++++++++++++ libi2pd/CryptoKey.h | 16 +++++++++++++++- libi2pd/Identity.cpp | 3 +++ libi2pd/Identity.h | 1 + libi2pd/LeaseSet.cpp | 5 ++--- libi2pd/LeaseSet.h | 2 ++ 8 files changed, 52 insertions(+), 4 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 1c3f0b7b..567ae574 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -367,6 +367,18 @@ namespace crypto #endif } + void X25519Keys::SetPrivateKey (const uint8_t * priv) + { +#if OPENSSL_X25519 + if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx); + if (m_Pkey) EVP_PKEY_free (m_Pkey); + m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32); + m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); +#else + memcpy (m_PrivateKey, priv, 32); +#endif + } + // ElGamal void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding) { diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 785c0b9d..33490c8a 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -80,6 +80,7 @@ namespace crypto void GenerateKeys (); const uint8_t * GetPublicKey () const { return m_PublicKey; }; void GetPrivateKey (uint8_t * priv) const; + void SetPrivateKey (const uint8_t * priv); // wihout calculating public void Agree (const uint8_t * pub, uint8_t * shared); private: diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index f247f37e..df5dd38f 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -146,6 +146,22 @@ namespace crypto BN_free (x); BN_free (y); } + ECIESX25519AEADRatchetEncryptor::ECIESX25519AEADRatchetEncryptor (const uint8_t * pub) + { + memcpy (m_PublicKey, pub, 32); + } + + void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t * epriv, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding) + { + X25519Keys ep; + ep.SetPrivateKey (epriv); + ep.Agree (m_PublicKey, sharedSecret); + } + + ECIESX25519AEADRatchetDecryptor::ECIESX25519AEADRatchetDecryptor (const uint8_t * priv) + { + m_StaticKeys.SetPrivateKey (priv); + } bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding) { diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index e7cde780..6412f4d3 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -119,11 +119,25 @@ namespace crypto // ECIES-X25519-AEAD-Ratchet + class ECIESX25519AEADRatchetEncryptor: public CryptoKeyEncryptor + { + public: + + ECIESX25519AEADRatchetEncryptor (const uint8_t * pub); + ~ECIESX25519AEADRatchetEncryptor () {}; + void Encrypt (const uint8_t * epriv, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding); + // agree with ephemeral priv and return in sharedSecret (32 bytes) + + private: + + uint8_t m_PublicKey[32]; + }; + class ECIESX25519AEADRatchetDecryptor: public CryptoKeyDecryptor { public: - ECIESX25519AEADRatchetDecryptor (const uint8_t * priv): m_StaticKeys (priv, nullptr) {}; + ECIESX25519AEADRatchetDecryptor (const uint8_t * priv); ~ECIESX25519AEADRatchetDecryptor () {}; bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding); // agree with static and return in sharedSecret (32 bytes) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index d217f41d..de94732f 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -417,6 +417,9 @@ namespace data case CRYPTO_KEY_TYPE_ELGAMAL: return std::make_shared(key); break; + case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET: + return std::make_shared(key); + break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST: return std::make_shared(key); diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 3bacf5da..f217f3c5 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -216,6 +216,7 @@ namespace data virtual bool IsDestination () const = 0; // for garlic const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); }; + virtual CryptoKeyType GetEncryptionType () const { return GetIdentity ()->GetCryptoKeyType (); }; // override in LeaseSet2 }; class LocalDestination diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index b516f010..e6373dd9 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -355,7 +355,6 @@ namespace data offset += propertiesLen; // skip for now. TODO: implement properties if (offset + 1 >= len) return 0; // key sections - uint16_t currentKeyType = 0; int numKeySections = buf[offset]; offset++; for (int i = 0; i < numKeySections; i++) { @@ -368,10 +367,10 @@ namespace data // we pick first valid key, higher key type has higher priority 4-1-0 // if two keys with of the same type, pick first auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); - if (encryptor && (!m_Encryptor || keyType > currentKeyType)) + if (encryptor && (!m_Encryptor || keyType > m_EncryptionType)) { m_Encryptor = encryptor; // TODO: atomic - currentKeyType = keyType; + m_EncryptionType = keyType; } } offset += encryptionKeyLen; diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 70aa7110..84d87e17 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -147,6 +147,7 @@ namespace data // implements RoutingDestination void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; + CryptoKeyType GetEncryptionType () const { return m_EncryptionType; }; private: @@ -167,6 +168,7 @@ namespace data uint32_t m_PublishedTimestamp = 0; bool m_IsPublic = true, m_IsPublishedEncrypted = false; std::shared_ptr m_TransientVerifier; + CryptoKeyType m_EncryptionType = CRYPTO_KEY_TYPE_ELGAMAL; std::shared_ptr m_Encryptor; // for standardLS2 }; From 5337aa10f762c98535d2170f367aa8cece7910b6 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 2 Jan 2020 13:30:54 -0500 Subject: [PATCH 40/51] check AES tag first --- libi2pd/Garlic.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 3c255d0d..1ee69df5 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -435,13 +435,8 @@ namespace garlic return; } buf += 4; // length - if (GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET) - { - HandleECIESx25519 (buf, length - 4); - return; - } - // otherwise assume ElGamal/AES auto it = m_Tags.find (SessionTag(buf)); + // AES tag might be used even if encryption type is not ElGamal/AES if (it != m_Tags.end ()) { // tag found. Use AES @@ -460,7 +455,13 @@ namespace garlic } else { - // tag not found. Use ElGamal + // tag not found. Handle depending on encryption type + if (GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET) + { + HandleECIESx25519 (buf, length - 4); + return; + } + // otherwise assume ElGamal/AES ElGamalBlock elGamal; if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx)) { From 26ad793d82bb0b1df23613ed77bcd6364a1b8b55 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 5 Jan 2020 23:04:08 +0000 Subject: [PATCH 41/51] use unscoped storage (fixes usage on android 10) Signed-off-by: r4sas --- android/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 757b35bb..71526701 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -16,6 +16,7 @@ android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Light.DarkActionBar" + android:requestLegacyExternalStorage="true" > From a33584150930335bbb75f6f53aa940717b8e9d8f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Jan 2020 14:37:40 -0500 Subject: [PATCH 42/51] pass msgID to HandleDeliveryStatus --- libi2pd/Destination.cpp | 10 +++++----- libi2pd/Destination.h | 2 +- libi2pd/Garlic.cpp | 6 +++--- libi2pd/Garlic.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index ca60f0fb..cbbee03a 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -353,7 +353,8 @@ namespace client void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); + uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET); + m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msgID)); } void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) @@ -366,7 +367,7 @@ namespace client break; case eI2NPDeliveryStatus: // we assume tunnel tests non-encrypted - HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from)); + HandleDeliveryStatusMessage (bufbe32toh (buf + I2NP_HEADER_SIZE + DELIVERY_STATUS_MSGID_OFFSET)); break; case eI2NPDatabaseStore: HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE); @@ -511,9 +512,8 @@ namespace client LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found"); } - void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr msg) + void LeaseSetDestination::HandleDeliveryStatusMessage (uint32_t msgID) { - uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET); if (msgID == m_PublishReplyToken) { LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed for ", GetIdentHash().ToBase32()); @@ -525,7 +525,7 @@ namespace client shared_from_this (), std::placeholders::_1)); } else - i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg); + i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msgID); } void LeaseSetDestination::SetLeaseSetUpdated () diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index e4489fe0..a6e6fe2d 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -152,7 +152,7 @@ namespace client void HandlePublishDelayTimer (const boost::system::error_code& ecode); void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len); - void HandleDeliveryStatusMessage (std::shared_ptr msg); + void HandleDeliveryStatusMessage (uint32_t msgID); void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr requestedBlindedKey = nullptr); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 1ee69df5..8cd12464 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -723,9 +723,8 @@ namespace garlic m_DeliveryStatusSessions[msgID] = session; } - void GarlicDestination::HandleDeliveryStatusMessage (std::shared_ptr msg) + void GarlicDestination::HandleDeliveryStatusMessage (uint32_t msgID) { - uint32_t msgID = bufbe32toh (msg->GetPayload ()); GarlicRoutingSessionPtr session; { std::unique_lock l(m_DeliveryStatusSessionsMutex); @@ -757,7 +756,8 @@ namespace garlic void GarlicDestination::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - HandleDeliveryStatusMessage (msg); + uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET); + HandleDeliveryStatusMessage (msgID); } void GarlicDestination::SaveTags () diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 4054d88c..bc999df5 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -206,7 +206,7 @@ namespace garlic protected: void HandleGarlicMessage (std::shared_ptr msg); - void HandleDeliveryStatusMessage (std::shared_ptr msg); + void HandleDeliveryStatusMessage (uint32_t msgID); void SaveTags (); void LoadTags (); From 815b6db0bfb811afd996a694736677ff0a63a817 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Jan 2020 15:31:20 -0500 Subject: [PATCH 43/51] HandleCloveI2NPMessage --- libi2pd/Destination.cpp | 17 ++++++++++++----- libi2pd/Destination.h | 5 ++++- libi2pd/Garlic.h | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index cbbee03a..f6855844 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -360,24 +360,31 @@ namespace client void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) { uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET]; + if (!HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE)) + i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from)); + } + + bool LeaseSetDestination::HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) + { switch (typeID) { case eI2NPData: - HandleDataMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE); + HandleDataMessage (payload, len); break; case eI2NPDeliveryStatus: // we assume tunnel tests non-encrypted - HandleDeliveryStatusMessage (bufbe32toh (buf + I2NP_HEADER_SIZE + DELIVERY_STATUS_MSGID_OFFSET)); + HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET)); break; case eI2NPDatabaseStore: - HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE); + HandleDatabaseStoreMessage (payload, len); break; case eI2NPDatabaseSearchReply: - HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE); + HandleDatabaseSearchReplyMessage (payload, len); break; default: - i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from)); + return false; } + return true; } void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index a6e6fe2d..bf08c80c 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -121,7 +121,6 @@ namespace client // implements GarlicDestination std::shared_ptr GetLeaseSet (); std::shared_ptr GetTunnelPool () const { return m_Pool; } - void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from); // override GarlicDestination bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); @@ -131,6 +130,10 @@ namespace client protected: + // implements GarlicDestination + void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from); + bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len); + void SetLeaseSet (std::shared_ptr newLeaseSet); int GetLeaseSetType () const { return m_LeaseSetType; }; void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index bc999df5..fea2c935 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -201,10 +201,10 @@ namespace garlic virtual std::shared_ptr GetLeaseSet () = 0; // TODO virtual std::shared_ptr GetTunnelPool () const = 0; - virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) = 0; protected: + virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) = 0; // called from clove only void HandleGarlicMessage (std::shared_ptr msg); void HandleDeliveryStatusMessage (uint32_t msgID); From 4afef91359cc59a14d13987c26bf4a0094b94a1e Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Jan 2020 16:14:41 -0500 Subject: [PATCH 44/51] invoke HandleCloveI2NPMessage --- libi2pd/Garlic.cpp | 28 +++++++++++++++++++++++++++- libi2pd/Garlic.h | 2 ++ libi2pd/RouterContext.h | 7 ++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 8cd12464..82778ddc 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -913,7 +913,7 @@ namespace garlic switch (blk) { case eECIESx25519BlkGalicClove: - // TODO: + HandleECIESx25519GarlicClove (buf + offset, size); break; case eECIESx25519BlkDateTime: LogPrint (eLogDebug, "Garlic: datetime"); @@ -931,5 +931,31 @@ namespace garlic } } + void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len) + { + const uint8_t * buf1 = buf; + uint8_t flag = buf[0]; buf++; // flag + GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); + switch (deliveryType) + { + case eGarlicDeliveryTypeDestination: + buf += 32; // TODO: check destination + // no break here + case eGarlicDeliveryTypeLocal: + { + uint8_t typeID = buf[0]; buf++; // typeid + buf += (4 + 4); // msgID + expiration + ptrdiff_t offset = buf - buf1; + if (offset <= (int)len) + HandleCloveI2NPMessage (typeID, buf, len - offset); + else + LogPrint (eLogError, "Garlic: clove is too long"); + break; + } + // TODO: tunnel + default: + LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); + } + } } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index fea2c935..5ef77638 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -205,6 +205,7 @@ namespace garlic protected: virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) = 0; // called from clove only + virtual bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) = 0; void HandleGarlicMessage (std::shared_ptr msg); void HandleDeliveryStatusMessage (uint32_t msgID); @@ -220,6 +221,7 @@ namespace garlic // ECIES-X25519-AEAD-Ratchet void HandleECIESx25519 (const uint8_t * buf, size_t len); void HandleECIESx25519Payload (const uint8_t * buf, size_t len); + void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); private: diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index f6aa281f..47a6f4fa 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -115,12 +115,17 @@ namespace i2p // implements GarlicDestination std::shared_ptr GetLeaseSet () { return nullptr; }; std::shared_ptr GetTunnelPool () const; - void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from); // override GarlicDestination void ProcessGarlicMessage (std::shared_ptr msg); void ProcessDeliveryStatusMessage (std::shared_ptr msg); + protected: + + // implements GarlicDestination + void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from); + bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) { return false; }; // not implemented + private: void CreateNewRouter (); From 0007f304d00157ac28ecdac2d970641adf79bec9 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 7 Jan 2020 15:20:55 -0500 Subject: [PATCH 45/51] don't pass from to HandleI2NPMessage --- libi2pd/Destination.cpp | 6 +++--- libi2pd/Destination.h | 2 +- libi2pd/Garlic.cpp | 4 ++-- libi2pd/Garlic.h | 2 +- libi2pd/RouterContext.cpp | 6 +++--- libi2pd/RouterContext.h | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index f6855844..c3f63ffc 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -357,11 +357,10 @@ namespace client m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msgID)); } - void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) + void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len) { uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET]; - if (!HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE)) - i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from)); + LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE); } bool LeaseSetDestination::HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) @@ -382,6 +381,7 @@ namespace client HandleDatabaseSearchReplyMessage (payload, len); break; default: + LogPrint (eLogWarning, "Destination: Unexpected I2NP message type ", typeID); return false; } return true; diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index bf08c80c..2b7f7bb8 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -131,7 +131,7 @@ namespace client protected: // implements GarlicDestination - void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from); + void HandleI2NPMessage (const uint8_t * buf, size_t len); bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len); void SetLeaseSet (std::shared_ptr newLeaseSet); diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 82778ddc..e87aae05 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -552,7 +552,7 @@ namespace garlic LogPrint (eLogError, "Garlic: message is too short"); break; } - HandleI2NPMessage (buf, len - offset, from); + HandleI2NPMessage (buf, len - offset); break; case eGarlicDeliveryTypeDestination: LogPrint (eLogDebug, "Garlic: type destination"); @@ -563,7 +563,7 @@ namespace garlic LogPrint (eLogError, "Garlic: message is too short"); break; } - HandleI2NPMessage (buf, len - offset, from); + HandleI2NPMessage (buf, len - offset); break; case eGarlicDeliveryTypeTunnel: { diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 5ef77638..6acfce95 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -204,7 +204,7 @@ namespace garlic protected: - virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) = 0; // called from clove only + virtual void HandleI2NPMessage (const uint8_t * buf, size_t len) = 0; // called from clove only virtual bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) = 0; void HandleGarlicMessage (std::shared_ptr msg); void HandleDeliveryStatusMessage (uint32_t msgID); diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index bf3459d8..2c07c21b 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -27,7 +27,7 @@ namespace i2p void RouterContext::Init () { srand (i2p::util::GetMillisecondsSinceEpoch () % 1000); - m_StartupTime = std::chrono::steady_clock::now(); + m_StartupTime = std::chrono::steady_clock::now(); if (!Load ()) CreateNewRouter (); @@ -692,9 +692,9 @@ namespace i2p return i2p::tunnel::tunnels.GetExploratoryPool (); } - void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) + void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len) { - i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from)); + i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len))); } void RouterContext::ProcessGarlicMessage (std::shared_ptr msg) diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 47a6f4fa..1524270d 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -123,7 +123,7 @@ namespace i2p protected: // implements GarlicDestination - void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from); + void HandleI2NPMessage (const uint8_t * buf, size_t len); bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) { return false; }; // not implemented private: From 4f70822b13a1fee29f175fac2d7ca17d56d5b831 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 12 Jan 2020 10:03:30 -0500 Subject: [PATCH 46/51] always persist crypto keys for public destinations --- libi2pd/Destination.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index c3f63ffc..71a5c329 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -879,11 +879,14 @@ namespace client if (it != params->end ()) m_EncryptionKeyType = std::stoi(it->second); } - - if (isPublic && m_EncryptionKeyType == GetIdentity ()->GetCryptoKeyType ()) // TODO: presist key type + + memset (m_EncryptionPrivateKey, 0, 256); + memset (m_EncryptionPublicKey, 0, 256); + if (isPublic) PersistTemporaryKeys (); else i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey); + m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_EncryptionKeyType, m_EncryptionPrivateKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); @@ -1172,8 +1175,8 @@ namespace client LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p"); memset (m_EncryptionPrivateKey, 0, 256); memset (m_EncryptionPublicKey, 0, 256); - i2p::data::PrivateKeys::GenerateCryptoKeyPair (GetIdentity ()->GetCryptoKeyType (), m_EncryptionPrivateKey, m_EncryptionPublicKey); - + i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey); + // TODO:: persist crypto key type std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); if (f1) { f1.write ((char *)m_EncryptionPublicKey, 256); From 7ac05f848737ffd6b4ccea05f86aecdd07313ef2 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Mon, 13 Jan 2020 14:47:15 +0200 Subject: [PATCH 47/51] Pass -dead_strip -dead_strip_dylibs -bind_at_load on macOS --- Makefile.osx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.osx b/Makefile.osx index d673d3ef..c6af4fc2 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -2,6 +2,9 @@ CXX = clang++ CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX INCFLAGS = -I/usr/local/include LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib +LDFLAGS += -Wl,-dead_strip +LDFLAGS += -Wl,-dead_strip_dylibs +LDFLAGS += -Wl,-bind_at_load ifeq ($(USE_STATIC),yes) LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread From 61752e2aaba77428de3014e97be864ca2f4f6673 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Jan 2020 22:37:31 -0500 Subject: [PATCH 48/51] correct ciphertext length --- libi2pd/Garlic.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index e87aae05..740b213b 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -836,7 +836,7 @@ namespace garlic // KDF1 // TODO : use precalculated hashes static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes - uint8_t h[64], ck[32]; + uint8_t h[80], ck[32]; SHA256 ((const uint8_t *)protocolName, 40, h); memcpy (ck, h, 32); SHA256 (h, 32, h); @@ -855,7 +855,7 @@ namespace garlic SHA256 (h, 64, h); // h = SHA256(h || aepk) uint8_t sharedSecret[32], keyData[64]; - Decrypt (aepk, sharedSecret, m_Ctx); // x25519 + Decrypt (aepk, sharedSecret, m_Ctx); // x25519(bsk, aepk) i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) memcpy (ck, keyData, 32); // chainKey = keydata[0:31] @@ -867,8 +867,8 @@ namespace garlic LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); return; } - memcpy (h + 32, buf, 32); - SHA256 (h, 64, h); // h = SHA256(h || ciphertext) + memcpy (h + 32, buf, 48); + SHA256 (h, 80, h); // h = SHA256(h || ciphertext) buf += 48; len -= 48; // 32 data + 16 poly // decrypt payload std::vector payload (len + 32); uint8_t h1[32]; @@ -877,7 +877,7 @@ namespace garlic if (isStatic) { // static key, fs is apk - Decrypt (fs, sharedSecret, m_Ctx); // DH(bsk, apk) + Decrypt (fs, sharedSecret, m_Ctx); // x25519(bsk, apk) i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) memcpy (ck, keyData, 32); // chainKey = keydata[0:31] memcpy (payload.data (), h, 32); From f651baab25ab6fbcf53e89ac89a13d424f708360 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 15 Jan 2020 15:13:43 -0500 Subject: [PATCH 49/51] ECIESX25519AEADRatchetSession added --- build/CMakeLists.txt | 1 + libi2pd/ECIESX25519AEADRatchetSession.cpp | 160 ++++++++++++++++++++++ libi2pd/ECIESX25519AEADRatchetSession.h | 49 +++++++ libi2pd/Garlic.cpp | 132 +----------------- libi2pd/Garlic.h | 13 -- 5 files changed, 217 insertions(+), 138 deletions(-) create mode 100644 libi2pd/ECIESX25519AEADRatchetSession.cpp create mode 100644 libi2pd/ECIESX25519AEADRatchetSession.h diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index a9cf3a83..2577fb1b 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -83,6 +83,7 @@ set (LIBI2PD_SRC "${LIBI2PD_SRC_DIR}/NTCP2.cpp" "${LIBI2PD_SRC_DIR}/Blinding.cpp" "${LIBI2PD_SRC_DIR}/Elligator.cpp" + "${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp" ) if (WITH_WEBSOCKETS) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp new file mode 100644 index 00000000..a258e8f7 --- /dev/null +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -0,0 +1,160 @@ +#include +#include +#include "Log.h" +#include "Crypto.h" +#include "Elligator.h" +#include "Tag.h" +#include "I2PEndian.h" +#include "Garlic.h" +#include "ECIESX25519AEADRatchetSession.h" + +namespace i2p +{ +namespace garlic +{ + + ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession () + { + // TODO : use precalculated hashes + static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes + SHA256 ((const uint8_t *)protocolName, 40, m_H); + memcpy (m_CK, m_H, 32); + SHA256 (m_H, 32, m_H); + } + + ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession () + { + } + + void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len) + { + SHA256_CTX ctx; + SHA256_Init (&ctx); + SHA256_Update (&ctx, m_H, 32); + SHA256_Update (&ctx, buf, len); + SHA256_Final (m_H, &ctx); + } + + bool ECIESX25519AEADRatchetSession::NewIncomingSession (const i2p::data::LocalDestination& dest, + const uint8_t * buf, size_t len, CloveI2NPMsgHandler handleCloveI2NPMsg) + { + // we are Bob + // KDF1 + MixHash (dest.GetEncryptionPublicKey (), 32); // h = SHA256(h || bpk) + + uint8_t aepk[32]; // Alice's ephemeral key + if (!i2p::crypto::GetElligator ()->Decode (buf, aepk)) + { + LogPrint (eLogError, "Garlic: Can't decode elligator"); + return false; + } + buf += 32; len -= 32; + MixHash (aepk, 32); // h = SHA256(h || aepk) + + uint8_t sharedSecret[32], keyData[64]; + dest.Decrypt (aepk, sharedSecret, nullptr); // x25519(bsk, aepk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) + memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31] + + // decrypt flags/static + uint8_t nonce[12], fs[32]; + memset (nonce, 0, 12); // n = 0 + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, keyData + 32, nonce, fs, 32, false)) // decrypt + { + LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); + return false; + } + MixHash (buf, 48); // h = SHA256(h || ciphertext) + buf += 48; len -= 48; // 32 data + 16 poly + + // decrypt payload + std::vector payload (len - 16); + // KDF2 for payload + bool isStatic = !i2p::data::Tag<32> (fs).IsZero (); + if (isStatic) + { + // static key, fs is apk + dest.Decrypt (fs, sharedSecret, nullptr); // x25519(bsk, apk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) + memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31] + } + else // all zeros flags + htole64buf (nonce + 4, 1); // n = 1 + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keyData + 32, nonce, payload.data (), len - 16, false)) // decrypt + { + LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); + return false; + } + if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext) + + HandlePayload (payload.data (), len - 16, handleCloveI2NPMsg); + + return true; + } + + void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg) + { + size_t offset = 0; + while (offset < len) + { + uint8_t blk = buf[offset]; + offset++; + auto size = bufbe16toh (buf + offset); + offset += 2; + LogPrint (eLogDebug, "Garlic: Block type ", (int)blk, " of size ", size); + if (size > len) + { + LogPrint (eLogError, "Garlic: Unexpected block length ", size); + break; + } + switch (blk) + { + case eECIESx25519BlkGalicClove: + HandleClove (buf + offset, size, handleCloveI2NPMsg); + break; + case eECIESx25519BlkDateTime: + LogPrint (eLogDebug, "Garlic: datetime"); + break; + case eECIESx25519BlkOptions: + LogPrint (eLogDebug, "Garlic: options"); + break; + case eECIESx25519BlkPadding: + LogPrint (eLogDebug, "NTCP2: padding"); + break; + default: + LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk); + } + offset += size; + } + } + + void ECIESX25519AEADRatchetSession::HandleClove (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg) + { + const uint8_t * buf1 = buf; + uint8_t flag = buf[0]; buf++; // flag + GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); + switch (deliveryType) + { + case eGarlicDeliveryTypeDestination: + buf += 32; // TODO: check destination + // no break here + case eGarlicDeliveryTypeLocal: + { + uint8_t typeID = buf[0]; buf++; // typeid + buf += (4 + 4); // msgID + expiration + ptrdiff_t offset = buf - buf1; + if (offset <= (int)len) + handleCloveI2NPMsg (typeID, buf, len - offset); + else + LogPrint (eLogError, "Garlic: clove is too long"); + break; + } + // TODO: tunnel + default: + LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); + } + } +} +} + + diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h new file mode 100644 index 00000000..dd28c669 --- /dev/null +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -0,0 +1,49 @@ +#ifndef ECIES_X25519_AEAD_RATCHET_SESSION_H__ +#define ECIES_X25519_AEAD_RATCHET_SESSION_H__ + +#include +#include +#include "Identity.h" + +namespace i2p +{ +namespace garlic +{ + enum ECIESx25519BlockType + { + eECIESx25519BlkDateTime = 0, + eECIESx25519BlkSessionID = 1, + eECIESx25519BlkTermination = 4, + eECIESx25519BlkOptions = 5, + eECIESx25519BlkNextSessionKey = 7, + eECIESx25519BlkGalicClove = 11, + eECIESx25519BlkPadding = 254 + }; + + class ECIESX25519AEADRatchetSession + { + public: + + typedef std::function CloveI2NPMsgHandler; + + ECIESX25519AEADRatchetSession (); + ~ECIESX25519AEADRatchetSession (); + + bool NewIncomingSession (const i2p::data::LocalDestination& dest, const uint8_t * buf, size_t len, + CloveI2NPMsgHandler handleCloveI2NPMsg); + + private: + + void MixHash (const uint8_t * buf, size_t len); + + void HandlePayload (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg); + void HandleClove (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg); + + private: + + uint8_t m_H[32], m_CK[32]; + }; +} +} + +#endif diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 740b213b..de8d6944 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1,10 +1,8 @@ #include -#include #include "I2PEndian.h" #include #include #include "Crypto.h" -#include "Elligator.h" #include "RouterContext.h" #include "I2NPProtocol.h" #include "Tunnel.h" @@ -13,6 +11,7 @@ #include "Timestamp.h" #include "Log.h" #include "FS.h" +#include "ECIESX25519AEADRatchetSession.h" #include "Garlic.h" namespace i2p @@ -833,129 +832,12 @@ namespace garlic void GarlicDestination::HandleECIESx25519 (const uint8_t * buf, size_t len) { - // KDF1 - // TODO : use precalculated hashes - static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes - uint8_t h[80], ck[32]; - SHA256 ((const uint8_t *)protocolName, 40, h); - memcpy (ck, h, 32); - SHA256 (h, 32, h); - // we are Bob - memcpy (h + 32, GetEncryptionPublicKey (), 32); - SHA256 (h, 64, h); // h = SHA256(h || bpk) - - uint8_t aepk[32]; - if (!i2p::crypto::GetElligator ()->Decode (buf, aepk)) - { - LogPrint (eLogError, "Garlic: Can't decode elligator"); - return; - } - buf += 32; len -= 32; - memcpy (h + 32, aepk, 32); - SHA256 (h, 64, h); // h = SHA256(h || aepk) - - uint8_t sharedSecret[32], keyData[64]; - Decrypt (aepk, sharedSecret, m_Ctx); // x25519(bsk, aepk) - i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) - memcpy (ck, keyData, 32); // chainKey = keydata[0:31] - - // decrypt flags/static - uint8_t nonce[12], fs[32]; - memset (nonce, 0, 12); // n = 0 - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, h, 32, keyData + 32, nonce, fs, 32, false)) // decrypt - { - LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); - return; - } - memcpy (h + 32, buf, 48); - SHA256 (h, 80, h); // h = SHA256(h || ciphertext) - buf += 48; len -= 48; // 32 data + 16 poly - // decrypt payload - std::vector payload (len + 32); uint8_t h1[32]; - // KDF2 for payload - bool isStatic = !i2p::data::Tag<32> (fs).IsZero (); - if (isStatic) - { - // static key, fs is apk - Decrypt (fs, sharedSecret, m_Ctx); // x25519(bsk, apk) - i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) - memcpy (ck, keyData, 32); // chainKey = keydata[0:31] - memcpy (payload.data (), h, 32); - memcpy (payload.data () + 32, buf, len); // h || ciphertext - SHA256 (payload.data (), len + 32, h1); - } - else // all zeros flags - htole64buf (nonce + 4, 1); // n = 1 - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, h, 32, keyData + 32, nonce, payload.data () + 32, len - 16, false)) // decrypt - { - LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); - return; - } - if (isStatic) memcpy (h, h1, 32); // h = SHA256(h || ciphertext) - HandleECIESx25519Payload (payload.data () + 32, len - 16); - } - - void GarlicDestination::HandleECIESx25519Payload (const uint8_t * buf, size_t len) - { - size_t offset = 0; - while (offset < len) - { - uint8_t blk = buf[offset]; - offset++; - auto size = bufbe16toh (buf + offset); - offset += 2; - LogPrint (eLogDebug, "Garlic: Block type ", (int)blk, " of size ", size); - if (size > len) - { - LogPrint (eLogError, "Garlic: Unexpected block length ", size); - break; - } - switch (blk) - { - case eECIESx25519BlkGalicClove: - HandleECIESx25519GarlicClove (buf + offset, size); - break; - case eECIESx25519BlkDateTime: - LogPrint (eLogDebug, "Garlic: datetime"); - break; - case eECIESx25519BlkOptions: - LogPrint (eLogDebug, "Garlic: options"); - break; - case eECIESx25519BlkPadding: - LogPrint (eLogDebug, "NTCP2: padding"); - break; - default: - LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk); - } - offset += size; - } - } - - void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len) - { - const uint8_t * buf1 = buf; - uint8_t flag = buf[0]; buf++; // flag - GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); - switch (deliveryType) - { - case eGarlicDeliveryTypeDestination: - buf += 32; // TODO: check destination - // no break here - case eGarlicDeliveryTypeLocal: - { - uint8_t typeID = buf[0]; buf++; // typeid - buf += (4 + 4); // msgID + expiration - ptrdiff_t offset = buf - buf1; - if (offset <= (int)len) - HandleCloveI2NPMessage (typeID, buf, len - offset); - else - LogPrint (eLogError, "Garlic: clove is too long"); - break; - } - // TODO: tunnel - default: - LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); - } + ECIESX25519AEADRatchetSession session; + session.NewIncomingSession (*this, buf, len, + [this](uint8_t typeID, const uint8_t * payload, size_t len) + { + HandleCloveI2NPMessage (typeID, payload,len); + }); } } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 6acfce95..44ab2e82 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -165,17 +165,6 @@ namespace garlic //using GarlicRoutingSessionPtr = std::shared_ptr; typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 - enum ECIESx25519BlockType - { - eECIESx25519BlkDateTime = 0, - eECIESx25519BlkSessionID = 1, - eECIESx25519BlkTermination = 4, - eECIESx25519BlkOptions = 5, - eECIESx25519BlkNextSessionKey = 7, - eECIESx25519BlkGalicClove = 11, - eECIESx25519BlkPadding = 254 - }; - class GarlicDestination: public i2p::data::LocalDestination { public: @@ -220,8 +209,6 @@ namespace garlic // ECIES-X25519-AEAD-Ratchet void HandleECIESx25519 (const uint8_t * buf, size_t len); - void HandleECIESx25519Payload (const uint8_t * buf, size_t len); - void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); private: From 376bf6ba72af16d4d5ef2e75dfc1277176806c42 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 15 Jan 2020 19:22:42 -0500 Subject: [PATCH 50/51] correct message size for ECIESx25519 --- libi2pd/Garlic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index de8d6944..5dfdfe79 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -457,7 +457,7 @@ namespace garlic // tag not found. Handle depending on encryption type if (GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET) { - HandleECIESx25519 (buf, length - 4); + HandleECIESx25519 (buf, length); return; } // otherwise assume ElGamal/AES From bcfe44db54a83f3f3206bb97e9c7b921a2e86da0 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Jan 2020 12:47:08 -0500 Subject: [PATCH 51/51] handle tunnel delivery instructioin for ECIESx25519 --- libi2pd/Destination.cpp | 4 +- libi2pd/Destination.h | 2 +- libi2pd/ECIESX25519AEADRatchetSession.cpp | 38 ++------------ libi2pd/ECIESX25519AEADRatchetSession.h | 7 ++- libi2pd/Garlic.cpp | 63 +++++++++++++++++++++-- libi2pd/Garlic.h | 3 +- libi2pd/RouterContext.h | 2 +- 7 files changed, 72 insertions(+), 47 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 71a5c329..ba74f61f 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -359,11 +359,11 @@ namespace client void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len) { - uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET]; + I2NPMessageType typeID = (I2NPMessageType)(buf[I2NP_HEADER_TYPEID_OFFSET]); LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE); } - bool LeaseSetDestination::HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) + bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len) { switch (typeID) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 2b7f7bb8..f4483032 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -132,7 +132,7 @@ namespace client // implements GarlicDestination void HandleI2NPMessage (const uint8_t * buf, size_t len); - bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len); + bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len); void SetLeaseSet (std::shared_ptr newLeaseSet); int GetLeaseSetType () const { return m_LeaseSetType; }; diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index a258e8f7..96efe5e6 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -5,7 +5,6 @@ #include "Elligator.h" #include "Tag.h" #include "I2PEndian.h" -#include "Garlic.h" #include "ECIESX25519AEADRatchetSession.h" namespace i2p @@ -36,7 +35,7 @@ namespace garlic } bool ECIESX25519AEADRatchetSession::NewIncomingSession (const i2p::data::LocalDestination& dest, - const uint8_t * buf, size_t len, CloveI2NPMsgHandler handleCloveI2NPMsg) + const uint8_t * buf, size_t len, CloveHandler handleClove) { // we are Bob // KDF1 @@ -87,12 +86,12 @@ namespace garlic } if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext) - HandlePayload (payload.data (), len - 16, handleCloveI2NPMsg); + HandlePayload (payload.data (), len - 16, handleClove); return true; } - void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg) + void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, CloveHandler& handleClove) { size_t offset = 0; while (offset < len) @@ -110,7 +109,7 @@ namespace garlic switch (blk) { case eECIESx25519BlkGalicClove: - HandleClove (buf + offset, size, handleCloveI2NPMsg); + handleClove (buf + offset, size); break; case eECIESx25519BlkDateTime: LogPrint (eLogDebug, "Garlic: datetime"); @@ -119,7 +118,7 @@ namespace garlic LogPrint (eLogDebug, "Garlic: options"); break; case eECIESx25519BlkPadding: - LogPrint (eLogDebug, "NTCP2: padding"); + LogPrint (eLogDebug, "Garlic: padding"); break; default: LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk); @@ -127,33 +126,6 @@ namespace garlic offset += size; } } - - void ECIESX25519AEADRatchetSession::HandleClove (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg) - { - const uint8_t * buf1 = buf; - uint8_t flag = buf[0]; buf++; // flag - GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); - switch (deliveryType) - { - case eGarlicDeliveryTypeDestination: - buf += 32; // TODO: check destination - // no break here - case eGarlicDeliveryTypeLocal: - { - uint8_t typeID = buf[0]; buf++; // typeid - buf += (4 + 4); // msgID + expiration - ptrdiff_t offset = buf - buf1; - if (offset <= (int)len) - handleCloveI2NPMsg (typeID, buf, len - offset); - else - LogPrint (eLogError, "Garlic: clove is too long"); - break; - } - // TODO: tunnel - default: - LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); - } - } } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index dd28c669..aa482d54 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -24,20 +24,19 @@ namespace garlic { public: - typedef std::function CloveI2NPMsgHandler; + typedef std::function CloveHandler; ECIESX25519AEADRatchetSession (); ~ECIESX25519AEADRatchetSession (); bool NewIncomingSession (const i2p::data::LocalDestination& dest, const uint8_t * buf, size_t len, - CloveI2NPMsgHandler handleCloveI2NPMsg); + CloveHandler handleClove); private: void MixHash (const uint8_t * buf, size_t len); - void HandlePayload (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg); - void HandleClove (const uint8_t * buf, size_t len, CloveI2NPMsgHandler& handleCloveI2NPMsg); + void HandlePayload (const uint8_t * buf, size_t len, CloveHandler& handleClove); private: diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 5dfdfe79..aa715e0c 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -833,11 +833,64 @@ namespace garlic void GarlicDestination::HandleECIESx25519 (const uint8_t * buf, size_t len) { ECIESX25519AEADRatchetSession session; - session.NewIncomingSession (*this, buf, len, - [this](uint8_t typeID, const uint8_t * payload, size_t len) - { - HandleCloveI2NPMessage (typeID, payload,len); - }); + session.NewIncomingSession (*this, buf, len, std::bind (&GarlicDestination::HandleECIESx25519GarlicClove, + this, std::placeholders::_1, std::placeholders::_2)); } + + void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len) + { + const uint8_t * buf1 = buf; + uint8_t flag = buf[0]; buf++; // flag + GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); + switch (deliveryType) + { + case eGarlicDeliveryTypeDestination: + LogPrint (eLogDebug, "Garlic: type destination"); + buf += 32; // TODO: check destination + // no break here + case eGarlicDeliveryTypeLocal: + { + LogPrint (eLogDebug, "Garlic: type local"); + I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid + buf += (4 + 4); // msgID + expiration + ptrdiff_t offset = buf - buf1; + if (offset <= (int)len) + HandleCloveI2NPMessage (typeID, buf, len - offset); + else + LogPrint (eLogError, "Garlic: clove is too long"); + break; + } + case eGarlicDeliveryTypeTunnel: + { + LogPrint (eLogDebug, "Garlic: type tunnel"); + // gwHash and gwTunnel sequence is reverted + const uint8_t * gwHash = buf; + buf += 32; + ptrdiff_t offset = buf - buf1; + if (offset + 13 > (int)len) + { + LogPrint (eLogError, "Garlic: message is too short"); + break; + } + uint32_t gwTunnel = bufbe32toh (buf); buf += 4; + I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid + buf += (4 + 4); // msgID + expiration + offset += 13; + if (GetTunnelPool ()) + { + auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel (); + if (tunnel) + tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset)); + else + LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove"); + } + else + LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel"); + break; + } + default: + LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); + } + } } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 44ab2e82..30e6ff4b 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -194,7 +194,7 @@ namespace garlic protected: virtual void HandleI2NPMessage (const uint8_t * buf, size_t len) = 0; // called from clove only - virtual bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) = 0; + virtual bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len) = 0; void HandleGarlicMessage (std::shared_ptr msg); void HandleDeliveryStatusMessage (uint32_t msgID); @@ -209,6 +209,7 @@ namespace garlic // ECIES-X25519-AEAD-Ratchet void HandleECIESx25519 (const uint8_t * buf, size_t len); + void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); private: diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 1524270d..dfc05fe7 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -124,7 +124,7 @@ namespace i2p // implements GarlicDestination void HandleI2NPMessage (const uint8_t * buf, size_t len); - bool HandleCloveI2NPMessage (uint8_t typeID, const uint8_t * payload, size_t len) { return false; }; // not implemented + bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len) { return false; }; // not implemented private: