From 7a5146ea7455136d507843c2180a3761ab401bc7 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 1 Mar 2020 13:25:50 +0300 Subject: [PATCH] fix code syle(spaces->tabs, tabulations) Signed-off-by: R4SAS --- Win32/DaemonWin32.cpp | 4 +- Win32/Win32App.cpp | 910 +++++++++++----------- Win32/Win32App.h | 34 +- Win32/Win32Service.h | 88 +-- Win32/resource.h | 22 +- daemon/Daemon.cpp | 45 +- daemon/Daemon.h | 14 +- daemon/HTTPServer.cpp | 4 +- daemon/HTTPServer.h | 22 +- daemon/I2PControl.cpp | 49 +- daemon/I2PControl.h | 1 + daemon/UPnP.cpp | 44 +- daemon/UPnP.h | 62 +- daemon/UnixDaemon.cpp | 1 - daemon/i2pd.cpp | 3 +- libi2pd/Base.cpp | 218 +++--- libi2pd/Base.h | 12 +- libi2pd/Blinding.cpp | 79 +- libi2pd/Blinding.h | 8 +- libi2pd/CPU.h | 6 +- libi2pd/ChaCha20.cpp | 115 ++- libi2pd/ChaCha20.h | 30 +- libi2pd/Config.cpp | 2 +- libi2pd/Config.h | 169 ++-- libi2pd/Crypto.cpp | 118 ++- libi2pd/Crypto.h | 30 +- libi2pd/CryptoKey.cpp | 7 +- libi2pd/CryptoKey.h | 13 +- libi2pd/CryptoWorker.h | 1 - libi2pd/Datagram.cpp | 32 +- libi2pd/Datagram.h | 97 +-- libi2pd/Destination.cpp | 119 ++- libi2pd/Destination.h | 31 +- libi2pd/ECIESX25519AEADRatchetSession.cpp | 748 +++++++++--------- libi2pd/ECIESX25519AEADRatchetSession.h | 166 ++-- libi2pd/Ed25519.cpp | 43 +- libi2pd/Ed25519.h | 14 +- libi2pd/Elligator.cpp | 87 +-- libi2pd/Elligator.h | 6 +- libi2pd/FS.h | 251 +++--- libi2pd/Family.cpp | 1 - libi2pd/Garlic.cpp | 188 ++--- libi2pd/Garlic.h | 106 +-- libi2pd/Gost.h | 8 +- libi2pd/Gzip.cpp | 26 +- libi2pd/Gzip.h | 5 +- libi2pd/I2NPProtocol.cpp | 28 +- libi2pd/I2NPProtocol.h | 6 +- libi2pd/Identity.cpp | 50 +- libi2pd/Identity.h | 13 +- libi2pd/LeaseSet.cpp | 224 +++--- libi2pd/LeaseSet.h | 39 +- libi2pd/LittleBigEndian.h | 380 ++++----- libi2pd/Log.cpp | 26 +- libi2pd/Log.h | 6 +- libi2pd/NTCP2.cpp | 20 +- libi2pd/NTCP2.h | 1 - libi2pd/NTCPSession.cpp | 15 +- libi2pd/NetDb.cpp | 28 +- libi2pd/NetDb.hpp | 37 +- libi2pd/NetDbRequests.cpp | 5 +- libi2pd/NetDbRequests.h | 1 - libi2pd/Poly1305.cpp | 3 +- libi2pd/Poly1305.h | 15 +- libi2pd/Reseed.cpp | 128 +-- libi2pd/Reseed.h | 2 +- libi2pd/RouterContext.cpp | 8 +- libi2pd/RouterContext.h | 14 +- libi2pd/RouterInfo.cpp | 54 +- libi2pd/RouterInfo.h | 4 +- libi2pd/SSU.cpp | 23 +- libi2pd/SSU.h | 3 +- libi2pd/SSUData.cpp | 3 +- libi2pd/SSUData.h | 1 - libi2pd/SSUSession.cpp | 5 +- libi2pd/SSUSession.h | 9 +- libi2pd/Signature.cpp | 52 +- libi2pd/Signature.h | 61 +- libi2pd/Siphash.h | 276 +++---- libi2pd/Streaming.cpp | 54 +- libi2pd/Tag.h | 158 ++-- libi2pd/Timestamp.cpp | 13 +- libi2pd/Timestamp.h | 13 +- libi2pd/TransitTunnel.cpp | 4 +- libi2pd/TransportSession.h | 8 +- libi2pd/Transports.cpp | 14 +- libi2pd/Transports.h | 20 +- libi2pd/TunnelEndpoint.cpp | 3 +- libi2pd/TunnelGateway.cpp | 5 +- libi2pd/TunnelPool.cpp | 12 +- libi2pd/TunnelPool.h | 24 +- libi2pd/api.cpp | 5 +- libi2pd/api.h | 1 - libi2pd/util.cpp | 55 +- libi2pd/util.h | 16 +- libi2pd_client/AddressBook.cpp | 64 +- libi2pd_client/AddressBook.h | 6 +- libi2pd_client/BOB.cpp | 50 +- libi2pd_client/BOB.h | 27 +- libi2pd_client/ClientContext.cpp | 64 +- libi2pd_client/ClientContext.h | 10 +- libi2pd_client/HTTPProxy.cpp | 12 +- libi2pd_client/HTTPProxy.h | 3 + libi2pd_client/I2CP.cpp | 53 +- libi2pd_client/I2CP.h | 9 +- libi2pd_client/I2PService.cpp | 22 +- libi2pd_client/I2PService.h | 26 +- libi2pd_client/I2PTunnel.cpp | 12 +- libi2pd_client/I2PTunnel.h | 36 +- libi2pd_client/MatchedDestination.cpp | 8 +- libi2pd_client/MatchedDestination.h | 38 +- libi2pd_client/SAM.cpp | 99 ++- libi2pd_client/SAM.h | 17 +- libi2pd_client/SOCKS.cpp | 9 +- libi2pd_client/SOCKS.h | 2 + 115 files changed, 3298 insertions(+), 3253 deletions(-) diff --git a/Win32/DaemonWin32.cpp b/Win32/DaemonWin32.cpp index 5524aff3..7ba3ffc3 100644 --- a/Win32/DaemonWin32.cpp +++ b/Win32/DaemonWin32.cpp @@ -27,8 +27,8 @@ namespace util i2p::log::SetThrowFunction ([](const std::string& s) { MessageBox(0, TEXT(s.c_str ()), TEXT("i2pd"), MB_ICONERROR | MB_TASKMODAL | MB_OK ); - }); - + }); + if (!Daemon_Singleton::init(argc, argv)) return false; diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 7ae4e419..3bcb24b3 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -1,455 +1,455 @@ -#include -#include -#include -#include -#include "ClientContext.h" -#include "Config.h" -#include "NetDb.hpp" -#include "RouterContext.h" -#include "Transports.h" -#include "Tunnel.h" -#include "version.h" -#include "resource.h" -#include "Daemon.h" -#include "Win32App.h" -#include "Win32NetState.h" - -#define ID_ABOUT 2000 -#define ID_EXIT 2001 -#define ID_CONSOLE 2002 -#define ID_APP 2003 -#define ID_GRACEFUL_SHUTDOWN 2004 -#define ID_STOP_GRACEFUL_SHUTDOWN 2005 -#define ID_RELOAD 2006 -#define ID_ACCEPT_TRANSIT 2007 -#define ID_DECLINE_TRANSIT 2008 - -#define ID_TRAY_ICON 2050 -#define WM_TRAYICON (WM_USER + 1) - -#define IDT_GRACEFUL_SHUTDOWN_TIMER 2100 -#define FRAME_UPDATE_TIMER 2101 -#define IDT_GRACEFUL_TUNNELCHECK_TIMER 2102 - -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) - { - HMENU hPopup = CreatePopupMenu(); - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console"); - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app"); - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About..."); - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - if(!i2p::context.AcceptsTunnels()) - InsertMenu (hPopup, -1, - i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING, - 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 tunnels config"); - if (!i2p::util::DaemonWin32::Instance ().isGraceful) - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown"); - else - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_STOP_GRACEFUL_SHUTDOWN, "Stop &graceful shutdown"); - InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit"); - SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE); - SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0); - - POINT p; - if (!curpos) - { - GetCursorPos (&p); - curpos = &p; - } - - WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL); - SendMessage (hWnd, WM_COMMAND, cmd, 0); - - DestroyMenu(hPopup); - } - - static void AddTrayIcon (HWND hWnd) - { - NOTIFYICONDATA nid; - memset(&nid, 0, sizeof(nid)); - nid.cbSize = sizeof(nid); - nid.hWnd = hWnd; - nid.uID = ID_TRAY_ICON; - nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO; - nid.uCallbackMessage = WM_TRAYICON; - nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON)); - strcpy (nid.szTip, "i2pd"); - strcpy (nid.szInfo, "i2pd is starting"); - Shell_NotifyIcon(NIM_ADD, &nid ); - } - - static void RemoveTrayIcon (HWND hWnd) - { - NOTIFYICONDATA nid; - nid.hWnd = hWnd; - nid.uID = ID_TRAY_ICON; - Shell_NotifyIcon (NIM_DELETE, &nid); - } - - static void ShowUptime (std::stringstream& s, int seconds) - { - int num; - - if ((num = seconds / 86400) > 0) { - s << num << " days, "; - seconds -= num * 86400; - } - if ((num = seconds / 3600) > 0) { - s << num << " hours, "; - seconds -= num * 3600; - } - if ((num = seconds / 60) > 0) { - s << num << " min, "; - seconds -= num * 60; - } - s << seconds << " seconds\n"; - } - - template static void ShowTransfered (std::stringstream& s, size transfer) - { - auto bytes = transfer & 0x03ff; - transfer >>= 10; - auto kbytes = transfer & 0x03ff; - transfer >>= 10; - auto mbytes = transfer & 0x03ff; - transfer >>= 10; - auto gbytes = transfer & 0x03ff; - - if (gbytes) - s << gbytes << " GB, "; - if (mbytes) - s << mbytes << " MB, "; - if (kbytes) - s << kbytes << " KB, "; - s << bytes << " Bytes\n"; - } - - static void PrintMainWindowText (std::stringstream& s) - { - s << "\n"; - s << "Status: "; - switch (i2p::context.GetStatus()) - { - case eRouterStatusOK: s << "OK"; break; - case eRouterStatusTesting: s << "Testing"; break; - case eRouterStatusFirewalled: s << "Firewalled"; break; - case eRouterStatusError: - { - switch (i2p::context.GetError()) - { - case eRouterErrorClockSkew: s << "Clock skew"; break; - default: s << "Error"; - } - break; - } - default: s << "Unknown"; - } - s << "; "; - s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n"; - s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ()); - if (GracefulShutdownEndtime != 0) - { - DWORD GracefulTimeLeft = (GracefulShutdownEndtime - GetTickCountLocal()) / 1000; - s << "Graceful shutdown, time left: "; ShowUptime(s, GracefulTimeLeft); - } - else - s << "\n"; - s << "Inbound: " << i2p::transport::transports.GetInBandwidth() / 1024 << " KiB/s; "; - s << "Outbound: " << i2p::transport::transports.GetOutBandwidth() / 1024 << " KiB/s\n"; - s << "Received: "; ShowTransfered (s, i2p::transport::transports.GetTotalReceivedBytes()); - s << "Sent: "; ShowTransfered (s, i2p::transport::transports.GetTotalSentBytes()); - s << "\n"; - s << "Routers: " << i2p::data::netdb.GetNumRouters () << "; "; - s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << "; "; - s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "\n"; - s << "Tunnels: "; - s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; "; - s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; "; - s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n"; - s << "\n"; - } - - static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - static UINT s_uTaskbarRestart; - - switch (uMsg) - { - case WM_CREATE: - { - s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); - AddTrayIcon (hWnd); - break; - } - case WM_CLOSE: - { - RemoveTrayIcon (hWnd); - KillTimer (hWnd, FRAME_UPDATE_TIMER); - KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER); - KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER); - PostQuitMessage (0); - break; - } - case WM_COMMAND: - { - switch (LOWORD(wParam)) - { - case ID_ABOUT: - { - std::stringstream text; - text << "Version: " << I2PD_VERSION << " " << CODENAME; - MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); - return 0; - } - case ID_EXIT: - { - PostMessage (hWnd, WM_CLOSE, 0, 0); - return 0; - } - case ID_ACCEPT_TRANSIT: - { - i2p::context.SetAcceptsTunnels (true); - std::stringstream text; - text << "I2Pd now accept transit tunnels"; - MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); - return 0; - } - case ID_DECLINE_TRANSIT: - { - i2p::context.SetAcceptsTunnels (false); - std::stringstream text; - text << "I2Pd now decline new transit tunnels"; - MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); - return 0; - } - case ID_GRACEFUL_SHUTDOWN: - { - 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 = GetTickCountLocal() + 10*60*1000; - i2p::util::DaemonWin32::Instance ().isGraceful = true; - return 0; - } - case ID_STOP_GRACEFUL_SHUTDOWN: - { - i2p::context.SetAcceptsTunnels (true); - KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER); - KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER); - GracefulShutdownEndtime = 0; - i2p::util::DaemonWin32::Instance ().isGraceful = false; - return 0; - } - case ID_RELOAD: - { - i2p::client::context.ReloadConfig(); - std::stringstream text; - text << "I2Pd reloading configs..."; - MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); - return 0; - } - case ID_CONSOLE: - { - char buf[30]; - std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); - uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); - snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort); - ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL); - return 0; - } - case ID_APP: - { - ShowWindow(hWnd, SW_SHOW); - SetTimer(hWnd, FRAME_UPDATE_TIMER, 3000, NULL); - return 0; - } - } - break; - } - case WM_SYSCOMMAND: - { - switch (wParam) - { - case SC_MINIMIZE: - { - ShowWindow(hWnd, SW_HIDE); - KillTimer (hWnd, FRAME_UPDATE_TIMER); - return 0; - } - case SC_CLOSE: - { - std::string close; i2p::config::GetOption("close", close); - if (0 == close.compare("ask")) - switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?" - " You can add 'close' configuration option. Valid values are: ask, minimize, exit.", - "Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1)) - { - case IDYES: close = "minimize"; break; - case IDNO: close = "exit"; break; - default: return 0; - } - if (0 == close.compare("minimize")) - { - ShowWindow(hWnd, SW_HIDE); - KillTimer (hWnd, FRAME_UPDATE_TIMER); - return 0; - } - if (0 != close.compare("exit")) - { - ::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING); - return 0; - } - } - } - } - case WM_TRAYICON: - { - switch (lParam) - { - case WM_LBUTTONUP: - case WM_RBUTTONUP: - { - SetForegroundWindow (hWnd); - ShowPopupMenu(hWnd, NULL, -1); - PostMessage (hWnd, WM_APP + 1, 0, 0); - break; - } - } - break; - } - case WM_TIMER: - { - switch(wParam) - { - case IDT_GRACEFUL_SHUTDOWN_TIMER: - { - GracefulShutdownEndtime = 0; - PostMessage (hWnd, WM_CLOSE, 0, 0); // exit - return 0; - } - case IDT_GRACEFUL_TUNNELCHECK_TIMER: - { - if (i2p::tunnel::tunnels.CountTransitTunnels() == 0) - PostMessage (hWnd, WM_CLOSE, 0, 0); - else - SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); - return 0; - } - case FRAME_UPDATE_TIMER: - { - InvalidateRect(hWnd, NULL, TRUE); - return 0; - } - } - break; - } - case WM_PAINT: - { - HDC hDC; - PAINTSTRUCT ps; - RECT rp; - HFONT hFont; - std::stringstream s; PrintMainWindowText (s); - hDC = BeginPaint (hWnd, &ps); - GetClientRect(hWnd, &rp); - SetTextColor(hDC, 0x00D43B69); - hFont = CreateFont(18,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,TEXT("Times New Roman")); - SelectObject(hDC,hFont); - DrawText(hDC, TEXT(s.str().c_str()), s.str().length(), &rp, DT_CENTER|DT_VCENTER); - DeleteObject(hFont); - EndPaint(hWnd, &ps); - break; - } - default: - { - if (uMsg == s_uTaskbarRestart) - AddTrayIcon (hWnd); - break; - } - } - return DefWindowProc( hWnd, uMsg, wParam, lParam); - } - - bool StartWin32App () - { - if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"))) - { - MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK); - return false; - } - // register main window - auto hInst = GetModuleHandle(NULL); - WNDCLASSEX wclx; - memset (&wclx, 0, sizeof(wclx)); - wclx.cbSize = sizeof(wclx); - wclx.style = 0; - wclx.lpfnWndProc = WndProc; - //wclx.cbClsExtra = 0; - //wclx.cbWndExtra = 0; - wclx.hInstance = hInst; - wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(MAINICON)); - wclx.hCursor = LoadCursor (NULL, IDC_ARROW); - //wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); - wclx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wclx.lpszMenuName = NULL; - wclx.lpszClassName = I2PD_WIN32_CLASSNAME; - RegisterClassEx (&wclx); - // create new window - if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 210, NULL, NULL, hInst, NULL)) - { - MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST); - return false; - } - SubscribeToEvents(); - return true; - } - - int RunWin32App () - { - MSG msg; - while (GetMessage (&msg, NULL, 0, 0 )) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - return msg.wParam; - } - - void StopWin32App () - { - HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); - if (hWnd) - PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0); - // UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app - UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL)); - } - - bool GracefulShutdown () - { - HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); - if (hWnd) - PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0); - return hWnd; - } - - bool StopGracefulShutdown () - { - HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); - if (hWnd) - PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0); - return hWnd; - } -} -} +#include +#include +#include +#include +#include "ClientContext.h" +#include "Config.h" +#include "NetDb.hpp" +#include "RouterContext.h" +#include "Transports.h" +#include "Tunnel.h" +#include "version.h" +#include "resource.h" +#include "Daemon.h" +#include "Win32App.h" +#include "Win32NetState.h" + +#define ID_ABOUT 2000 +#define ID_EXIT 2001 +#define ID_CONSOLE 2002 +#define ID_APP 2003 +#define ID_GRACEFUL_SHUTDOWN 2004 +#define ID_STOP_GRACEFUL_SHUTDOWN 2005 +#define ID_RELOAD 2006 +#define ID_ACCEPT_TRANSIT 2007 +#define ID_DECLINE_TRANSIT 2008 + +#define ID_TRAY_ICON 2050 +#define WM_TRAYICON (WM_USER + 1) + +#define IDT_GRACEFUL_SHUTDOWN_TIMER 2100 +#define FRAME_UPDATE_TIMER 2101 +#define IDT_GRACEFUL_TUNNELCHECK_TIMER 2102 + +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) + { + HMENU hPopup = CreatePopupMenu(); + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console"); + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app"); + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About..."); + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + if(!i2p::context.AcceptsTunnels()) + InsertMenu (hPopup, -1, + i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING, + 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 tunnels config"); + if (!i2p::util::DaemonWin32::Instance ().isGraceful) + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown"); + else + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_STOP_GRACEFUL_SHUTDOWN, "Stop &graceful shutdown"); + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit"); + SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE); + SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0); + + POINT p; + if (!curpos) + { + GetCursorPos (&p); + curpos = &p; + } + + WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL); + SendMessage (hWnd, WM_COMMAND, cmd, 0); + + DestroyMenu(hPopup); + } + + static void AddTrayIcon (HWND hWnd) + { + NOTIFYICONDATA nid; + memset(&nid, 0, sizeof(nid)); + nid.cbSize = sizeof(nid); + nid.hWnd = hWnd; + nid.uID = ID_TRAY_ICON; + nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO; + nid.uCallbackMessage = WM_TRAYICON; + nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON)); + strcpy (nid.szTip, "i2pd"); + strcpy (nid.szInfo, "i2pd is starting"); + Shell_NotifyIcon(NIM_ADD, &nid ); + } + + static void RemoveTrayIcon (HWND hWnd) + { + NOTIFYICONDATA nid; + nid.hWnd = hWnd; + nid.uID = ID_TRAY_ICON; + Shell_NotifyIcon (NIM_DELETE, &nid); + } + + static void ShowUptime (std::stringstream& s, int seconds) + { + int num; + + if ((num = seconds / 86400) > 0) { + s << num << " days, "; + seconds -= num * 86400; + } + if ((num = seconds / 3600) > 0) { + s << num << " hours, "; + seconds -= num * 3600; + } + if ((num = seconds / 60) > 0) { + s << num << " min, "; + seconds -= num * 60; + } + s << seconds << " seconds\n"; + } + + template static void ShowTransfered (std::stringstream& s, size transfer) + { + auto bytes = transfer & 0x03ff; + transfer >>= 10; + auto kbytes = transfer & 0x03ff; + transfer >>= 10; + auto mbytes = transfer & 0x03ff; + transfer >>= 10; + auto gbytes = transfer & 0x03ff; + + if (gbytes) + s << gbytes << " GB, "; + if (mbytes) + s << mbytes << " MB, "; + if (kbytes) + s << kbytes << " KB, "; + s << bytes << " Bytes\n"; + } + + static void PrintMainWindowText (std::stringstream& s) + { + s << "\n"; + s << "Status: "; + switch (i2p::context.GetStatus()) + { + case eRouterStatusOK: s << "OK"; break; + case eRouterStatusTesting: s << "Testing"; break; + case eRouterStatusFirewalled: s << "Firewalled"; break; + case eRouterStatusError: + { + switch (i2p::context.GetError()) + { + case eRouterErrorClockSkew: s << "Clock skew"; break; + default: s << "Error"; + } + break; + } + default: s << "Unknown"; + } + s << "; "; + s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n"; + s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ()); + if (GracefulShutdownEndtime != 0) + { + DWORD GracefulTimeLeft = (GracefulShutdownEndtime - GetTickCountLocal()) / 1000; + s << "Graceful shutdown, time left: "; ShowUptime(s, GracefulTimeLeft); + } + else + s << "\n"; + s << "Inbound: " << i2p::transport::transports.GetInBandwidth() / 1024 << " KiB/s; "; + s << "Outbound: " << i2p::transport::transports.GetOutBandwidth() / 1024 << " KiB/s\n"; + s << "Received: "; ShowTransfered (s, i2p::transport::transports.GetTotalReceivedBytes()); + s << "Sent: "; ShowTransfered (s, i2p::transport::transports.GetTotalSentBytes()); + s << "\n"; + s << "Routers: " << i2p::data::netdb.GetNumRouters () << "; "; + s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << "; "; + s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "\n"; + s << "Tunnels: "; + s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; "; + s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; "; + s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n"; + s << "\n"; + } + + static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + static UINT s_uTaskbarRestart; + + switch (uMsg) + { + case WM_CREATE: + { + s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); + AddTrayIcon (hWnd); + break; + } + case WM_CLOSE: + { + RemoveTrayIcon (hWnd); + KillTimer (hWnd, FRAME_UPDATE_TIMER); + KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER); + KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER); + PostQuitMessage (0); + break; + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ID_ABOUT: + { + std::stringstream text; + text << "Version: " << I2PD_VERSION << " " << CODENAME; + MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); + return 0; + } + case ID_EXIT: + { + PostMessage (hWnd, WM_CLOSE, 0, 0); + return 0; + } + case ID_ACCEPT_TRANSIT: + { + i2p::context.SetAcceptsTunnels (true); + std::stringstream text; + text << "I2Pd now accept transit tunnels"; + MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); + return 0; + } + case ID_DECLINE_TRANSIT: + { + i2p::context.SetAcceptsTunnels (false); + std::stringstream text; + text << "I2Pd now decline new transit tunnels"; + MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); + return 0; + } + case ID_GRACEFUL_SHUTDOWN: + { + 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 = GetTickCountLocal() + 10*60*1000; + i2p::util::DaemonWin32::Instance ().isGraceful = true; + return 0; + } + case ID_STOP_GRACEFUL_SHUTDOWN: + { + i2p::context.SetAcceptsTunnels (true); + KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER); + KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER); + GracefulShutdownEndtime = 0; + i2p::util::DaemonWin32::Instance ().isGraceful = false; + return 0; + } + case ID_RELOAD: + { + i2p::client::context.ReloadConfig(); + std::stringstream text; + text << "I2Pd reloading configs..."; + MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK ); + return 0; + } + case ID_CONSOLE: + { + char buf[30]; + std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); + uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); + snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort); + ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL); + return 0; + } + case ID_APP: + { + ShowWindow(hWnd, SW_SHOW); + SetTimer(hWnd, FRAME_UPDATE_TIMER, 3000, NULL); + return 0; + } + } + break; + } + case WM_SYSCOMMAND: + { + switch (wParam) + { + case SC_MINIMIZE: + { + ShowWindow(hWnd, SW_HIDE); + KillTimer (hWnd, FRAME_UPDATE_TIMER); + return 0; + } + case SC_CLOSE: + { + std::string close; i2p::config::GetOption("close", close); + if (0 == close.compare("ask")) + switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?" + " You can add 'close' configuration option. Valid values are: ask, minimize, exit.", + "Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1)) + { + case IDYES: close = "minimize"; break; + case IDNO: close = "exit"; break; + default: return 0; + } + if (0 == close.compare("minimize")) + { + ShowWindow(hWnd, SW_HIDE); + KillTimer (hWnd, FRAME_UPDATE_TIMER); + return 0; + } + if (0 != close.compare("exit")) + { + ::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING); + return 0; + } + } + } + } + case WM_TRAYICON: + { + switch (lParam) + { + case WM_LBUTTONUP: + case WM_RBUTTONUP: + { + SetForegroundWindow (hWnd); + ShowPopupMenu(hWnd, NULL, -1); + PostMessage (hWnd, WM_APP + 1, 0, 0); + break; + } + } + break; + } + case WM_TIMER: + { + switch(wParam) + { + case IDT_GRACEFUL_SHUTDOWN_TIMER: + { + GracefulShutdownEndtime = 0; + PostMessage (hWnd, WM_CLOSE, 0, 0); // exit + return 0; + } + case IDT_GRACEFUL_TUNNELCHECK_TIMER: + { + if (i2p::tunnel::tunnels.CountTransitTunnels() == 0) + PostMessage (hWnd, WM_CLOSE, 0, 0); + else + SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); + return 0; + } + case FRAME_UPDATE_TIMER: + { + InvalidateRect(hWnd, NULL, TRUE); + return 0; + } + } + break; + } + case WM_PAINT: + { + HDC hDC; + PAINTSTRUCT ps; + RECT rp; + HFONT hFont; + std::stringstream s; PrintMainWindowText (s); + hDC = BeginPaint (hWnd, &ps); + GetClientRect(hWnd, &rp); + SetTextColor(hDC, 0x00D43B69); + hFont = CreateFont(18,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,TEXT("Times New Roman")); + SelectObject(hDC,hFont); + DrawText(hDC, TEXT(s.str().c_str()), s.str().length(), &rp, DT_CENTER|DT_VCENTER); + DeleteObject(hFont); + EndPaint(hWnd, &ps); + break; + } + default: + { + if (uMsg == s_uTaskbarRestart) + AddTrayIcon (hWnd); + break; + } + } + return DefWindowProc( hWnd, uMsg, wParam, lParam); + } + + bool StartWin32App () + { + if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"))) + { + MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK); + return false; + } + // register main window + auto hInst = GetModuleHandle(NULL); + WNDCLASSEX wclx; + memset (&wclx, 0, sizeof(wclx)); + wclx.cbSize = sizeof(wclx); + wclx.style = 0; + wclx.lpfnWndProc = WndProc; + //wclx.cbClsExtra = 0; + //wclx.cbWndExtra = 0; + wclx.hInstance = hInst; + wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(MAINICON)); + wclx.hCursor = LoadCursor (NULL, IDC_ARROW); + //wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wclx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wclx.lpszMenuName = NULL; + wclx.lpszClassName = I2PD_WIN32_CLASSNAME; + RegisterClassEx (&wclx); + // create new window + if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 210, NULL, NULL, hInst, NULL)) + { + MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST); + return false; + } + SubscribeToEvents(); + return true; + } + + int RunWin32App () + { + MSG msg; + while (GetMessage (&msg, NULL, 0, 0 )) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + return msg.wParam; + } + + void StopWin32App () + { + HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); + if (hWnd) + PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0); + // UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app + UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL)); + } + + bool GracefulShutdown () + { + HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); + if (hWnd) + PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0); + return hWnd; + } + + bool StopGracefulShutdown () + { + HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); + if (hWnd) + PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0); + return hWnd; + } +} +} diff --git a/Win32/Win32App.h b/Win32/Win32App.h index b230eb06..23082842 100644 --- a/Win32/Win32App.h +++ b/Win32/Win32App.h @@ -1,17 +1,17 @@ -#ifndef WIN32APP_H__ -#define WIN32APP_H__ - -#define I2PD_WIN32_CLASSNAME "i2pd main window" - -namespace i2p -{ -namespace win32 -{ - bool StartWin32App (); - void StopWin32App (); - int RunWin32App (); - bool GracefulShutdown (); - bool StopGracefulShutdown (); -} -} -#endif // WIN32APP_H__ +#ifndef WIN32APP_H__ +#define WIN32APP_H__ + +#define I2PD_WIN32_CLASSNAME "i2pd main window" + +namespace i2p +{ +namespace win32 +{ + bool StartWin32App (); + void StopWin32App (); + int RunWin32App (); + bool GracefulShutdown (); + bool StopGracefulShutdown (); +} +} +#endif // WIN32APP_H__ diff --git a/Win32/Win32Service.h b/Win32/Win32Service.h index 2830d237..05a6b9f9 100644 --- a/Win32/Win32Service.h +++ b/Win32/Win32Service.h @@ -26,48 +26,48 @@ class I2PService { -public: - - I2PService(PSTR pszServiceName, - BOOL fCanStop = TRUE, - BOOL fCanShutdown = TRUE, - BOOL fCanPauseContinue = FALSE); - - virtual ~I2PService(void); - - static BOOL isService(); - static BOOL Run(I2PService &service); - void Stop(); - -protected: - - virtual void OnStart(DWORD dwArgc, PSTR *pszArgv); - virtual void OnStop(); - virtual void OnPause(); - virtual void OnContinue(); - virtual void OnShutdown(); - void SetServiceStatus(DWORD dwCurrentState, - DWORD dwWin32ExitCode = NO_ERROR, - DWORD dwWaitHint = 0); - -private: - - static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv); - static void WINAPI ServiceCtrlHandler(DWORD dwCtrl); - void WorkerThread(); - void Start(DWORD dwArgc, PSTR *pszArgv); - void Pause(); - void Continue(); - void Shutdown(); - static I2PService* s_service; - PSTR m_name; - SERVICE_STATUS m_status; - SERVICE_STATUS_HANDLE m_statusHandle; - - BOOL m_fStopping; - HANDLE m_hStoppedEvent; - - std::thread* _worker; + public: + + I2PService(PSTR pszServiceName, + BOOL fCanStop = TRUE, + BOOL fCanShutdown = TRUE, + BOOL fCanPauseContinue = FALSE); + + virtual ~I2PService(void); + + static BOOL isService(); + static BOOL Run(I2PService &service); + void Stop(); + + protected: + + virtual void OnStart(DWORD dwArgc, PSTR *pszArgv); + virtual void OnStop(); + virtual void OnPause(); + virtual void OnContinue(); + virtual void OnShutdown(); + void SetServiceStatus(DWORD dwCurrentState, + DWORD dwWin32ExitCode = NO_ERROR, + DWORD dwWaitHint = 0); + + private: + + static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv); + static void WINAPI ServiceCtrlHandler(DWORD dwCtrl); + void WorkerThread(); + void Start(DWORD dwArgc, PSTR *pszArgv); + void Pause(); + void Continue(); + void Shutdown(); + static I2PService* s_service; + PSTR m_name; + SERVICE_STATUS m_status; + SERVICE_STATUS_HANDLE m_statusHandle; + + BOOL m_fStopping; + HANDLE m_hStoppedEvent; + + std::thread* _worker; }; void InstallService( @@ -77,8 +77,8 @@ void InstallService( PCSTR pszDependencies, PCSTR pszAccount, PCSTR pszPassword - ); +); void UninstallService(PCSTR pszServiceName); -#endif // WIN_32_SERVICE_H__ \ No newline at end of file +#endif // WIN_32_SERVICE_H__ diff --git a/Win32/resource.h b/Win32/resource.h index 3b188481..daa1ddcb 100644 --- a/Win32/resource.h +++ b/Win32/resource.h @@ -1,11 +1,11 @@ -//{{NO_DEPENDENCIES}} -#define MAINICON 101 - -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +#define MAINICON 101 + +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index fc71123f..dd302fce 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -127,8 +127,8 @@ namespace i2p i2p::context.SetNetID (netID); i2p::context.Init (); - bool ipv6; i2p::config::GetOption("ipv6", ipv6); - bool ipv4; i2p::config::GetOption("ipv4", ipv4); + bool ipv6; i2p::config::GetOption("ipv6", ipv6); + bool ipv4; i2p::config::GetOption("ipv4", ipv4); #ifdef MESHNET // manual override for meshnet ipv4 = false; @@ -143,8 +143,8 @@ namespace i2p i2p::context.SetSupportsV6 (ipv6); i2p::context.SetSupportsV4 (ipv4); - bool ntcp; i2p::config::GetOption("ntcp", ntcp); - i2p::context.PublishNTCPAddress (ntcp, !ipv6); + bool ntcp; i2p::config::GetOption("ntcp", ntcp); + i2p::context.PublishNTCPAddress (ntcp, !ipv6); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) { @@ -172,10 +172,13 @@ namespace i2p SetMaxNumTransitTunnels (transitTunnels); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); - if (isFloodfill) { + if (isFloodfill) + { LogPrint(eLogInfo, "Daemon: router will be floodfill"); i2p::context.SetFloodfill (true); - } else { + } + else + { i2p::context.SetFloodfill (false); } @@ -243,7 +246,8 @@ namespace i2p i2p::transport::transports.RestrictRoutesToFamilies(fams); restricted = fams.size() > 0; } - if (routers.length() > 0) { + if (routers.length() > 0) + { std::set idents; size_t pos = 0, comma; do @@ -279,7 +283,8 @@ namespace i2p i2p::data::netdb.Start(); bool upnp; i2p::config::GetOption("upnp.enabled", upnp); - if (upnp) { + if (upnp) + { d.UPnP = std::unique_ptr(new i2p::transport::UPnP); d.UPnP->Start (); } @@ -292,15 +297,15 @@ namespace i2p } bool ntcp; i2p::config::GetOption("ntcp", ntcp); - bool ssu; i2p::config::GetOption("ssu", ssu); + bool ssu; i2p::config::GetOption("ssu", ssu); LogPrint(eLogInfo, "Daemon: starting Transports"); if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled"); i2p::transport::transports.Start(ntcp, ssu); - if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2()) + if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2()) LogPrint(eLogInfo, "Daemon: Transports started"); - else + else { LogPrint(eLogError, "Daemon: failed to start Transports"); /** shut down netdb right away */ @@ -310,23 +315,23 @@ namespace i2p } bool http; i2p::config::GetOption("http.enabled", http); - if (http) { + if (http) + { std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort); - try + try { d.httpServer = std::unique_ptr(new i2p::http::HTTPServer(httpAddr, httpPort)); d.httpServer->Start(); - } - catch (std::exception& ex) + } + catch (std::exception& ex) { LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ()); ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ()); } } - LogPrint(eLogInfo, "Daemon: starting Tunnels"); i2p::tunnel::tunnels.Start(); @@ -339,12 +344,12 @@ namespace i2p std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr); uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort); LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort); - try + try { d.m_I2PControlService = std::unique_ptr(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort)); d.m_I2PControlService->Start (); - } - catch (std::exception& ex) + } + catch (std::exception& ex) { LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ()); ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ()); @@ -361,7 +366,7 @@ namespace i2p LogPrint(eLogInfo, "Daemon: stopping Tunnels"); i2p::tunnel::tunnels.Stop(); - if (d.UPnP) + if (d.UPnP) { d.UPnP->Stop (); d.UPnP = nullptr; diff --git a/daemon/Daemon.h b/daemon/Daemon.h index 1745b980..050cc7e8 100644 --- a/daemon/Daemon.h +++ b/daemon/Daemon.h @@ -13,9 +13,10 @@ namespace util class Daemon_Singleton { public: - virtual bool init(int argc, char* argv[], std::shared_ptr logstream); - virtual bool init(int argc, char* argv[]); - virtual bool start(); + + virtual bool init(int argc, char* argv[], std::shared_ptr logstream); + virtual bool init(int argc, char* argv[]); + virtual bool start(); virtual bool stop(); virtual void run () {}; @@ -23,6 +24,7 @@ namespace util bool running; protected: + Daemon_Singleton(); virtual ~Daemon_Singleton(); @@ -39,6 +41,7 @@ namespace util class DaemonQT: public i2p::util::Daemon_Singleton { public: + static DaemonQT& Instance() { static DaemonQT instance; @@ -51,6 +54,7 @@ namespace util class DaemonWin32 : public Daemon_Singleton { public: + static DaemonWin32& Instance() { static DaemonWin32 instance; @@ -72,6 +76,7 @@ namespace util class DaemonAndroid: public i2p::util::Daemon_Singleton { public: + static DaemonAndroid& Instance() { static DaemonAndroid instance; @@ -83,6 +88,7 @@ namespace util class DaemonLinux : public Daemon_Singleton { public: + static DaemonLinux& Instance() { static DaemonLinux instance; @@ -94,10 +100,12 @@ namespace util void run (); private: + std::string pidfile; int pidFH; public: + int gracefulShutdownInterval; // in seconds }; #endif diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index de052a2b..6f903e7e 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -892,8 +892,8 @@ namespace http { void HTTPConnection::Receive () { m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE), - std::bind(&HTTPConnection::HandleReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2)); + std::bind(&HTTPConnection::HandleReceive, shared_from_this (), + std::placeholders::_1, std::placeholders::_2)); } void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index abc4fea5..fe62c271 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -79,17 +79,17 @@ namespace http std::string m_Hostname; }; - //all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml - enum OutputFormatEnum { forWebConsole, forQtUi }; - void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat); - void ShowLocalDestinations (std::stringstream& s); - void ShowLeasesSets(std::stringstream& s); - void ShowTunnels (std::stringstream& s); - void ShowTransitTunnels (std::stringstream& s); - void ShowTransports (std::stringstream& s); - void ShowSAMSessions (std::stringstream& s); - void ShowI2PTunnels (std::stringstream& s); - void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token); + //all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml + enum OutputFormatEnum { forWebConsole, forQtUi }; + void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat); + void ShowLocalDestinations (std::stringstream& s); + void ShowLeasesSets(std::stringstream& s); + void ShowTunnels (std::stringstream& s); + void ShowTransitTunnels (std::stringstream& s); + void ShowTransports (std::stringstream& s); + void ShowSAMSessions (std::stringstream& s); + void ShowI2PTunnels (std::stringstream& s); + void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token); } // http } // i2p diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index acf054f1..fb00dc29 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -59,29 +59,28 @@ namespace client m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem); // handlers - m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler; - m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler; - m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler; - m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler; - m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler; - m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler; - m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler; + m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler; + m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler; + m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler; + m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler; + m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler; + m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler; + m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler; // I2PControl m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler; // RouterInfo - m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler; - m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler; - m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler; - m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler; - m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler; - m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S; - m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S; - m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler; + m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler; + m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler; + m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler; + m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler; + m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler; + m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S; + m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S; + m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler; m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler; - m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = -&I2PControlService::TunnelsSuccessRateHandler; + m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler; m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes; m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes; @@ -97,10 +96,10 @@ namespace client // ClientServicesInfo m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler; m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler; - m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler; - m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler; - m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler; - m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler; + m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler; + m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler; + m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler; + m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler; } I2PControlService::~I2PControlService () @@ -401,8 +400,8 @@ namespace client auto it1 = m_RouterInfoHandlers.find (it->first); if (it1 != m_RouterInfoHandlers.end ()) { - if (!first) results << ","; - else first = false; + if (!first) results << ","; + else first = false; (this->*(it1->second))(results); } else @@ -500,7 +499,7 @@ namespace client m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent m_ShutdownTimer.async_wait ( [](const boost::system::error_code& ecode) - { + { Daemon.running = 0; }); } @@ -514,7 +513,7 @@ namespace client m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second m_ShutdownTimer.async_wait ( [](const boost::system::error_code& ecode) - { + { Daemon.running = 0; }); } diff --git a/daemon/I2PControl.h b/daemon/I2PControl.h index 3233ad12..eb28af76 100644 --- a/daemon/I2PControl.h +++ b/daemon/I2PControl.h @@ -27,6 +27,7 @@ namespace client class I2PControlService { typedef boost::asio::ssl::stream ssl_socket; + public: I2PControlService (const std::string& address, int port); diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index b2ebb005..92e79c11 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -80,10 +80,10 @@ namespace transport void UPnP::Discover () { bool isError; - int err; + int err; #if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS)) - err = UPNPDISCOVER_SUCCESS; + err = UPNPDISCOVER_SUCCESS; #if (MINIUPNPC_API_VERSION >= 14) m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err); @@ -92,9 +92,9 @@ namespace transport #endif isError = err != UPNPDISCOVER_SUCCESS; -#else // MINIUPNPC_API_VERSION >= 8 - err = 0; - m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0); +#else // MINIUPNPC_API_VERSION >= 8 + err = 0; + m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0); isError = m_Devlist == NULL; #endif // MINIUPNPC_API_VERSION >= 8 { @@ -105,15 +105,15 @@ namespace transport if (isError) { - LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err); + LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err); return; } err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr)); - m_upnpUrlsInitialized=err!=0; + m_upnpUrlsInitialized = err != 0; if (err == UPNP_IGD_VALID_CONNECTED) { - err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); + err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); if(err != UPNPCOMMAND_SUCCESS) { LogPrint (eLogError, "UPnP: unable to get external address: error ", err); @@ -124,14 +124,14 @@ namespace transport LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL); if (!m_externalIPAddress[0]) { - LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address"); + LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address"); return; } } } else { - LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err); + LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err); return; } @@ -182,7 +182,7 @@ namespace transport err = CheckMapping (strPort.c_str (), strType.c_str ()); if (err != UPNPCOMMAND_SUCCESS) // if mapping not found { - LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err); + LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err); #if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS)) err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL); @@ -202,7 +202,7 @@ namespace transport } else { - LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device"); + LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device"); return; } } @@ -219,14 +219,14 @@ namespace transport void UPnP::CloseMapping (std::shared_ptr address) { - if(!m_upnpUrlsInitialized) { - return; - } + if(!m_upnpUrlsInitialized) { + return; + } std::string strType (GetProto (address)), strPort (std::to_string (address->port)); int err = UPNPCOMMAND_SUCCESS; - + err = CheckMapping (strPort.c_str (), strType.c_str ()); - if (err == UPNPCOMMAND_SUCCESS) + if (err == UPNPCOMMAND_SUCCESS) { err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL); LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err); @@ -237,11 +237,11 @@ namespace transport { freeUPNPDevlist (m_Devlist); m_Devlist = 0; - if(m_upnpUrlsInitialized){ - FreeUPNPUrls (&m_upnpUrls); - m_upnpUrlsInitialized=false; - } - } + if(m_upnpUrlsInitialized){ + FreeUPNPUrls (&m_upnpUrls); + m_upnpUrlsInitialized=false; + } + } std::string UPnP::GetProto (std::shared_ptr address) { diff --git a/daemon/UPnP.h b/daemon/UPnP.h index e66f0aff..29f9e3e6 100644 --- a/daemon/UPnP.h +++ b/daemon/UPnP.h @@ -33,41 +33,41 @@ namespace transport { public: - UPnP (); - ~UPnP (); - void Close (); + UPnP (); + ~UPnP (); + void Close (); - void Start (); - void Stop (); + void Start (); + void Stop (); private: - void Discover (); - int CheckMapping (const char* port, const char* type); - void PortMapping (); - void TryPortMapping (std::shared_ptr address); - void CloseMapping (); - void CloseMapping (std::shared_ptr address); + void Discover (); + int CheckMapping (const char* port, const char* type); + void PortMapping (); + void TryPortMapping (std::shared_ptr address); + void CloseMapping (); + void CloseMapping (std::shared_ptr address); - void Run (); - std::string GetProto (std::shared_ptr address); + void Run (); + std::string GetProto (std::shared_ptr address); private: - bool m_IsRunning; - std::unique_ptr m_Thread; - std::condition_variable m_Started; - std::mutex m_StartedMutex; - boost::asio::io_service m_Service; - boost::asio::deadline_timer m_Timer; - bool m_upnpUrlsInitialized=false; - struct UPNPUrls m_upnpUrls; - struct IGDdatas m_upnpData; - - // For miniupnpc - struct UPNPDev * m_Devlist = 0; - char m_NetworkAddr[64]; - char m_externalIPAddress[40]; + bool m_IsRunning; + std::unique_ptr m_Thread; + std::condition_variable m_Started; + std::mutex m_StartedMutex; + boost::asio::io_service m_Service; + boost::asio::deadline_timer m_Timer; + bool m_upnpUrlsInitialized = false; + struct UPNPUrls m_upnpUrls; + struct IGDdatas m_upnpData; + + // For miniupnpc + struct UPNPDev * m_Devlist = 0; + char m_NetworkAddr[64]; + char m_externalIPAddress[40]; }; } } @@ -79,10 +79,10 @@ namespace transport { class UPnP { public: - UPnP () {}; - ~UPnP () {}; - void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); } - void Stop () {}; + UPnP () {}; + ~UPnP () {}; + void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); } + void Stop () {}; }; } } diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index b7af779c..a59fc693 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -196,5 +196,4 @@ namespace i2p } } } - #endif diff --git a/daemon/i2pd.cpp b/daemon/i2pd.cpp index 425c2560..7b68c073 100644 --- a/daemon/i2pd.cpp +++ b/daemon/i2pd.cpp @@ -2,7 +2,6 @@ #include "Daemon.h" #if defined(QT_GUI_LIB) - namespace i2p { namespace qt @@ -10,11 +9,11 @@ namespace qt int RunQT (int argc, char* argv[]); } } + int main( int argc, char* argv[] ) { return i2p::qt::RunQT (argc, argv); } - #else int main( int argc, char* argv[] ) { diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index f80f2751..51f5f225 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -7,7 +7,8 @@ namespace i2p { namespace data { - static const char T32[32] = { + static const char T32[32] = + { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', @@ -29,15 +30,16 @@ namespace data * Direct Substitution Table */ - static const char T64[64] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '-', '~' + static const char T64[64] = + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '-', '~' }; const char * GetBase64SubstitutionTable () @@ -67,14 +69,12 @@ namespace data * */ - size_t /* Number of bytes in the encoded buffer */ - ByteStreamToBase64 ( - const uint8_t * InBuffer, /* Input buffer, binary data */ - size_t InCount, /* Number of bytes in the input buffer */ - char * OutBuffer, /* output buffer */ - size_t len /* length of output buffer */ + size_t ByteStreamToBase64 ( /* Number of bytes in the encoded buffer */ + const uint8_t * InBuffer, /* Input buffer, binary data */ + size_t InCount, /* Number of bytes in the input buffer */ + char * OutBuffer, /* output buffer */ + size_t len /* length of output buffer */ ) - { unsigned char * ps; unsigned char * pd; @@ -83,55 +83,60 @@ namespace data int i; int n; int m; - size_t outCount; + size_t outCount; ps = (unsigned char *)InBuffer; - n = InCount/3; - m = InCount%3; + n = InCount / 3; + m = InCount % 3; if (!m) - outCount = 4*n; + outCount = 4 * n; else - outCount = 4*(n+1); + outCount = 4 * (n + 1); + if (outCount > len) return 0; + pd = (unsigned char *)OutBuffer; - for ( i = 0; i>= 2; /* base64 digit #1 */ - *pd++ = T64[acc_1]; - acc_1 = *ps++; - acc_2 |= acc_1 >> 4; /* base64 digit #2 */ - *pd++ = T64[acc_2]; - acc_1 &= 0x0f; - acc_1 <<=2; - acc_2 = *ps++; - acc_1 |= acc_2>>6; /* base64 digit #3 */ - *pd++ = T64[acc_1]; - acc_2 &= 0x3f; /* base64 digit #4 */ - *pd++ = T64[acc_2]; + for ( i = 0; i < n; i++ ) + { + acc_1 = *ps++; + acc_2 = (acc_1 << 4) & 0x30; + acc_1 >>= 2; /* base64 digit #1 */ + *pd++ = T64[acc_1]; + acc_1 = *ps++; + acc_2 |= acc_1 >> 4; /* base64 digit #2 */ + *pd++ = T64[acc_2]; + acc_1 &= 0x0f; + acc_1 <<= 2; + acc_2 = *ps++; + acc_1 |= acc_2 >> 6; /* base64 digit #3 */ + *pd++ = T64[acc_1]; + acc_2 &= 0x3f; /* base64 digit #4 */ + *pd++ = T64[acc_2]; } - if ( m == 1 ){ - acc_1 = *ps++; - acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */ - acc_1 >>= 2; /* base64 digit #1 */ - *pd++ = T64[acc_1]; - *pd++ = T64[acc_2]; - *pd++ = P64; - *pd++ = P64; + if ( m == 1 ) + { + acc_1 = *ps++; + acc_2 = (acc_1 << 4) & 0x3f; /* base64 digit #2 */ + acc_1 >>= 2; /* base64 digit #1 */ + *pd++ = T64[acc_1]; + *pd++ = T64[acc_2]; + *pd++ = P64; + *pd++ = P64; } - else if ( m == 2 ){ - acc_1 = *ps++; - acc_2 = (acc_1<<4)&0x3f; - acc_1 >>= 2; /* base64 digit #1 */ - *pd++ = T64[acc_1]; - acc_1 = *ps++; - acc_2 |= acc_1 >> 4; /* base64 digit #2 */ - *pd++ = T64[acc_2]; - acc_1 &= 0x0f; - acc_1 <<=2; /* base64 digit #3 */ - *pd++ = T64[acc_1]; - *pd++ = P64; + else if ( m == 2 ) + { + acc_1 = *ps++; + acc_2 = (acc_1 << 4) & 0x3f; + acc_1 >>= 2; /* base64 digit #1 */ + *pd++ = T64[acc_1]; + acc_1 = *ps++; + acc_2 |= acc_1 >> 4; /* base64 digit #2 */ + *pd++ = T64[acc_2]; + acc_1 &= 0x0f; + acc_1 <<= 2; /* base64 digit #3 */ + *pd++ = T64[acc_1]; + *pd++ = P64; } return outCount; @@ -147,12 +152,11 @@ namespace data * */ - size_t /* Number of output bytes */ - Base64ToByteStream ( - const char * InBuffer, /* BASE64 encoded buffer */ - size_t InCount, /* Number of input bytes */ - uint8_t * OutBuffer, /* output buffer length */ - size_t len /* length of output buffer */ + size_t Base64ToByteStream ( /* Number of output bytes */ + const char * InBuffer, /* BASE64 encoded buffer */ + size_t InCount, /* Number of input bytes */ + uint8_t * OutBuffer, /* output buffer length */ + size_t len /* length of output buffer */ ) { unsigned char * ps; @@ -162,42 +166,52 @@ namespace data int i; int n; int m; - size_t outCount; + size_t outCount; + + if (isFirstTime) + iT64Build(); + + n = InCount / 4; + m = InCount % 4; - if (isFirstTime) iT64Build(); - n = InCount/4; - m = InCount%4; if (InCount && !m) - outCount = 3*n; - else { - outCount = 0; - return 0; + outCount = 3 * n; + else + { + outCount = 0; + return 0; } ps = (unsigned char *)(InBuffer + InCount - 1); - while ( *ps-- == P64 ) outCount--; + while ( *ps-- == P64 ) + outCount--; ps = (unsigned char *)InBuffer; - if (outCount > len) return -1; + if (outCount > len) + return -1; + pd = OutBuffer; auto endOfOutBuffer = OutBuffer + outCount; - for ( i = 0; i < n; i++ ){ - acc_1 = iT64[*ps++]; - acc_2 = iT64[*ps++]; - acc_1 <<= 2; - acc_1 |= acc_2>>4; - *pd++ = acc_1; - if (pd >= endOfOutBuffer) break; - - acc_2 <<= 4; - acc_1 = iT64[*ps++]; - acc_2 |= acc_1 >> 2; - *pd++ = acc_2; - if (pd >= endOfOutBuffer) break; - - acc_2 = iT64[*ps++]; - acc_2 |= acc_1 << 6; - *pd++ = acc_2; + for ( i = 0; i < n; i++ ) + { + acc_1 = iT64[*ps++]; + acc_2 = iT64[*ps++]; + acc_1 <<= 2; + acc_1 |= acc_2 >> 4; + *pd++ = acc_1; + if (pd >= endOfOutBuffer) + break; + + acc_2 <<= 4; + acc_1 = iT64[*ps++]; + acc_2 |= acc_1 >> 2; + *pd++ = acc_2; + if (pd >= endOfOutBuffer) + break; + + acc_2 = iT64[*ps++]; + acc_2 |= acc_1 << 6; + *pd++ = acc_2; } return outCount; @@ -206,20 +220,25 @@ namespace data size_t Base64EncodingBufferSize (const size_t input_size) { auto d = div (input_size, 3); - if (d.rem) d.quot++; - return 4*d.quot; + if (d.rem) + d.quot++; + + return 4 * d.quot; } std::string ToBase64Standard (const std::string& in) { - auto len = Base64EncodingBufferSize (in.length ()); - char * str = new char[len+1]; + auto len = Base64EncodingBufferSize (in.length ()); + char * str = new char[len + 1]; auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len); str[l] = 0; // replace '-' by '+' and '~' by '/' for (size_t i = 0; i < l; i++) - if (str[i] == '-') str[i] = '+'; - else if (str[i] == '~') str[i] = '/'; + if (str[i] == '-') + str[i] = '+'; + else if (str[i] == '~') + str[i] = '/'; + std::string s(str); delete[] str; return s; @@ -236,10 +255,10 @@ namespace data static void iT64Build() { - int i; + int i; isFirstTime = 0; - for ( i=0; i<256; i++ ) iT64[i] = -1; - for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i; + for ( i = 0; i < 256; i++ ) iT64[i] = -1; + for ( i = 0; i < 64; i++ ) iT64[(int)T64[i]] = i; iT64[(int)P64] = 0; } @@ -302,4 +321,3 @@ namespace data } } } - diff --git a/libi2pd/Base.h b/libi2pd/Base.h index a273f468..5d550092 100644 --- a/libi2pd/Base.h +++ b/libi2pd/Base.h @@ -15,13 +15,13 @@ namespace data { size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); - /** - Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes - */ + /** + Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes + */ size_t Base64EncodingBufferSize(const size_t input_size); - - std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization - + + std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization + } // data } // i2p diff --git a/libi2pd/Blinding.cpp b/libi2pd/Blinding.cpp index 8d3f4b40..287d3648 100644 --- a/libi2pd/Blinding.cpp +++ b/libi2pd/Blinding.cpp @@ -17,21 +17,21 @@ namespace i2p namespace data { static EC_POINT * BlindPublicKeyECDSA (const EC_GROUP * group, const EC_POINT * pub, const uint8_t * seed) - { + { BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); - BIGNUM * q = BN_CTX_get (ctx); + BIGNUM * q = BN_CTX_get (ctx); EC_GROUP_get_order (group, q, ctx); // calculate alpha = seed mod q BIGNUM * alpha = BN_CTX_get (ctx); - BN_bin2bn (seed, 64, alpha); // seed is in BigEndian + BN_bin2bn (seed, 64, alpha); // seed is in BigEndian BN_mod (alpha, alpha, q, ctx); // % q // A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha) auto p = EC_POINT_new (group); EC_POINT_mul (group, p, alpha, nullptr, nullptr, ctx); // B*alpha EC_POINT_add (group, p, pub, p, ctx); // pub + B*alpha BN_CTX_end (ctx); - BN_CTX_free (ctx); + BN_CTX_free (ctx); return p; } @@ -39,18 +39,18 @@ namespace data { BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); - BIGNUM * q = BN_CTX_get (ctx); + BIGNUM * q = BN_CTX_get (ctx); EC_GROUP_get_order (group, q, ctx); // calculate alpha = seed mod q BIGNUM * alpha = BN_CTX_get (ctx); - BN_bin2bn (seed, 64, alpha); // seed is in BigEndian - BN_mod (alpha, alpha, q, ctx); // % q + BN_bin2bn (seed, 64, alpha); // seed is in BigEndian + BN_mod (alpha, alpha, q, ctx); // % q BN_add (alpha, alpha, priv); // alpha = alpha + priv - // a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod q + // a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod q BN_mod (blindedPriv, alpha, q, ctx); // % q BN_CTX_end (ctx); BN_CTX_free (ctx); - } + } static void BlindEncodedPublicKeyECDSA (size_t publicKeyLen, const EC_GROUP * group, const uint8_t * pub, const uint8_t * seed, uint8_t * blindedPub) { @@ -63,7 +63,7 @@ namespace data EC_POINT_get_affine_coordinates_GFp (group, p1, x, y, NULL); EC_POINT_free (p1); i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2); - i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2); + i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2); BN_free (x); BN_free (y); } @@ -85,7 +85,7 @@ namespace data i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2); i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2); BN_free (x); BN_free (y); - } + } template static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args) @@ -97,7 +97,7 @@ namespace data { case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256: { - publicKeyLength = i2p::crypto::ECDSAP256_KEY_LENGTH; + publicKeyLength = i2p::crypto::ECDSAP256_KEY_LENGTH; group = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1); break; } @@ -116,18 +116,18 @@ namespace data default: LogPrint (eLogError, "Blinding: signature type ", (int)sigType, " is not ECDSA"); } - if (group) + if (group) { blind (publicKeyLength, group, key, seed, std::forward(args)...); EC_GROUP_free (group); - } + } return publicKeyLength; } //---------------------------------------------------------- const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01; - const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now + const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04; BlindedPublicKey::BlindedPublicKey (std::shared_ptr identity, bool clientAuth): @@ -138,7 +138,7 @@ namespace data m_PublicKey.resize (len); memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len); m_SigType = identity->GetSigningKeyType (); - m_BlindedSigType = m_SigType; + m_BlindedSigType = m_SigType; } BlindedPublicKey::BlindedPublicKey (const std::string& b33): @@ -150,12 +150,12 @@ namespace data { LogPrint (eLogError, "Blinding: malformed b33 ", b33); return; - } - uint32_t checksum = crc32 (0, addr + 3, l - 3); + } + uint32_t checksum = crc32 (0, addr + 3, l - 3); // checksum is Little Endian - addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16); + addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16); uint8_t flags = addr[0]; - size_t offset = 1; + size_t offset = 1; if (flags & B33_TWO_BYTES_SIGTYPE_FLAG) // two bytes signatures { m_SigType = bufbe16toh (addr + offset); offset += 2; @@ -178,7 +178,7 @@ namespace data memcpy (m_PublicKey.data (), addr + offset, len); } else - LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType); + LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType); } else LogPrint (eLogError, "Blinding: unknown signature type ", (int)m_SigType, " in b33"); @@ -189,25 +189,25 @@ namespace data if (m_PublicKey.size () > 32) return ""; // assume 25519 uint8_t addr[35]; char str[60]; // TODO: define actual length uint8_t flags = 0; - if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG; + if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG; addr[0] = flags; // flags addr[1] = m_SigType; // sig type addr[2] = m_BlindedSigType; // blinded sig type memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ()); - uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ()); + uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ()); // checksum is Little Endian - addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16); + addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16); auto l = ByteStreamToBase32 (addr, m_PublicKey.size () + 3, str, 60); return std::string (str, str + l); } void BlindedPublicKey::GetCredential (uint8_t * credential) const { - // A = destination's signing public key + // A = destination's signing public key // stA = signature type of A, 2 bytes big endian uint16_t stA = htobe16 (GetSigType ()); // stA1 = signature type of blinded A, 2 bytes big endian - uint16_t stA1 = htobe16 (GetBlindedSigType ()); + uint16_t stA1 = htobe16 (GetBlindedSigType ()); // credential = H("credential", A || stA || stA1) H ("credential", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, credential); } @@ -224,15 +224,15 @@ namespace data { uint16_t stA = htobe16 (GetSigType ()), stA1 = htobe16 (GetBlindedSigType ()); uint8_t salt[32]; - //seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64) + //seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64) H ("I2PGenerateAlpha", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt); i2p::crypto::HKDF (salt, (const uint8_t *)date, 8, "i2pblinding1", seed); } size_t BlindedPublicKey::GetBlindedKey (const char * date, uint8_t * blindedKey) const { - uint8_t seed[64]; - GenerateAlpha (date, seed); + uint8_t seed[64]; + GenerateAlpha (date, seed); size_t publicKeyLength = 0; switch (m_SigType) @@ -244,7 +244,7 @@ namespace data break; case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: - i2p::crypto::GetEd25519 ()->BlindPublicKey (GetPublicKey (), seed, blindedKey); + i2p::crypto::GetEd25519 ()->BlindPublicKey (GetPublicKey (), seed, blindedKey); publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; break; default: @@ -255,8 +255,8 @@ namespace data size_t BlindedPublicKey::BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const { - uint8_t seed[64]; - GenerateAlpha (date, seed); + uint8_t seed[64]; + GenerateAlpha (date, seed); size_t publicKeyLength = 0; switch (m_SigType) { @@ -272,15 +272,15 @@ namespace data default: LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType); } - return publicKeyLength; + return publicKeyLength; } - void BlindedPublicKey::H (const std::string& p, const std::vector >& bufs, uint8_t * hash) const + void BlindedPublicKey::H (const std::string& p, const std::vector >& bufs, uint8_t * hash) const { SHA256_CTX ctx; SHA256_Init (&ctx); SHA256_Update (&ctx, p.c_str (), p.length ()); - for (const auto& it: bufs) + for (const auto& it: bufs) SHA256_Update (&ctx, it.first, it.second); SHA256_Final (hash, &ctx); } @@ -289,15 +289,15 @@ namespace data { i2p::data::IdentHash hash; uint8_t blinded[128]; - size_t publicKeyLength = 0; + size_t publicKeyLength = 0; if (date) publicKeyLength = GetBlindedKey (date, blinded); else { char currentDate[9]; i2p::util::GetCurrentDate (currentDate); - publicKeyLength = GetBlindedKey (currentDate, blinded); - } + publicKeyLength = GetBlindedKey (currentDate, blinded); + } if (publicKeyLength) { auto stA1 = htobe16 (m_BlindedSigType); @@ -308,10 +308,9 @@ namespace data SHA256_Final ((uint8_t *)hash, &ctx); } else - LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported"); + LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported"); return hash; } } } - diff --git a/libi2pd/Blinding.h b/libi2pd/Blinding.h index 65b8c0f8..3e0ad3fc 100644 --- a/libi2pd/Blinding.h +++ b/libi2pd/Blinding.h @@ -15,7 +15,7 @@ namespace data public: BlindedPublicKey (std::shared_ptr identity, bool clientAuth = false); - BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p + BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p std::string ToB33 () const; const uint8_t * GetPublicKey () const { return m_PublicKey.data (); }; @@ -25,14 +25,14 @@ namespace data bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes - size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length - size_t BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const; // date is 8 chars "YYYYMMDD", return public key length + size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length + size_t BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const; // date is 8 chars "YYYYMMDD", return public key length i2p::data::IdentHash GetStoreHash (const char * date = nullptr) const; // date is 8 chars "YYYYMMDD", use current if null private: void GetCredential (uint8_t * credential) const; // 32 bytes - void GenerateAlpha (const char * date, uint8_t * seed) const; // 64 bytes, date is 8 chars "YYYYMMDD" + void GenerateAlpha (const char * date, uint8_t * seed) const; // 64 bytes, date is 8 chars "YYYYMMDD" void H (const std::string& p, const std::vector >& bufs, uint8_t * hash) const; private: diff --git a/libi2pd/CPU.h b/libi2pd/CPU.h index b4c19607..e1fd450c 100644 --- a/libi2pd/CPU.h +++ b/libi2pd/CPU.h @@ -5,10 +5,10 @@ namespace i2p { namespace cpu { - extern bool aesni; - extern bool avx; + extern bool aesni; + extern bool avx; - void Detect(); + void Detect(); } } diff --git a/libi2pd/ChaCha20.cpp b/libi2pd/ChaCha20.cpp index 222111b7..1d1e9bc6 100644 --- a/libi2pd/ChaCha20.cpp +++ b/libi2pd/ChaCha20.cpp @@ -12,73 +12,72 @@ #include "I2PEndian.h" #include "ChaCha20.h" -#if !OPENSSL_AEAD_CHACHA20_POLY1305 +#if !OPENSSL_AEAD_CHACHA20_POLY1305 namespace i2p { namespace crypto { namespace chacha { -void u32t8le(uint32_t v, uint8_t * p) +void u32t8le(uint32_t v, uint8_t * p) { - p[0] = v & 0xff; - p[1] = (v >> 8) & 0xff; - p[2] = (v >> 16) & 0xff; - p[3] = (v >> 24) & 0xff; + p[0] = v & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; } -uint32_t u8t32le(const uint8_t * p) +uint32_t u8t32le(const uint8_t * p) { - uint32_t value = p[3]; + uint32_t value = p[3]; - value = (value << 8) | p[2]; - value = (value << 8) | p[1]; - value = (value << 8) | p[0]; + value = (value << 8) | p[2]; + value = (value << 8) | p[1]; + value = (value << 8) | p[0]; - return value; + return value; } -uint32_t rotl32(uint32_t x, int n) +uint32_t rotl32(uint32_t x, int n) { - return x << n | (x >> (-n & 31)); + return x << n | (x >> (-n & 31)); } -void quarterround(uint32_t *x, int a, int b, int c, int d) +void quarterround(uint32_t *x, int a, int b, int c, int d) { - x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); - x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); - x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); - x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); + x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); + x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); + x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); + x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); } void Chacha20Block::operator << (const Chacha20State & st) { int i; - for (i = 0; i < 16; i++) + for (i = 0; i < 16; i++) u32t8le(st.data[i], data + (i << 2)); } void block (Chacha20State &input, int rounds) { - int i; - Chacha20State x; - x.Copy(input); - - for (i = rounds; i > 0; i -= 2) - { - quarterround(x.data, 0, 4, 8, 12); - quarterround(x.data, 1, 5, 9, 13); - quarterround(x.data, 2, 6, 10, 14); - quarterround(x.data, 3, 7, 11, 15); - quarterround(x.data, 0, 5, 10, 15); - quarterround(x.data, 1, 6, 11, 12); - quarterround(x.data, 2, 7, 8, 13); - quarterround(x.data, 3, 4, 9, 14); - } - x += input; - input.block << x; + int i; + Chacha20State x; + x.Copy(input); + for (i = rounds; i > 0; i -= 2) + { + quarterround(x.data, 0, 4, 8, 12); + quarterround(x.data, 1, 5, 9, 13); + quarterround(x.data, 2, 6, 10, 14); + quarterround(x.data, 3, 7, 11, 15); + quarterround(x.data, 0, 5, 10, 15); + quarterround(x.data, 1, 6, 11, 12); + quarterround(x.data, 2, 7, 8, 13); + quarterround(x.data, 3, 4, 9, 14); + } + x += input; + input.block << x; } void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter) @@ -87,52 +86,52 @@ void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * state.data[1] = 0x3320646e; state.data[2] = 0x79622d32; state.data[3] = 0x6b206574; - for (size_t i = 0; i < 8; i++) - state.data[4 + i] = chacha::u8t32le(key + i * 4); - + for (size_t i = 0; i < 8; i++) + state.data[4 + i] = chacha::u8t32le(key + i * 4); + state.data[12] = htole32 (counter); - for (size_t i = 0; i < 3; i++) - state.data[13 + i] = chacha::u8t32le(nonce + i * 4); + for (size_t i = 0; i < 3; i++) + state.data[13 + i] = chacha::u8t32le(nonce + i * 4); } void Chacha20SetCounter (Chacha20State& state, uint32_t counter) { state.data[12] = htole32 (counter); state.offset = 0; -} +} void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz) -{ +{ if (state.offset > 0) { - // previous block if any - auto s = chacha::blocksize - state.offset; + // previous block if any + auto s = chacha::blocksize - state.offset; if (sz < s) s = sz; for (size_t i = 0; i < s; i++) buf[i] ^= state.block.data[state.offset + i]; buf += s; sz -= s; state.offset += s; - if (state.offset >= chacha::blocksize) state.offset = 0; + if (state.offset >= chacha::blocksize) state.offset = 0; } - for (size_t i = 0; i < sz; i += chacha::blocksize) + for (size_t i = 0; i < sz; i += chacha::blocksize) { - chacha::block(state, chacha::rounds); - state.data[12]++; - for (size_t j = i; j < i + chacha::blocksize; j++) - { - if (j >= sz) + chacha::block(state, chacha::rounds); + state.data[12]++; + for (size_t j = i; j < i + chacha::blocksize; j++) + { + if (j >= sz) { state.offset = j & 0x3F; // % 64 break; } - buf[j] ^= state.block.data[j - i]; - } + buf[j] ^= state.block.data[j - i]; + } } } + } // namespace chacha +} // namespace crypto +} // namespace i2p -} -} #endif - diff --git a/libi2pd/ChaCha20.h b/libi2pd/ChaCha20.h index b2eec320..a8bb1d56 100644 --- a/libi2pd/ChaCha20.h +++ b/libi2pd/ChaCha20.h @@ -21,23 +21,23 @@ namespace i2p { namespace crypto { - const std::size_t CHACHA20_KEY_BYTES = 32; - const std::size_t CHACHA20_NOUNCE_BYTES = 12; - + const std::size_t CHACHA20_KEY_BYTES = 32; + const std::size_t CHACHA20_NOUNCE_BYTES = 12; + namespace chacha { - constexpr std::size_t blocksize = 64; + constexpr std::size_t blocksize = 64; constexpr int rounds = 20; struct Chacha20State; struct Chacha20Block { - Chacha20Block () {}; - Chacha20Block (Chacha20Block &&) = delete; + Chacha20Block () {}; + Chacha20Block (Chacha20Block &&) = delete; - uint8_t data[blocksize]; + uint8_t data[blocksize]; - void operator << (const Chacha20State & st); + void operator << (const Chacha20State & st); }; struct Chacha20State @@ -54,19 +54,19 @@ namespace chacha void Copy(const Chacha20State & other) { - memcpy(data, other.data, sizeof(uint32_t) * 16); + memcpy(data, other.data, sizeof(uint32_t) * 16); } uint32_t data[16]; Chacha20Block block; - size_t offset; + size_t offset; }; void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter); void Chacha20SetCounter (Chacha20State& state, uint32_t counter); - void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place -} -} -} -#endif + void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place +} // namespace chacha +} // namespace crypto +} // namespace i2p #endif +#endif diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index b741b118..59b51c00 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -242,7 +242,7 @@ namespace config { "1.pool.ntp.org," "2.pool.ntp.org," "3.pool.ntp.org" - ), "Comma separated list of NTCP servers") + ), "Comma separated list of NTCP servers") ("nettime.ntpsyncinterval", value()->default_value(72), "NTP sync interval in hours (default: 72)") ; diff --git a/libi2pd/Config.h b/libi2pd/Config.h index 679ae3bb..679795b1 100644 --- a/libi2pd/Config.h +++ b/libi2pd/Config.h @@ -18,98 +18,101 @@ namespace i2p { namespace config { - extern boost::program_options::variables_map m_Options; + extern boost::program_options::variables_map m_Options; - /** - * @brief Initialize list of acceptable parameters - * - * Should be called before any Parse* functions. - */ - void Init(); + /** + * @brief Initialize list of acceptable parameters + * + * Should be called before any Parse* functions. + */ + void Init(); - /** - * @brief Parse cmdline parameters, and show help if requested - * @param argc Cmdline arguments count, should be passed from main(). - * @param argv Cmdline parameters array, should be passed from main() - * - * If --help is given in parameters, shows its list with description - * and terminates the program with exitcode 0. - * - * In case of parameter misuse boost throws an exception. - * We internally handle type boost::program_options::unknown_option, - * and then terminate the program with exitcode 1. - * - * Other exceptions will be passed to higher level. - */ - void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false); + /** + * @brief Parse cmdline parameters, and show help if requested + * @param argc Cmdline arguments count, should be passed from main(). + * @param argv Cmdline parameters array, should be passed from main() + * + * If --help is given in parameters, shows its list with description + * and terminates the program with exitcode 0. + * + * In case of parameter misuse boost throws an exception. + * We internally handle type boost::program_options::unknown_option, + * and then terminate the program with exitcode 1. + * + * Other exceptions will be passed to higher level. + */ + void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false); - /** - * @brief Load and parse given config file - * @param path Path to config file - * - * If error occurred when opening file path is points to, - * we show the error message and terminate program. - * - * In case of parameter misuse boost throws an exception. - * We internally handle type boost::program_options::unknown_option, - * and then terminate program with exitcode 1. - * - * Other exceptions will be passed to higher level. - */ - void ParseConfig(const std::string& path); + /** + * @brief Load and parse given config file + * @param path Path to config file + * + * If error occurred when opening file path is points to, + * we show the error message and terminate program. + * + * In case of parameter misuse boost throws an exception. + * We internally handle type boost::program_options::unknown_option, + * and then terminate program with exitcode 1. + * + * Other exceptions will be passed to higher level. + */ + void ParseConfig(const std::string& path); - /** - * @brief Used to combine options from cmdline, config and default values - */ - void Finalize(); + /** + * @brief Used to combine options from cmdline, config and default values + */ + void Finalize(); - /* @brief Accessor to parameters by name - * @param name Name of the requested parameter - * @param value Variable where to store option - * @return this function returns false if parameter not found - * - * Example: uint16_t port; GetOption("sam.port", port); - */ - template - bool GetOption(const char *name, T& value) { - if (!m_Options.count(name)) - return false; - value = m_Options[name].as(); - return true; - } + /** + * @brief Accessor to parameters by name + * @param name Name of the requested parameter + * @param value Variable where to store option + * @return this function returns false if parameter not found + * + * Example: uint16_t port; GetOption("sam.port", port); + */ + template + bool GetOption(const char *name, T& value) + { + if (!m_Options.count(name)) + return false; + value = m_Options[name].as(); + return true; + } - template - bool GetOption(const std::string& name, T& value) - { - return GetOption (name.c_str (), value); - } + template + bool GetOption(const std::string& name, T& value) + { + return GetOption (name.c_str (), value); + } - bool GetOptionAsAny(const char *name, boost::any& value); - bool GetOptionAsAny(const std::string& name, boost::any& value); + bool GetOptionAsAny(const char *name, boost::any& value); + bool GetOptionAsAny(const std::string& name, boost::any& value); - /** - * @brief Set value of given parameter - * @param name Name of settable parameter - * @param value New parameter value - * @return true if value set up successful, false otherwise - * - * Example: uint16_t port = 2827; SetOption("bob.port", port); - */ - template - bool SetOption(const char *name, const T& value) { - if (!m_Options.count(name)) - return false; - m_Options.at(name).value() = value; - notify(m_Options); - return true; - } + /** + * @brief Set value of given parameter + * @param name Name of settable parameter + * @param value New parameter value + * @return true if value set up successful, false otherwise + * + * Example: uint16_t port = 2827; SetOption("bob.port", port); + */ + template + bool SetOption(const char *name, const T& value) + { + if (!m_Options.count(name)) + return false; + m_Options.at(name).value() = value; + notify(m_Options); + return true; + } - /** - * @brief Check is value explicitly given or default - * @param name Name of checked parameter - * @return true if value set to default, false otherwise - */ - bool IsDefault(const char *name); + /** + * @brief Check is value explicitly given or default + * @param name Name of checked parameter + * @return true if value set to default, false otherwise + */ + bool IsDefault(const char *name); } } diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 567ae574..d4d3519e 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -286,14 +286,14 @@ namespace crypto #if OPENSSL_X25519 m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL); m_Pkey = nullptr; -#else +#else m_Ctx = BN_CTX_new (); -#endif - } +#endif + } X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub) { -#if OPENSSL_X25519 +#if OPENSSL_X25519 m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32); m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); if (pub) @@ -302,33 +302,33 @@ namespace crypto { size_t len = 32; EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len); - } + } #else - m_Ctx = BN_CTX_new (); + m_Ctx = BN_CTX_new (); memcpy (m_PrivateKey, priv, 32); if (pub) memcpy (m_PublicKey, pub, 32); else GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx); -#endif - } - +#endif + } + X25519Keys::~X25519Keys () { #if OPENSSL_X25519 EVP_PKEY_CTX_free (m_Ctx); - if (m_Pkey) EVP_PKEY_free (m_Pkey); -#else + if (m_Pkey) EVP_PKEY_free (m_Pkey); +#else BN_CTX_free (m_Ctx); -#endif - } +#endif + } void X25519Keys::GenerateKeys () { #if OPENSSL_X25519 if (m_Pkey) - { - EVP_PKEY_free (m_Pkey); + { + EVP_PKEY_free (m_Pkey); m_Pkey = nullptr; } EVP_PKEY_keygen_init (m_Ctx); @@ -337,26 +337,26 @@ namespace crypto m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx? size_t len = 32; EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len); -#else +#else RAND_bytes (m_PrivateKey, 32); GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx); -#endif - } +#endif + } void X25519Keys::Agree (const uint8_t * pub, uint8_t * shared) { -#if OPENSSL_X25519 +#if OPENSSL_X25519 EVP_PKEY_derive_init (m_Ctx); auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32); EVP_PKEY_derive_set_peer (m_Ctx, pkey); size_t len = 32; EVP_PKEY_derive (m_Ctx, shared, &len); EVP_PKEY_free (pkey); -#else +#else GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx); -#endif - } - +#endif + } + void X25519Keys::GetPrivateKey (uint8_t * priv) const { #if OPENSSL_X25519 @@ -369,14 +369,14 @@ namespace crypto void X25519Keys::SetPrivateKey (const uint8_t * priv) { -#if OPENSSL_X25519 - if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx); +#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 +#endif } // ElGamal @@ -681,12 +681,12 @@ namespace crypto // AES #ifdef __AES__ - #ifdef ARM64AES - void init_aesenc(void){ + #ifdef ARM64AES + void init_aesenc(void){ // TODO: Implementation - } + } - #endif + #endif #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ @@ -884,7 +884,6 @@ namespace crypto } } - void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { #ifdef __AES__ @@ -1139,10 +1138,10 @@ namespace crypto } EVP_CIPHER_CTX_free (ctx); -#else +#else chacha::Chacha20State state; // generate one time poly key - chacha::Chacha20Init (state, nonce, key, 0); + chacha::Chacha20Init (state, nonce, key, 0); uint64_t polyKey[8]; memset(polyKey, 0, sizeof(polyKey)); chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64); @@ -1158,7 +1157,7 @@ namespace crypto { // padding1 rem = 16 - rem; - polyHash.Update (padding, rem); + polyHash.Update (padding, rem); } } // encrypt/decrypt data and add to hash @@ -1174,20 +1173,20 @@ namespace crypto { polyHash.Update (buf, msgLen); // before decryption chacha::Chacha20Encrypt (state, buf, msgLen); // decrypt - } + } auto rem = msgLen & 0x0F; // %16 if (rem) { // padding2 rem = 16 - rem; - polyHash.Update (padding, rem); + polyHash.Update (padding, rem); } // adLen and msgLen htole64buf (padding, adLen); htole64buf (padding + 8, msgLen); - polyHash.Update (padding, 16); - + polyHash.Update (padding, 16); + if (encrypt) // calculate Poly1305 tag and write in after encrypted data polyHash.Finish ((uint64_t *)(buf + msgLen)); @@ -1195,7 +1194,7 @@ namespace crypto { uint64_t tag[4]; // calculate Poly1305 tag - polyHash.Finish (tag); + polyHash.Finish (tag); if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided } #endif @@ -1211,20 +1210,20 @@ namespace crypto EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0); EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); - for (const auto& it: bufs) + for (const auto& it: bufs) EVP_EncryptUpdate(ctx, it.first, &outlen, it.first, it.second); EVP_EncryptFinal_ex(ctx, NULL, &outlen); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac); EVP_CIPHER_CTX_free (ctx); -#else +#else chacha::Chacha20State state; // generate one time poly key - chacha::Chacha20Init (state, nonce, key, 0); + chacha::Chacha20Init (state, nonce, key, 0); uint64_t polyKey[8]; memset(polyKey, 0, sizeof(polyKey)); chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64); Poly1305 polyHash (polyKey); - // encrypt buffers + // encrypt buffers Chacha20SetCounter (state, 1); size_t size = 0; for (const auto& it: bufs) @@ -1234,22 +1233,22 @@ namespace crypto size += it.second; } // padding - uint8_t padding[16]; + uint8_t padding[16]; memset (padding, 0, 16); auto rem = size & 0x0F; // %16 if (rem) { // padding2 rem = 16 - rem; - polyHash.Update (padding, rem); + polyHash.Update (padding, rem); } // adLen and msgLen // adLen is always zero htole64buf (padding + 8, size); - polyHash.Update (padding, 16); + polyHash.Update (padding, 16); // MAC - polyHash.Finish ((uint64_t *)mac); -#endif + polyHash.Finish ((uint64_t *)mac); +#endif } void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out) @@ -1265,13 +1264,13 @@ namespace crypto EVP_CIPHER_CTX_free (ctx); #else chacha::Chacha20State state; - chacha::Chacha20Init (state, nonce, key, 1); + chacha::Chacha20Init (state, nonce, key, 1); if (out != msg) memcpy (out, msg, msgLen); chacha::Chacha20Encrypt (state, out, msgLen); #endif } - void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, + 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 @@ -1279,10 +1278,10 @@ namespace crypto EVP_PKEY_derive_init (pctx); EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256()); if (key && keyLen) - { + { EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32); EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen); - } + } else { // zerolen @@ -1290,22 +1289,22 @@ namespace crypto 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 ()); EVP_PKEY_derive (pctx, out, &outLen); EVP_PKEY_CTX_free (pctx); #else uint8_t prk[32]; unsigned int len; - HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len); + HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len); auto l = info.length (); memcpy (out, info.c_str (), l); out[l] = 0x01; HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &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); - } + HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len); + } #endif } @@ -1323,10 +1322,10 @@ namespace crypto } }*/ - + void InitCrypto (bool precomputation) { - i2p::cpu::Detect (); + i2p::cpu::Detect (); #if LEGACY_OPENSSL SSL_library_init (); #endif @@ -1364,4 +1363,3 @@ namespace crypto } } } - diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 32410daf..2dfd6d0e 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -28,13 +28,13 @@ #else # define LEGACY_OPENSSL 0 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 -# define OPENSSL_HKDF 1 -# define OPENSSL_EDDSA 1 -# define OPENSSL_X25519 1 -# define OPENSSL_SIPHASH 1 +# define OPENSSL_HKDF 1 +# define OPENSSL_EDDSA 1 +# define OPENSSL_X25519 1 +# define OPENSSL_SIPHASH 1 # endif # if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them -# define OPENSSL_AEAD_CHACHA20_POLY1305 1 +# define OPENSSL_AEAD_CHACHA20_POLY1305 1 # endif #endif @@ -81,20 +81,20 @@ namespace crypto 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); + void Agree (const uint8_t * pub, uint8_t * shared); private: - uint8_t m_PublicKey[32]; + uint8_t m_PublicKey[32]; #if OPENSSL_X25519 EVP_PKEY_CTX * m_Ctx; EVP_PKEY * m_Pkey; -#else +#else BN_CTX * m_Ctx; uint8_t m_PrivateKey[32]; -#endif +#endif }; - + // ElGamal void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false); bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false); @@ -117,15 +117,15 @@ namespace crypto void operator^=(const ChipherBlock& other) // XOR { if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ? - { + { for (int i = 0; i < 4; i++) reinterpret_cast(buf)[i] ^= reinterpret_cast(other.buf)[i]; - } + } else - { + { for (int i = 0; i < 16; i++) buf[i] ^= other.buf[i]; - } + } } }; @@ -297,7 +297,7 @@ namespace crypto // HKDF - 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 + 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/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index 878e984a..2abcb111 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -151,7 +151,7 @@ namespace crypto ECIESX25519AEADRatchetEncryptor::ECIESX25519AEADRatchetEncryptor (const uint8_t * pub) { memcpy (m_PublicKey, pub, 32); - } + } void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool) { @@ -166,16 +166,15 @@ namespace crypto bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding) { m_StaticKeys.Agree (epub, sharedSecret); - return true; + return true; } void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub) { X25519Keys k; - k.GenerateKeys (); + k.GenerateKeys (); k.GetPrivateKey (priv); memcpy (pub, k.GetPublicKey (), 32); } } } - diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 701e9482..43bd3aaa 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -45,7 +45,7 @@ namespace crypto ElGamalDecryptor (const uint8_t * priv); bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding); size_t GetPublicKeyLen () const { return 256; }; - + private: uint8_t m_PrivateKey[256]; @@ -76,7 +76,7 @@ namespace crypto ~ECIESP256Decryptor (); bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding); size_t GetPublicKeyLen () const { return 64; }; - + private: EC_GROUP * m_Curve; @@ -109,7 +109,7 @@ namespace crypto ~ECIESGOSTR3410Decryptor (); bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding); size_t GetPublicKeyLen () const { return 64; }; - + private: BIGNUM * m_PrivateKey; @@ -119,14 +119,14 @@ namespace crypto // ECIES-X25519-AEAD-Ratchet - class ECIESX25519AEADRatchetEncryptor: public CryptoKeyEncryptor + class ECIESX25519AEADRatchetEncryptor: public CryptoKeyEncryptor { public: ECIESX25519AEADRatchetEncryptor (const uint8_t * pub); ~ECIESX25519AEADRatchetEncryptor () {}; void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool); - // copies m_PublicKey to pub + // copies m_PublicKey to pub private: @@ -139,7 +139,7 @@ namespace crypto ECIESX25519AEADRatchetDecryptor (const uint8_t * priv); ~ECIESX25519AEADRatchetDecryptor () {}; - bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding); + 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; }; @@ -153,4 +153,3 @@ namespace crypto } #endif - diff --git a/libi2pd/CryptoWorker.h b/libi2pd/CryptoWorker.h index d43e356c..baeb7f14 100644 --- a/libi2pd/CryptoWorker.h +++ b/libi2pd/CryptoWorker.h @@ -77,5 +77,4 @@ namespace worker } } - #endif diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 6441b5e2..2da73649 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -13,10 +13,10 @@ namespace datagram DatagramDestination::DatagramDestination (std::shared_ptr owner, bool gzip): m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip) { - auto identityLen = m_Owner->GetIdentity ()->GetFullLen (); - m_From.resize (identityLen); - m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen); - m_Signature.resize (m_Owner->GetIdentity ()->GetSignatureLen ()); + auto identityLen = m_Owner->GetIdentity ()->GetFullLen (); + m_From.resize (identityLen); + m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen); + m_Signature.resize (m_Owner->GetIdentity ()->GetSignatureLen ()); } DatagramDestination::~DatagramDestination () @@ -36,7 +36,7 @@ namespace datagram m_Owner->Sign (payload, len, m_Signature.data ()); auto session = ObtainSession(identity); - auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, + auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, fromPort, toPort, false, !session->IsRatchets ()); // datagram session->SendMsg(msg); } @@ -46,8 +46,8 @@ namespace datagram auto session = ObtainSession(identity); auto msg = CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ()); // raw session->SendMsg(msg); - } - + } + void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len) { i2p::data::IdentityEx identity; @@ -86,8 +86,8 @@ namespace datagram m_RawReceiver (fromPort, toPort, buf, len); else LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram"); - } - + } + DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port) { std::lock_guard lock(m_ReceiversMutex); @@ -107,23 +107,22 @@ namespace datagram { if (isRaw) HandleRawDatagram (fromPort, toPort, uncompressed, uncompressedLen); - else + else HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen); - } + } else LogPrint (eLogWarning, "Datagram: decompression failed"); } - std::shared_ptr DatagramDestination::CreateDataMessage ( - const std::vector >& payloads, - uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum) + const std::vector >& payloads, + uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum) { auto msg = NewI2NPMessage (); uint8_t * buf = msg->GetPayload (); buf += 4; // reserve for length size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) : - i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len); + i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len); if (size) { htobe32buf (msg->GetPayload (), size); // length @@ -186,7 +185,7 @@ namespace datagram } DatagramSession::DatagramSession(std::shared_ptr localDestination, - const i2p::data::IdentHash & remoteIdent) : + const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), m_RemoteIdent(remoteIdent), m_SendQueueTimer(localDestination->GetService()), @@ -384,4 +383,3 @@ namespace datagram } } } - diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index ea2a4e13..72e7340c 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -32,68 +32,71 @@ namespace datagram const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; // milliseconds minimum time between path switches const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000; - // max 64 messages buffered in send queue for each datagram session - const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64; + // max 64 messages buffered in send queue for each datagram session + const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64; class DatagramSession : public std::enable_shared_from_this { - public: - DatagramSession(std::shared_ptr localDestination, const i2p::data::IdentHash & remoteIdent); - void Start (); - void Stop (); + public: + + DatagramSession(std::shared_ptr localDestination, const i2p::data::IdentHash & remoteIdent); + + void Start (); + void Stop (); - /** @brief ack the garlic routing path */ - void Ack(); + /** @brief ack the garlic routing path */ + void Ack(); - /** send an i2np message to remote endpoint for this session */ - void SendMsg(std::shared_ptr msg); - /** get the last time in milliseconds for when we used this datagram session */ - uint64_t LastActivity() const { return m_LastUse; } + /** send an i2np message to remote endpoint for this session */ + void SendMsg(std::shared_ptr msg); + /** get the last time in milliseconds for when we used this datagram session */ + uint64_t LastActivity() const { return m_LastUse; } bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); } - + struct Info { std::shared_ptr IBGW; std::shared_ptr OBEP; const uint64_t activity; - Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {} - Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) : - activity(a) { - if(ibgw) IBGW = std::make_shared(ibgw); - else IBGW = nullptr; - if(obep) OBEP = std::make_shared(obep); - else OBEP = nullptr; - } - }; + Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {} + Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) : + activity(a) { + if(ibgw) IBGW = std::make_shared(ibgw); + else IBGW = nullptr; + if(obep) OBEP = std::make_shared(obep); + else OBEP = nullptr; + } + }; - Info GetSessionInfo() const; + Info GetSessionInfo() const; - private: + private: - void FlushSendQueue(); - void ScheduleFlushSendQueue(); + void FlushSendQueue(); + void ScheduleFlushSendQueue(); - void HandleSend(std::shared_ptr msg); + void HandleSend(std::shared_ptr msg); - std::shared_ptr GetSharedRoutingPath(); + std::shared_ptr GetSharedRoutingPath(); - void HandleLeaseSetUpdated(std::shared_ptr ls); + void HandleLeaseSetUpdated(std::shared_ptr ls); - private: - std::shared_ptr m_LocalDestination; - i2p::data::IdentHash m_RemoteIdent; - std::shared_ptr m_RemoteLeaseSet; - std::shared_ptr m_RoutingSession; - std::shared_ptr m_CurrentRemoteLease; - std::shared_ptr m_CurrentOutboundTunnel; - boost::asio::deadline_timer m_SendQueueTimer; - std::vector > m_SendQueue; - uint64_t m_LastUse; - bool m_RequestingLS; + private: + + std::shared_ptr m_LocalDestination; + i2p::data::IdentHash m_RemoteIdent; + std::shared_ptr m_RemoteLeaseSet; + std::shared_ptr m_RoutingSession; + std::shared_ptr m_CurrentRemoteLease; + std::shared_ptr m_CurrentOutboundTunnel; + boost::asio::deadline_timer m_SendQueueTimer; + std::vector > m_SendQueue; + uint64_t m_LastUse; + bool m_RequestingLS; }; typedef std::shared_ptr DatagramSession_ptr; @@ -104,17 +107,15 @@ namespace datagram typedef std::function Receiver; typedef std::function RawReceiver; - public: - - DatagramDestination (std::shared_ptr owner, bool gzip); + DatagramDestination (std::shared_ptr owner, bool gzip); ~DatagramDestination (); void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false); - + void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; void ResetReceiver () { m_Receiver = nullptr; }; @@ -123,7 +124,7 @@ namespace datagram void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; }; void ResetRawReceiver () { m_RawReceiver = nullptr; }; - + std::shared_ptr GetInfoForRemote(const i2p::data::IdentHash & remote); // clean up stale sessions @@ -131,14 +132,14 @@ namespace datagram private: - std::shared_ptr ObtainSession(const i2p::data::IdentHash & ident); + std::shared_ptr ObtainSession(const i2p::data::IdentHash & ident); - std::shared_ptr CreateDataMessage (const std::vector >& payloads, + std::shared_ptr CreateDataMessage (const std::vector >& payloads, uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true); void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - + /** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */ Receiver FindReceiver(uint16_t port); diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 782e2841..921e55f0 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -16,8 +16,8 @@ namespace i2p namespace client { LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service, - bool isPublic, const std::map * params): - m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0), + bool isPublic, const std::map * params): + m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service), m_LeaseSetType (DEFAULT_LEASESET_TYPE), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE) @@ -160,13 +160,12 @@ namespace client bool LeaseSetDestination::Reconfigure(std::map params) { - auto itr = params.find("i2cp.dontPublishLeaseSet"); if (itr != params.end()) { m_IsPublic = itr->second != "true"; } - + int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency; std::map intOpts = { {I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen}, @@ -185,7 +184,7 @@ namespace client outQuant = pool->GetNumOutboundTunnels(); minLatency = 0; maxLatency = 0; - + for (auto & opt : intOpts) { itr = params.find(opt.first); @@ -197,7 +196,7 @@ namespace client pool->RequireLatency(minLatency, maxLatency); return pool->Reconfigure(inLen, outLen, inQuant, outQuant); } - + std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { std::shared_ptr remoteLS; @@ -266,7 +265,7 @@ namespace client std::lock_guard l(m_LeaseSetMutex); return m_LeaseSet; } - + void LeaseSetDestination::SetLeaseSet (std::shared_ptr newLeaseSet) { { @@ -281,7 +280,7 @@ namespace client { s->m_PublishVerificationTimer.cancel (); s->Publish (); - }); + }); } } @@ -565,12 +564,12 @@ namespace client m_PublishReplyToken = 0; if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); Publish (); } else { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ()); + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ()); // Java floodfill never sends confirmation back for unknown crypto type // assume it successive and try to verify m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); @@ -591,7 +590,7 @@ namespace client { LogPrint (eLogWarning, "Destination: couldn't verify LeaseSet for ", GetIdentHash().ToBase32()); return; - } + } auto s = shared_from_this (); // we must capture this for gcc 4.7 due the bug RequestLeaseSet (ls->GetStoreHash (), @@ -643,9 +642,9 @@ namespace client if (requestComplete) m_Service.post ([requestComplete](void){requestComplete (nullptr);}); return false; - } + } auto storeHash = dest->GetStoreHash (); - auto leaseSet = FindLeaseSet (storeHash); + auto leaseSet = FindLeaseSet (storeHash); if (leaseSet) { if (requestComplete) @@ -720,7 +719,7 @@ namespace client } bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, - std::shared_ptr nextFloodfill, std::shared_ptr request) + std::shared_ptr nextFloodfill, std::shared_ptr request) { if (!request->replyTunnel || !request->replyTunnel->IsEstablished ()) request->replyTunnel = m_Pool->GetNextInboundTunnel (); @@ -783,7 +782,7 @@ namespace client } else { - LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds"); + LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds"); done = true; } @@ -829,13 +828,13 @@ namespace client i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const { if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)) - return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET; - return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; - } - - ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, + return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET; + return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; + } + + ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): - LeaseSetDestination (service, isPublic, params), + LeaseSetDestination (service, isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(service) @@ -846,7 +845,7 @@ namespace client // extract encryption type params for LS2 std::set encryptionKeyTypes; if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 || - GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params) + GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params) { auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE); if (it != params->end ()) @@ -864,37 +863,37 @@ namespace client { LogPrint (eLogInfo, "Destination: Unexpected crypto type ", it1, ". ", ex.what ()); continue; - } - } - } - } - // if no param or valid crypto type use from identity - bool isSingleKey = false; - if (encryptionKeyTypes.empty ()) + } + } + } + } + // if no param or valid crypto type use from identity + bool isSingleKey = false; + if (encryptionKeyTypes.empty ()) { isSingleKey = true; encryptionKeyTypes.insert (GetIdentity ()->GetCryptoKeyType ()); - } + } for (auto& it: encryptionKeyTypes) - { + { auto encryptionKey = new EncryptionKey (it); - if (isPublic) + if (isPublic) PersistTemporaryKeys (encryptionKey, isSingleKey); else encryptionKey->GenerateKeys (); - encryptionKey->CreateDecryptor (); + encryptionKey->CreateDecryptor (); if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) m_ECIESx25519EncryptionKey.reset (encryptionKey); else - m_StandardEncryptionKey.reset (encryptionKey); - } - + m_StandardEncryptionKey.reset (encryptionKey); + } + if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); try - { + { if (params) { // extract streaming params @@ -910,9 +909,9 @@ namespace client { m_AuthKeys = std::make_shared >(); if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH) - ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params); + ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params); else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) - ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params); + ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params); else LogPrint (eLogError, "Destination: Unexpected auth type ", authType); if (m_AuthKeys->size ()) @@ -920,7 +919,7 @@ namespace client else { LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType); - m_AuthKeys = nullptr; + m_AuthKeys = nullptr; } } } @@ -1002,7 +1001,7 @@ namespace client m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length, true); else LogPrint (eLogError, "Destination: Missing raw datagram destination"); - break; + break; default: LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]); } @@ -1105,7 +1104,7 @@ namespace client return dest; } - i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip) + i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip) { if (m_DatagramDestination == nullptr) m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip); @@ -1130,7 +1129,7 @@ namespace client { if (!keys) return; std::string ident = GetIdentHash().ToBase32(); - std::string path = i2p::fs::DataDirPath("destinations", + std::string path = i2p::fs::DataDirPath("destinations", isSingleKey ? (ident + ".dat") : (ident + "." + std::to_string (keys->keyType) + ".dat")); std::ifstream f(path, std::ifstream::binary); @@ -1142,12 +1141,12 @@ namespace client LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p"); memset (keys->priv, 0, 256); - memset (keys->pub, 0, 256); + memset (keys->pub, 0, 256); keys->GenerateKeys (); // TODO:: persist crypto key type std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); if (f1) { - f1.write ((char *)keys->pub, 256); + f1.write ((char *)keys->pub, 256); f1.write ((char *)keys->priv, 256); return; } @@ -1160,11 +1159,11 @@ namespace client if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) { if (m_StandardEncryptionKey) - { + { leaseSet = std::make_shared (GetIdentity (), m_StandardEncryptionKey->pub, tunnels); // sign - Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); - } + Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); + } else LogPrint (eLogError, "Destinations: Wrong encryption key type for LeaseSet type 1"); } @@ -1175,9 +1174,9 @@ namespace client if (m_ECIESx25519EncryptionKey) keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, 32, m_ECIESx25519EncryptionKey->pub} ); if (m_StandardEncryptionKey) - keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} ); + keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} ); - bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; + bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; auto ls2 = std::make_shared (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, m_Keys, keySections, tunnels, IsPublic (), isPublishedEncrypted); if (isPublishedEncrypted) // encrypt if type 5 @@ -1204,18 +1203,18 @@ namespace client return false; } - bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const - { + bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const + { return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ? (bool)m_ECIESx25519EncryptionKey : (bool)m_StandardEncryptionKey; } - const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const - { + const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const + { if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub : nullptr; return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub : nullptr; } - + void ClientDestination::ReadAuthKey (const std::string& group, const std::map * params) { for (auto it: *params) @@ -1229,7 +1228,7 @@ namespace client m_AuthKeys->push_back (pubKey); else LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1)); - } + } } } @@ -1241,10 +1240,10 @@ namespace client if (it.second->DeleteStream (recvStreamID)) return true; return false; - } - + } + RunnableClientDestination::RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): - RunnableService ("Destination"), + RunnableService ("Destination"), ClientDestination (GetIOService (), keys, isPublic, params) { } @@ -1253,7 +1252,7 @@ namespace client { if (IsRunning ()) Stop (); - } + } void RunnableClientDestination::Start () { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 04cf05f4..dbdc3704 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -52,13 +52,13 @@ namespace client const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname"; const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname"; const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType"; - const int DEFAULT_LEASESET_TYPE = 1; + const int DEFAULT_LEASESET_TYPE = 1; const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType"; const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64 const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType"; const char I2CP_PARAM_LEASESET_CLIENT_DH[] = "i2cp.leaseSetClient.dh"; // group of i2cp.leaseSetClient.dh.nnn const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn - + // latency const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min"; const int DEFAULT_MIN_TUNNEL_LATENCY = 0; @@ -94,7 +94,6 @@ namespace client } }; - public: LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map * params = nullptr); @@ -107,12 +106,12 @@ namespace client /** i2cp reconfigure */ virtual bool Reconfigure(std::map i2cpOpts); - + std::shared_ptr GetTunnelPool () { return m_Pool; }; bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; std::shared_ptr FindLeaseSet (const i2p::data::IdentHash& ident); bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); - bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr dest, RequestComplete requestComplete = nullptr); + bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr dest, RequestComplete requestComplete = nullptr); void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true); void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr dest, bool notify = true); @@ -155,7 +154,7 @@ namespace client 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); + bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleCleanupTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); @@ -202,11 +201,11 @@ namespace client EncryptionKey (i2p::data::CryptoKeyType t):keyType(t) { memset (pub, 0, 256); memset (priv, 0, 256); }; void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv, pub); }; void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv); }; - }; - + }; + public: - ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, + ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params = nullptr); ~ClientDestination (); @@ -235,13 +234,13 @@ namespace client int GetStreamingAckDelay () const { return m_StreamingAckDelay; } // datagram - i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; - i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true); + i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; + i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true); // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const; std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; - bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; protected: @@ -259,8 +258,8 @@ namespace client void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey); void ReadAuthKey (const std::string& group, const std::map * params); - private: - + private: + i2p::data::PrivateKeys m_Keys; std::unique_ptr m_StandardEncryptionKey; std::unique_ptr m_ECIESx25519EncryptionKey; @@ -273,7 +272,7 @@ namespace client boost::asio::deadline_timer m_ReadyChecker; - std::shared_ptr > m_AuthKeys; // we don't need them for I2CP + std::shared_ptr > m_AuthKeys; // we don't need them for I2CP public: @@ -287,7 +286,7 @@ namespace client public: RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params = nullptr); - ~RunnableClientDestination (); + ~RunnableClientDestination (); void Start (); void Stop (); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 7b386d92..f3b1a685 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -15,54 +15,54 @@ namespace i2p namespace garlic { - void RatchetTagSet::DHInitialize (const uint8_t * rootKey, const uint8_t * k) - { - // DH_INITIALIZE(rootKey, k) - uint8_t keydata[64]; - i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64) - memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31] - i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf); - // [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64) + void RatchetTagSet::DHInitialize (const uint8_t * rootKey, const uint8_t * k) + { + // DH_INITIALIZE(rootKey, k) + uint8_t keydata[64]; + i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64) + memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31] + i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf); + // [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64) memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32); m_NextSymmKeyIndex = 0; - } + } - void RatchetTagSet::NextSessionTagRatchet () - { - i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64) - memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32); + void RatchetTagSet::NextSessionTagRatchet () + { + i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64) + memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32); m_NextIndex = 0; - } + } - uint64_t RatchetTagSet::GetNextSessionTag () - { - i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64) - m_NextIndex++; - if (m_NextIndex >= 65535) + uint64_t RatchetTagSet::GetNextSessionTag () + { + i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64) + m_NextIndex++; + if (m_NextIndex >= 65535) { LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty"); return 0; - } - return m_KeyData.GetTag (); - } + } + return m_KeyData.GetTag (); + } void RatchetTagSet::GetSymmKey (int index, uint8_t * key) { if (index >= m_NextSymmKeyIndex) - { + { auto num = index + 1 - m_NextSymmKeyIndex; if (!m_NextSymmKeyIndex) { i2p::crypto::HKDF (m_SymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK); // keydata_0 = HKDF(symmKey_ck, SYMMKEY_CONSTANT, "SymmetricRatchet", 64) m_NextSymmKeyIndex = 1; num--; - } + } for (int i = 0; i < num; i++) - { + { i2p::crypto::HKDF (m_CurrentSymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK); if (i < num - 1) m_ItermediateSymmKeys.emplace (m_NextSymmKeyIndex + i, m_CurrentSymmKeyCK + 32); - } + } m_NextSymmKeyIndex += num; memcpy (key, m_CurrentSymmKeyCK + 32, 32); } @@ -70,30 +70,30 @@ namespace garlic { auto it = m_ItermediateSymmKeys.find (index); if (it != m_ItermediateSymmKeys.end ()) - { + { memcpy (key, it->second, 32); m_ItermediateSymmKeys.erase (it); - } + } else LogPrint (eLogError, "Garlic: Missing symmetric key for index ", index); - } - } + } + } void RatchetTagSet::Expire () { if (!m_ExpirationTimestamp) m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT; - } - - ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet): - GarlicRoutingSession (owner, attachLeaseSet) - { - ResetKeys (); - } - - ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession () - { - } + } + + ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet): + GarlicRoutingSession (owner, attachLeaseSet) + { + ResetKeys (); + } + + ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession () + { + } void ECIESX25519AEADRatchetSession::ResetKeys () { @@ -109,65 +109,65 @@ namespace garlic }; // SHA256 (protocolNameHash) memcpy (m_CK, protocolNameHash, 32); memcpy (m_H, hh, 32); - } - - void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len) - { - SHA256_CTX ctx; + } + + 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); - } - + } + void ECIESX25519AEADRatchetSession::CreateNonce (uint64_t seqn, uint8_t * nonce) { - memset (nonce, 0, 4); - htole64buf (nonce + 4, seqn); + memset (nonce, 0, 4); + htole64buf (nonce + 4, seqn); + } + + bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf) + { + for (int i = 0; i < 10; i++) + { + m_EphemeralKeys.GenerateKeys (); + if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf)) + return true; // success + } + return false; } - bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf) - { - for (int i = 0; i < 10; i++) - { - m_EphemeralKeys.GenerateKeys (); - if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf)) - return true; // success - } - return false; - } - - std::shared_ptr ECIESX25519AEADRatchetSession::CreateNewSessionTagset () - { - uint8_t tagsetKey[32]; - i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32) - // Session Tag Ratchet - auto tagsetNsr = std::make_shared(shared_from_this ()); - tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) - tagsetNsr->NextSessionTagRatchet (); - return tagsetNsr; - } - - bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len) - { - if (!GetOwner ()) return false; - // we are Bob - // KDF1 - MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk) - + std::shared_ptr ECIESX25519AEADRatchetSession::CreateNewSessionTagset () + { + uint8_t tagsetKey[32]; + i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32) + // Session Tag Ratchet + auto tagsetNsr = std::make_shared(shared_from_this ()); + tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) + tagsetNsr->NextSessionTagRatchet (); + return tagsetNsr; + } + + bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len) + { + if (!GetOwner ()) return false; + // we are Bob + // KDF1 + MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk) + if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) - { + { LogPrint (eLogError, "Garlic: Can't decode elligator"); - return false; + return false; } - buf += 32; len -= 32; - MixHash (m_Aepk, 32); // h = SHA256(h || aepk) - - uint8_t sharedSecret[32]; + buf += 32; len -= 32; + MixHash (m_Aepk, 32); // h = SHA256(h || aepk) + + uint8_t sharedSecret[32]; GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, aepk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) - - // decrypt flags/static + + // decrypt flags/static uint8_t nonce[12], fs[32]; CreateNonce (0, nonce); if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt @@ -179,17 +179,17 @@ namespace garlic buf += 48; len -= 48; // 32 data + 16 poly // KDF2 for payload - bool isStatic = !i2p::data::Tag<32> (fs).IsZero (); + bool isStatic = !i2p::data::Tag<32> (fs).IsZero (); if (isStatic) { // static key, fs is apk - memcpy (m_RemoteStaticKey, fs, 32); + memcpy (m_RemoteStaticKey, fs, 32); GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, apk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) } else // all zeros flags CreateNonce (1, nonce); - + // decrypt payload std::vector payload (len - 16); // we must save original ciphertext if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt @@ -198,17 +198,17 @@ namespace garlic return false; } if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext) - m_State = eSessionStateNewSessionReceived; + m_State = eSessionStateNewSessionReceived; GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); - HandlePayload (payload.data (), len - 16, nullptr, 0); + HandlePayload (payload.data (), len - 16, nullptr, 0); - return true; - } + return true; + } - void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index) - { - size_t offset = 0; + void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index) + { + size_t offset = 0; while (offset < len) { uint8_t blk = buf[offset]; @@ -228,48 +228,48 @@ namespace garlic GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size); break; case eECIESx25519BlkNextKey: - LogPrint (eLogDebug, "Garlic: next key"); + LogPrint (eLogDebug, "Garlic: next key"); HandleNextKey (buf + offset, size, receiveTagset); break; case eECIESx25519BlkAck: - { + { LogPrint (eLogDebug, "Garlic: ack"); int numAcks = size >> 2; // /4 - auto offset1 = offset; + auto offset1 = offset; for (auto i = 0; i < numAcks; i++) - { + { offset1 += 2; // tagsetid MessageConfirmed (bufbe16toh (buf + offset1)); offset1 += 2; // N } break; - } + } case eECIESx25519BlkAckRequest: - { + { LogPrint (eLogDebug, "Garlic: ack request"); - m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index}); - break; - } + m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index}); + break; + } case eECIESx25519BlkTermination: LogPrint (eLogDebug, "Garlic: termination"); if (GetOwner ()) GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey); if (receiveTagset) receiveTagset->Expire (); - break; + break; case eECIESx25519BlkDateTime: LogPrint (eLogDebug, "Garlic: datetime"); - break; + break; case eECIESx25519BlkOptions: LogPrint (eLogDebug, "Garlic: options"); break; case eECIESx25519BlkPadding: LogPrint (eLogDebug, "Garlic: padding"); - break; + break; default: LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk); } offset += size; } - } + } void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset) { @@ -279,7 +279,7 @@ namespace garlic if (!m_SendForwardKey || !m_NextSendRatchet) return; uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID if (((!m_NextSendRatchet->newKey || !m_NextSendRatchet->keyID) && keyID == m_NextSendRatchet->keyID) || - (m_NextSendRatchet->newKey && keyID == m_NextSendRatchet->keyID -1)) + (m_NextSendRatchet->newKey && keyID == m_NextSendRatchet->keyID -1)) { if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG) memcpy (m_NextSendRatchet->remote, buf, 32); @@ -288,15 +288,15 @@ namespace garlic i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32) auto newTagset = std::make_shared (shared_from_this ()); newTagset->SetTagSetID (1 + m_NextSendRatchet->keyID + keyID); - newTagset->DHInitialize (m_SendTagset->GetNextRootKey (), tagsetKey); + newTagset->DHInitialize (m_SendTagset->GetNextRootKey (), tagsetKey); newTagset->NextSessionTagRatchet (); - m_SendTagset = newTagset; + m_SendTagset = newTagset; m_SendForwardKey = false; LogPrint (eLogDebug, "Garlic: next send tagset ", newTagset->GetTagSetID (), " created"); } else LogPrint (eLogDebug, "Garlic: Unexpected next key ", keyID); - } + } else { uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID @@ -305,38 +305,38 @@ namespace garlic if (!m_NextReceiveRatchet) m_NextReceiveRatchet.reset (new DHRatchet ()); else - { - if (keyID == m_NextReceiveRatchet->keyID && newKey == m_NextReceiveRatchet->newKey) + { + if (keyID == m_NextReceiveRatchet->keyID && newKey == m_NextReceiveRatchet->newKey) { LogPrint (eLogDebug, "Garlic: Duplicate ", newKey ? "new" : "old", " key ", keyID, " received"); return; - } + } m_NextReceiveRatchet->keyID = keyID; } int tagsetID = 2*keyID; if (newKey) - { + { m_NextReceiveRatchet->key.GenerateKeys (); m_NextReceiveRatchet->newKey = true; tagsetID++; - } + } else m_NextReceiveRatchet->newKey = false; if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG) memcpy (m_NextReceiveRatchet->remote, buf, 32); - + uint8_t sharedSecret[32], tagsetKey[32]; m_NextReceiveRatchet->key.Agree (m_NextReceiveRatchet->remote, sharedSecret); i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32) - auto newTagset = std::make_shared(shared_from_this ()); - newTagset->SetTagSetID (tagsetID); - newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey); + auto newTagset = std::make_shared(shared_from_this ()); + newTagset->SetTagSetID (tagsetID); + newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey); newTagset->NextSessionTagRatchet (); - GenerateMoreReceiveTags (newTagset, ECIESX25519_MAX_NUM_GENERATED_TAGS); + GenerateMoreReceiveTags (newTagset, ECIESX25519_MAX_NUM_GENERATED_TAGS); receiveTagset->Expire (); LogPrint (eLogDebug, "Garlic: next receive tagset ", tagsetID, " created"); - } - } + } + } void ECIESX25519AEADRatchetSession::NewNextSendRatchet () { @@ -346,49 +346,49 @@ namespace garlic { m_NextSendRatchet->keyID++; m_NextSendRatchet->newKey = true; - } + } else m_NextSendRatchet->newKey = false; - } + } else m_NextSendRatchet.reset (new DHRatchet ()); if (m_NextSendRatchet->newKey) m_NextSendRatchet->key.GenerateKeys (); - + m_SendForwardKey = true; LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created"); - } - - bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) - { + } + + bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) + { ResetKeys (); - // we are Alice, bpk is m_RemoteStaticKey - size_t offset = 0; - if (!GenerateEphemeralKeysAndEncode (out + offset)) - { + // we are Alice, bpk is m_RemoteStaticKey + size_t offset = 0; + if (!GenerateEphemeralKeysAndEncode (out + offset)) + { LogPrint (eLogError, "Garlic: Can't encode elligator"); - return false; - } - offset += 32; - - // KDF1 - MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk) - MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk) - uint8_t sharedSecret[32]; + return false; + } + offset += 32; + + // KDF1 + MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk) + MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk) + uint8_t sharedSecret[32]; m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk) - i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) - // encrypt static key section - uint8_t nonce[12]; + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) + // encrypt static key section + uint8_t nonce[12]; CreateNonce (0, nonce); if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed "); return false; } - MixHash (out + offset, 48); // h = SHA256(h || ciphertext) - offset += 48; - // KDF2 - GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk) + MixHash (out + offset, 48); // h = SHA256(h || ciphertext) + offset += 48; + // KDF2 + GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) // encrypt payload if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt @@ -399,169 +399,169 @@ namespace garlic MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext) m_State = eSessionStateNewSessionSent; - if (GetOwner ()) + if (GetOwner ()) GenerateMoreReceiveTags (CreateNewSessionTagset (), ECIESX25519_NSR_NUM_GENERATED_TAGS); - return true; - } + return true; + } - bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) - { - // we are Bob + bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) + { + // we are Bob m_NSRTagset = CreateNewSessionTagset (); - uint64_t tag = m_NSRTagset->GetNextSessionTag (); - - size_t offset = 0; - memcpy (out + offset, &tag, 8); - offset += 8; - if (!GenerateEphemeralKeysAndEncode (out + offset)) // bepk - { + uint64_t tag = m_NSRTagset->GetNextSessionTag (); + + size_t offset = 0; + memcpy (out + offset, &tag, 8); + offset += 8; + if (!GenerateEphemeralKeysAndEncode (out + offset)) // bepk + { LogPrint (eLogError, "Garlic: Can't encode elligator"); - return false; + return false; } memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR memcpy (m_NSRH, m_H, 32); - offset += 32; - // KDF for Reply Key Section - MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) - MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) - uint8_t sharedSecret[32]; - m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk) - i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) - m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk) - i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) + offset += 32; + // KDF for Reply Key Section + MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) + MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) + uint8_t sharedSecret[32]; + m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) + m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) uint8_t nonce[12]; CreateNonce (0, nonce); - // calulate hash for zero length + // calculate hash for zero length if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) { LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); return false; } - MixHash (out + offset, 16); // h = SHA256(h || ciphertext) - offset += 16; - // KDF for payload - uint8_t keydata[64]; - i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) + MixHash (out + offset, 16); // h = SHA256(h || ciphertext) + offset += 16; + // KDF for payload + uint8_t keydata[64]; + i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) // k_ab = keydata[0:31], k_ba = keydata[32:63] auto receiveTagset = std::make_shared(shared_from_this ()); - receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) + receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) receiveTagset->NextSessionTagRatchet (); m_SendTagset = std::make_shared(shared_from_this ()); - m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) - m_SendTagset->NextSessionTagRatchet (); + m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) + m_SendTagset->NextSessionTagRatchet (); GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS); - i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) - // encrypt payload - if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt + i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) + // encrypt payload + if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt { LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed"); return false; } m_State = eSessionStateNewSessionReplySent; - - return true; - } + + return true; + } bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) - { - // we are Bob and sent NSR already - uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag - memcpy (out, &tag, 8); + { + // we are Bob and sent NSR already + uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag + memcpy (out, &tag, 8); memcpy (out + 8, m_NSREncodedKey, 32); - // recalculte h with new tag + // recalculate h with new tag memcpy (m_H, m_NSRH, 32); MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) - MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) + MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) uint8_t nonce[12]; - CreateNonce (0, nonce); + CreateNonce (0, nonce); if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) { LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); return false; } - MixHash (out + 40, 16); // h = SHA256(h || ciphertext) + MixHash (out + 40, 16); // h = SHA256(h || ciphertext) // encrypt payload - if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt + if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed"); return false; } return true; - } - - bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len) - { + } + + bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len) + { // we are Alice LogPrint (eLogDebug, "Garlic: reply received"); const uint8_t * tag = buf; buf += 8; len -= 8; // tag - uint8_t bepk[32]; // Bob's ephemeral key + uint8_t bepk[32]; // Bob's ephemeral key if (!i2p::crypto::GetElligator ()->Decode (buf, bepk)) - { + { LogPrint (eLogError, "Garlic: Can't decode elligator"); - return false; - } + return false; + } buf += 32; len -= 32; - // KDF for Reply Key Section + // KDF for Reply Key Section uint8_t h[32]; memcpy (h, m_H, 32); // save m_H - MixHash (tag, 8); // h = SHA256(h || tag) - MixHash (bepk, 32); // h = SHA256(h || bepk) - uint8_t sharedSecret[32]; + MixHash (tag, 8); // h = SHA256(h || tag) + MixHash (bepk, 32); // h = SHA256(h || bepk) + uint8_t sharedSecret[32]; if (m_State == eSessionStateNewSessionSent) - { + { // only fist time, we assume ephemeral keys the same - m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) - i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) + m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) - } + } uint8_t nonce[12]; CreateNonce (0, nonce); - // calulate hash for zero length - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anyting */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only + // calculate hash for zero length + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anything */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only { LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed"); return false; } - MixHash (buf, 16); // h = SHA256(h || ciphertext) + MixHash (buf, 16); // h = SHA256(h || ciphertext) buf += 16; len -= 16; // KDF for payload - uint8_t keydata[64]; - i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) + uint8_t keydata[64]; + i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) if (m_State == eSessionStateNewSessionSent) - { - // k_ab = keydata[0:31], k_ba = keydata[32:63] + { + // k_ab = keydata[0:31], k_ba = keydata[32:63] m_SendTagset = std::make_shared(shared_from_this ()); - m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) + m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) m_SendTagset->NextSessionTagRatchet (); auto receiveTagset = std::make_shared(shared_from_this ()); - receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) + receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) receiveTagset->NextSessionTagRatchet (); GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS); - } - i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) + } + i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) // decrypt payload - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); return false; } if (m_State == eSessionStateNewSessionSent) - { + { m_State = eSessionStateEstablished; GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); } - memcpy (m_H, h, 32); // restore m_H - HandlePayload (buf, len - 16, nullptr, 0); + memcpy (m_H, h, 32); // restore m_H + HandlePayload (buf, len - 16, nullptr, 0); // we have received reply to NS with LeaseSet in it SetLeaseSetUpdateStatus (eLeaseSetUpToDate); SetLeaseSetUpdateMsgID (0); - - return true; - } + + return true; + } bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { @@ -578,18 +578,18 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); return false; - } + } if (index >= ECIESX25519_TAGSET_MAX_NUM_TAGS && !m_SendForwardKey) - NewNextSendRatchet (); + NewNextSendRatchet (); return true; } - bool ECIESX25519AEADRatchetSession::HandleExistingSessionMessage (uint8_t * buf, size_t len, + bool ECIESX25519AEADRatchetSession::HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index) { uint8_t nonce[12]; CreateNonce (index, nonce); // tag's index - len -= 8; // tag + len -= 8; // tag uint8_t * payload = buf + 8; uint8_t key[32]; receiveTagset->GetSymmKey (index, key); @@ -597,17 +597,17 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); return false; - } - HandlePayload (payload, len - 16, receiveTagset, index); + } + HandlePayload (payload, len - 16, receiveTagset, index); int moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4 if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS; - moreTags -= (receiveTagset->GetNextIndex () - index); + moreTags -= (receiveTagset->GetNextIndex () - index); if (moreTags > 0) - GenerateMoreReceiveTags (receiveTagset, moreTags); + GenerateMoreReceiveTags (receiveTagset, moreTags); return true; } - bool ECIESX25519AEADRatchetSession::HandleNextMessage (uint8_t * buf, size_t len, + bool ECIESX25519AEADRatchetSession::HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index) { m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); @@ -617,8 +617,8 @@ namespace garlic m_State = eSessionStateEstablished; m_NSRTagset = nullptr; #if (__cplusplus >= 201703L) // C++ 17 or higher - [[fallthrough]]; -#endif + [[fallthrough]]; +#endif case eSessionStateEstablished: if (HandleExistingSessionMessage (buf, len, receiveTagset, index)) return true; // check NSR just in case @@ -637,77 +637,77 @@ namespace garlic return true; } - std::shared_ptr ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr msg) - { - auto payload = CreatePayload (msg, m_State != eSessionStateEstablished); - size_t len = payload.size (); + std::shared_ptr ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr msg) + { + auto payload = CreatePayload (msg, m_State != eSessionStateEstablished); + size_t len = payload.size (); if (!len) return nullptr; auto m = NewI2NPMessage (len + 100); // 96 + 4 m->Align (12); // in order to get buf aligned to 16 (12 + 4) uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length - - switch (m_State) - { + + switch (m_State) + { case eSessionStateEstablished: if (!NewExistingSessionMessage (payload.data (), payload.size (), buf, m->maxLen)) return nullptr; len += 24; - break; - case eSessionStateNew: - if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen)) - return nullptr; - len += 96; - break; - case eSessionStateNewSessionReceived: - if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen)) - return nullptr; - len += 72; - break; + break; + case eSessionStateNew: + if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen)) + return nullptr; + len += 96; + break; + case eSessionStateNewSessionReceived: + if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen)) + return nullptr; + len += 72; + break; case eSessionStateNewSessionReplySent: if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen)) - return nullptr; - len += 72; - break; - default: - return nullptr; - } - - htobe32buf (m->GetPayload (), len); + return nullptr; + len += 72; + break; + default: + return nullptr; + } + + htobe32buf (m->GetPayload (), len); m->len += len + 4; m->FillI2NPMessageHeader (eI2NPGarlic); return m; - } + } - std::vector ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr msg, bool first) - { + std::vector ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr msg, bool first) + { uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); - size_t payloadLen = 0; - if (first) payloadLen += 7;// datatime - if (msg && m_Destination) - payloadLen += msg->GetPayloadLength () + 13 + 32; + size_t payloadLen = 0; + if (first) payloadLen += 7;// datatime + if (msg && m_Destination) + payloadLen += msg->GetPayloadLength () + 13 + 32; auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated || - (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && - ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ? + (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && + ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ? GetOwner ()->GetLeaseSet () : nullptr; if (leaseSet) - { - payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13; - if (!first) + { + payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13; + if (!first) { // ack request SetLeaseSetUpdateStatus (eLeaseSetSubmitted); SetLeaseSetUpdateMsgID (m_SendTagset->GetNextIndex ()); SetLeaseSetSubmissionTime (ts); - payloadLen += 4; - } - } + payloadLen += 4; + } + } if (m_AckRequests.size () > 0) payloadLen += m_AckRequests.size ()*4 + 3; if (m_SendReverseKey) - { + { payloadLen += 6; if (m_NextReceiveRatchet->newKey) payloadLen += 32; - } + } if (m_SendForwardKey) { payloadLen += 6; @@ -715,110 +715,110 @@ namespace garlic } uint8_t paddingSize = 0; if (payloadLen) - { + { int delta = (int)ECIESX25519_OPTIMAL_PAYLOAD_SIZE - (int)payloadLen; if (delta < 0 || delta > 3) // don't create padding if we are close to optimal size { RAND_bytes (&paddingSize, 1); paddingSize &= 0x0F; // 0 - 15 if (delta > 3) - { + { delta -= 3; - if (paddingSize >= delta) paddingSize %= delta; - } + if (paddingSize >= delta) paddingSize %= delta; + } paddingSize++; - payloadLen += paddingSize + 3; - } - } - std::vector v(payloadLen); - size_t offset = 0; - // DateTime + payloadLen += paddingSize + 3; + } + } + std::vector v(payloadLen); + size_t offset = 0; + // DateTime if (first) - { - v[offset] = eECIESx25519BlkDateTime; offset++; - htobe16buf (v.data () + offset, 4); offset += 2; - htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds - } - // LeaseSet - if (leaseSet) - { - offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset); + { + v[offset] = eECIESx25519BlkDateTime; offset++; + htobe16buf (v.data () + offset, 4); offset += 2; + htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds + } + // LeaseSet + if (leaseSet) + { + offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset); if (!first) - { + { // ack request v[offset] = eECIESx25519BlkAckRequest; offset++; htobe16buf (v.data () + offset, 1); offset += 2; v[offset] = 0; offset++; // flags - } - } - // msg - if (msg && m_Destination) - offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); + } + } + // msg + if (msg && m_Destination) + offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); // ack if (m_AckRequests.size () > 0) { v[offset] = eECIESx25519BlkAck; offset++; - htobe16buf (v.data () + offset, m_AckRequests.size ()*4); offset += 2; + htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2; for (auto& it: m_AckRequests) { htobe16buf (v.data () + offset, it.first); offset += 2; htobe16buf (v.data () + offset, it.second); offset += 2; - } + } m_AckRequests.clear (); - } + } // next keys if (m_SendReverseKey) { v[offset] = eECIESx25519BlkNextKey; offset++; htobe16buf (v.data () + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2; - v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG; + v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG; int keyID = m_NextReceiveRatchet->keyID - 1; - if (m_NextReceiveRatchet->newKey) - { + if (m_NextReceiveRatchet->newKey) + { v[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG; keyID++; - } + } offset++; // flag htobe16buf (v.data () + offset, keyID); offset += 2; // keyid if (m_NextReceiveRatchet->newKey) - { - memcpy (v.data () + offset, m_NextReceiveRatchet->key.GetPublicKey (), 32); + { + memcpy (v.data () + offset, m_NextReceiveRatchet->key.GetPublicKey (), 32); offset += 32; // public key - } + } m_SendReverseKey = false; - } + } if (m_SendForwardKey) { v[offset] = eECIESx25519BlkNextKey; offset++; htobe16buf (v.data () + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2; - v[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; + v[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; if (!m_NextSendRatchet->keyID) v[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only offset++; // flag htobe16buf (v.data () + offset, m_NextSendRatchet->keyID); offset += 2; // keyid if (m_NextSendRatchet->newKey) - { - memcpy (v.data () + offset, m_NextSendRatchet->key.GetPublicKey (), 32); + { + memcpy (v.data () + offset, m_NextSendRatchet->key.GetPublicKey (), 32); offset += 32; // public key - } - } - // padding + } + } + // padding if (paddingSize) - { - v[offset] = eECIESx25519BlkPadding; offset++; - htobe16buf (v.data () + offset, paddingSize); offset += 2; - memset (v.data () + offset, 0, paddingSize); offset += paddingSize; - } - return v; - } - - size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len, bool isDestination) - { - if (!msg) return 0; - uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1; + { + v[offset] = eECIESx25519BlkPadding; offset++; + htobe16buf (v.data () + offset, paddingSize); offset += 2; + memset (v.data () + offset, 0, paddingSize); offset += paddingSize; + } + return v; + } + + size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len, bool isDestination) + { + if (!msg) return 0; + uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1; if (isDestination) cloveSize += 32; - if ((int)len < cloveSize + 3) return 0; - buf[0] = eECIESx25519BlkGalicClove; // clove type - htobe16buf (buf + 1, cloveSize); // size + if ((int)len < cloveSize + 3) return 0; + buf[0] = eECIESx25519BlkGalicClove; // clove type + htobe16buf (buf + 1, cloveSize); // size buf += 3; if (isDestination) { @@ -826,88 +826,86 @@ namespace garlic memcpy (buf + 1, *m_Destination, 32); buf += 32; } else - *buf = 0; + *buf = 0; buf++; // flag and delivery instructions - *buf = msg->GetTypeID (); // I2NP msg type - htobe32buf (buf + 1, msg->GetMsgID ()); // msgID - htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds - memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ()); - return cloveSize + 3; - } + *buf = msg->GetTypeID (); // I2NP msg type + htobe32buf (buf + 1, msg->GetMsgID ()); // msgID + htobe32buf (buf + 5, msg->GetExpiration () / 1000); // expiration in seconds + memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ()); + return cloveSize + 3; + } size_t ECIESX25519AEADRatchetSession::CreateLeaseSetClove (std::shared_ptr ls, uint64_t ts, uint8_t * buf, size_t len) - { + { if (!ls || ls->GetStoreType () != i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) { LogPrint (eLogError, "Garlic: Incorrect LeasetSet type to send"); return 0; - } + } uint16_t cloveSize = 1 + 9 + DATABASE_STORE_HEADER_SIZE + ls->GetBufferLen (); // to local if ((int)len < cloveSize + 3) return 0; buf[0] = eECIESx25519BlkGalicClove; // clove type - htobe16buf (buf + 1, cloveSize); // size + htobe16buf (buf + 1, cloveSize); // size buf += 3; *buf = 0; buf++; // flag and delivery instructions *buf = eI2NPDatabaseStore; buf++; // I2NP msg type RAND_bytes (buf, 4); buf += 4; // msgID - htobe32buf (buf, (ts + I2NP_MESSAGE_EXPIRATION_TIMEOUT)/1000); buf += 4; // expiration + htobe32buf (buf, (ts + I2NP_MESSAGE_EXPIRATION_TIMEOUT)/1000); buf += 4; // expiration // payload memcpy (buf + DATABASE_STORE_KEY_OFFSET, ls->GetStoreHash (), 32); buf[DATABASE_STORE_TYPE_OFFSET] = i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2; - memset (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // replyToken = 0 + memset (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // replyToken = 0 buf += DATABASE_STORE_HEADER_SIZE; memcpy (buf, ls->GetBuffer (), ls->GetBufferLen ()); return cloveSize + 3; } - + void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags) { for (int i = 0; i < numTags; i++) GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset); - } + } bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts) - { + { CleanupUnconfirmedLeaseSet (ts); - return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT; - } - + return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT; + } + std::shared_ptr WrapECIESX25519AEADRatchetMessage (std::shared_ptr msg, const uint8_t * key, uint64_t tag) { auto m = NewI2NPMessage (); m->Align (12); // in order to get buf aligned to 16 (12 + 4) uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length uint8_t nonce[12]; - memset (nonce, 0, 12); // n = 0 + memset (nonce, 0, 12); // n = 0 size_t offset = 0; memcpy (buf + offset, &tag, 8); offset += 8; auto payload = buf + offset; uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1; size_t len = cloveSize + 3; - payload[0] = eECIESx25519BlkGalicClove; // clove type - htobe16buf (payload + 1, cloveSize); // size + payload[0] = eECIESx25519BlkGalicClove; // clove type + htobe16buf (payload + 1, cloveSize); // size payload += 3; - *payload = 0; payload++; // flag and delivery instructions - *payload = msg->GetTypeID (); // I2NP msg type - htobe32buf (payload + 1, msg->GetMsgID ()); // msgID - htobe32buf (payload + 5, msg->GetExpiration ()/1000); // expiration in seconds - memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ()); + *payload = 0; payload++; // flag and delivery instructions + *payload = msg->GetTypeID (); // I2NP msg type + htobe32buf (payload + 1, msg->GetMsgID ()); // msgID + htobe32buf (payload + 5, msg->GetExpiration () / 1000); // expiration in seconds + memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ()); if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); return nullptr; - } + } offset += len + 16; - + htobe32buf (m->GetPayload (), offset); m->len += offset + 4; m->FillI2NPMessageHeader (eI2NPGarlic); return m; } - + } } - - diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 14f97ce9..d5a83f89 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -25,22 +25,22 @@ namespace garlic const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24; const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160; const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12; - - const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */ + + const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */ // - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */ - + class ECIESX25519AEADRatchetSession; - class RatchetTagSet - { - public: - - RatchetTagSet (std::shared_ptr session): m_Session (session) {}; - - void DHInitialize (const uint8_t * rootKey, const uint8_t * k); - void NextSessionTagRatchet (); - uint64_t GetNextSessionTag (); + class RatchetTagSet + { + public: + + RatchetTagSet (std::shared_ptr session): m_Session (session) {}; + + void DHInitialize (const uint8_t * rootKey, const uint8_t * k); + void NextSessionTagRatchet (); + uint64_t GetNextSessionTag (); const uint8_t * GetNextRootKey () const { return m_NextRootKey; }; - int GetNextIndex () const { return m_NextIndex; }; + int GetNextIndex () const { return m_NextIndex; }; void GetSymmKey (int index, uint8_t * key); std::shared_ptr GetSession () { return m_Session.lock (); }; @@ -49,54 +49,54 @@ namespace garlic void Expire (); bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; }; - + private: - - union - { - uint64_t ll[8]; - uint8_t buf[64]; - - const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31] - const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63] - uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39] - - } m_KeyData; - uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32]; - int m_NextIndex, m_NextSymmKeyIndex; - std::unordered_map > m_ItermediateSymmKeys; - std::weak_ptr m_Session; - int m_TagSetID = 0; - uint64_t m_ExpirationTimestamp = 0; - }; - - enum ECIESx25519BlockType + + union + { + uint64_t ll[8]; + uint8_t buf[64]; + + const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31] + const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63] + uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39] + + } m_KeyData; + uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32]; + int m_NextIndex, m_NextSymmKeyIndex; + std::unordered_map > m_ItermediateSymmKeys; + std::weak_ptr m_Session; + int m_TagSetID = 0; + uint64_t m_ExpirationTimestamp = 0; + }; + + enum ECIESx25519BlockType { - eECIESx25519BlkDateTime = 0, - eECIESx25519BlkSessionID = 1, + eECIESx25519BlkDateTime = 0, + eECIESx25519BlkSessionID = 1, eECIESx25519BlkTermination = 4, - eECIESx25519BlkOptions = 5, - eECIESx25519BlkNextKey = 7, - eECIESx25519BlkAck = 8, - eECIESx25519BlkAckRequest = 9, - eECIESx25519BlkGalicClove = 11, - eECIESx25519BlkPadding = 254 - }; + eECIESx25519BlkOptions = 5, + eECIESx25519BlkNextKey = 7, + eECIESx25519BlkAck = 8, + eECIESx25519BlkAckRequest = 9, + eECIESx25519BlkGalicClove = 11, + eECIESx25519BlkPadding = 254 + }; const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01; const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02; const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04; - - class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this - { - enum SessionState - { - eSessionStateNew =0, - eSessionStateNewSessionReceived, + + class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this + { + enum SessionState + { + eSessionStateNew = 0, + eSessionStateNewSessionReceived, eSessionStateNewSessionSent, eSessionStateNewSessionReplySent, - eSessionStateEstablished - }; + eSessionStateEstablished + }; struct DHRatchet { @@ -104,65 +104,65 @@ namespace garlic i2p::crypto::X25519Keys key; uint8_t remote[32]; // last remote public key bool newKey = true; - }; - - public: + }; - ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet); - ~ECIESX25519AEADRatchetSession (); + public: + + ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet); + ~ECIESX25519AEADRatchetSession (); bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index = 0); - std::shared_ptr WrapSingleMessage (std::shared_ptr msg); - - const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } + std::shared_ptr WrapSingleMessage (std::shared_ptr msg); + + const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); } void SetDestination (const i2p::data::IdentHash& dest) // TODO: { if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest)); } - + bool CheckExpired (uint64_t ts); // true is expired bool CanBeRestarted (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_RESTART_TIMEOUT; } bool IsRatchets () const { return true; }; - - private: + + private: void ResetKeys (); - void MixHash (const uint8_t * buf, size_t len); + void MixHash (const uint8_t * buf, size_t len); void CreateNonce (uint64_t seqn, uint8_t * nonce); - bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes + bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes std::shared_ptr CreateNewSessionTagset (); bool HandleNewIncomingSession (const uint8_t * buf, size_t len); - bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len); + bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len); bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index); - void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index); + void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index); void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset); - - bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); - bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); + + bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); + bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); - - std::vector CreatePayload (std::shared_ptr msg, bool first); - size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len, bool isDestination = false); + + std::vector CreatePayload (std::shared_ptr msg, bool first); + size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len, bool isDestination = false); size_t CreateLeaseSetClove (std::shared_ptr ls, uint64_t ts, uint8_t * buf, size_t len); - + void GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags); void NewNextSendRatchet (); - - private: - uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32]; + private: + + uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32]; uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only - i2p::crypto::X25519Keys m_EphemeralKeys; - SessionState m_State = eSessionStateNew; + i2p::crypto::X25519Keys m_EphemeralKeys; + SessionState m_State = eSessionStateNew; uint64_t m_LastActivityTimestamp = 0; // incoming - std::shared_ptr m_SendTagset, m_NSRTagset; - std::unique_ptr m_Destination;// TODO: might not need it + std::shared_ptr m_SendTagset, m_NSRTagset; + std::unique_ptr m_Destination;// TODO: might not need it std::list > m_AckRequests; // (tagsetid, index) bool m_SendReverseKey = false, m_SendForwardKey = false; std::unique_ptr m_NextReceiveRatchet, m_NextSendRatchet; @@ -174,8 +174,8 @@ namespace garlic i2p::data::IdentHash GetDestination () const { return m_Destination ? *m_Destination : i2p::data::IdentHash (); - } - }; + } + }; std::shared_ptr WrapECIESX25519AEADRatchetMessage (std::shared_ptr msg, const uint8_t * key, uint64_t tag); } diff --git a/libi2pd/Ed25519.cpp b/libi2pd/Ed25519.cpp index 69fec4e8..8de5e3a1 100644 --- a/libi2pd/Ed25519.cpp +++ b/libi2pd/Ed25519.cpp @@ -121,7 +121,7 @@ namespace crypto return passed; } - void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, + void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const { BN_CTX * bnCtx = BN_CTX_new (); @@ -153,7 +153,7 @@ namespace crypto BN_CTX_free (bnCtx); } - void Ed25519::SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, + void Ed25519::SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const { BN_CTX * bnCtx = BN_CTX_new (); @@ -164,16 +164,16 @@ namespace crypto SHA512_CTX ctx; SHA512_Init (&ctx); SHA512_Update (&ctx, T, 80); - SHA512_Update (&ctx, publicKeyEncoded, 32); + SHA512_Update (&ctx, publicKeyEncoded, 32); SHA512_Update (&ctx, buf, len); // data uint8_t digest[64]; SHA512_Final (digest, &ctx); - BIGNUM * r = DecodeBN<64> (digest); - BN_mod (r, r, l, bnCtx); // % l + BIGNUM * r = DecodeBN<64> (digest); + BN_mod (r, r, l, bnCtx); // % l EncodeBN (r, digest, 32); // calculate R uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf - EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); + EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // calculate S SHA512_Init (&ctx); SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R @@ -182,7 +182,7 @@ namespace crypto SHA512_Final (digest, &ctx); BIGNUM * h = DecodeBN<64> (digest); // S = (r + h*a) % l - BIGNUM * a = DecodeBN (privateKey); + BIGNUM * a = DecodeBN (privateKey); BN_mod_mul (h, h, a, l, bnCtx); // %l BN_mod_add (h, h, r, l, bnCtx); // %l memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2); @@ -190,7 +190,7 @@ namespace crypto BN_free (r); BN_free (h); BN_free (a); BN_CTX_free (bnCtx); } - + EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const { // x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2) @@ -467,7 +467,7 @@ namespace crypto --bits; auto k_t = BN_is_bit_set(k, bits) ? 1 : 0; swap ^= k_t; - if (swap) + if (swap) { std::swap (x2, x3); std::swap (z2, z3); @@ -492,7 +492,7 @@ namespace crypto BN_mod_mul(z3, x1, z2, q, ctx); BN_mod_mul(z2, tmp1, tmp0, q, ctx); } - if (swap) + if (swap) { std::swap (x2, x3); std::swap (z2, z3); @@ -533,9 +533,9 @@ namespace crypto { BN_CTX * ctx = BN_CTX_new (); // calculate alpha = seed mod l - BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian + BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian BN_mod (alpha, alpha, l, ctx); // % l - uint8_t priv[32]; + uint8_t priv[32]; EncodeBN (alpha, priv, 32); // back to Little Endian BN_free (alpha); // A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha) @@ -548,16 +548,16 @@ namespace crypto { BN_CTX * ctx = BN_CTX_new (); // calculate alpha = seed mod l - BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian + BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian BN_mod (alpha, alpha, l, ctx); // % l - BIGNUM * p = DecodeBN<32> (priv); // priv is in Little Endian + BIGNUM * p = DecodeBN<32> (priv); // priv is in Little Endian BN_add (alpha, alpha, p); // alpha = alpha + priv - // a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod L + // a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod L BN_mod (alpha, alpha, l, ctx); // % l EncodeBN (alpha, blindedPriv, 32); - // A' = DERIVE_PUBLIC(a') + // A' = DERIVE_PUBLIC(a') auto A1 = MulB (blindedPriv, ctx); - EncodePublicKey (A1, blindedPub, ctx); + EncodePublicKey (A1, blindedPub, ctx); BN_free (alpha); BN_free (p); BN_CTX_free (ctx); } @@ -574,14 +574,14 @@ namespace crypto { uint8_t seed[32]; RAND_bytes (seed, 32); - BIGNUM * p = DecodeBN<32> (seed); + BIGNUM * p = DecodeBN<32> (seed); BN_CTX * ctx = BN_CTX_new (); BN_mod (p, p, l, ctx); // % l - EncodeBN (p, priv, 32); + EncodeBN (p, priv, 32); BN_CTX_free (ctx); BN_free (p); - } - + } + static std::unique_ptr g_Ed25519; std::unique_ptr& GetEd25519 () { @@ -597,4 +597,3 @@ namespace crypto } } } - diff --git a/libi2pd/Ed25519.h b/libi2pd/Ed25519.h index 84501b03..10061ad0 100644 --- a/libi2pd/Ed25519.h +++ b/libi2pd/Ed25519.h @@ -86,10 +86,10 @@ namespace crypto bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const; void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const; void SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const; - + static void ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey); // key - 32 bytes, expandedKey - 64 bytes void CreateRedDSAPrivateKey (uint8_t * priv); // priv is 32 bytes - + private: EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const; @@ -97,8 +97,8 @@ namespace crypto EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const; EDDSAPoint MulB (const uint8_t * e, BN_CTX * ctx) const; // B*e, e is 32 bytes Little Endian EDDSAPoint Normalize (const EDDSAPoint& p, BN_CTX * ctx) const; - - bool IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const; + + bool IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const; BIGNUM * RecoverX (const BIGNUM * y, BN_CTX * ctx) const; EDDSAPoint DecodePoint (const uint8_t * buf, BN_CTX * ctx) const; void EncodePoint (const EDDSAPoint& p, uint8_t * buf) const; @@ -109,7 +109,7 @@ namespace crypto #if !OPENSSL_X25519 // for x25519 - BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const; + BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const; #endif private: @@ -121,13 +121,11 @@ namespace crypto // if j > 128 we use 256 - j and carry 1 to next byte // Bi256[0][0] = B, base point EDDSAPoint Bi256Carry; // Bi256[32][0] - }; + }; std::unique_ptr& GetEd25519 (); } } - #endif - diff --git a/libi2pd/Elligator.cpp b/libi2pd/Elligator.cpp index 48a5a7ac..8fefb2ae 100644 --- a/libi2pd/Elligator.cpp +++ b/libi2pd/Elligator.cpp @@ -6,7 +6,7 @@ namespace i2p { namespace crypto { - + Elligator2::Elligator2 () { // TODO: share with Ed22519 @@ -21,32 +21,32 @@ namespace crypto 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) + BN_CTX * ctx = BN_CTX_new (); + // calculate sqrt(-1) sqrtn1 = BN_new (); - BN_set_word (sqrtn1, 2); + BN_set_word (sqrtn1, 2); BN_mod_exp (sqrtn1, sqrtn1, p14, p, ctx); // 2^((p-1)/4 - + u = BN_new (); BN_set_word (u, 2); - iu = BN_new (); BN_mod_inverse (iu, u, p, ctx); - + iu = BN_new (); BN_mod_inverse (iu, u, p, ctx); + BN_CTX_free (ctx); } Elligator2::~Elligator2 () { 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); + BN_free (sqrtn1); BN_free (A); BN_free (nA); + BN_free (u); BN_free (iu); } bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const - { + { bool ret = true; BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); - uint8_t key1[32]; + uint8_t key1[32]; for (size_t i = 0; i < 16; i++) // from Little Endian { key1[i] = key[31 - i]; @@ -59,35 +59,35 @@ namespace crypto 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); - + BN_mod_mul (uxxA, uxxA, xA, p, ctx); + if (Legendre (uxxA, ctx) != -1) - { - uint8_t randByte = 0; // random highest bits and high y + { + uint8_t randByte = 0; // random highest bits and high y if (random) - { - RAND_bytes (&randByte, 1); - highY = randByte & 0x01; + { + RAND_bytes (&randByte, 1); + highY = randByte & 0x01; } - + BIGNUM * r = BN_CTX_get (ctx); if (highY) { BN_mod_inverse (r, x, p, ctx); - BN_mod_mul (r, r, xA, p, ctx); + BN_mod_mul (r, r, xA, p, ctx); } else { - BN_mod_inverse (r, xA, p, 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 (r, r, iu, p, ctx); + SquareRoot (r, r, ctx); bn2buf (r, encoded, 32); if (random) - encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte + encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte for (size_t i = 0; i < 16; i++) // To Little Endian { uint8_t tmp = encoded[i]; @@ -98,7 +98,7 @@ namespace crypto else ret = false; - BN_CTX_end (ctx); + BN_CTX_end (ctx); BN_CTX_free (ctx); return ret; } @@ -109,31 +109,31 @@ namespace crypto BN_CTX * ctx = BN_CTX_new (); BN_CTX_start (ctx); - uint8_t encoded1[32]; + uint8_t encoded1[32]; for (size_t i = 0; i < 16; i++) // from Little Endian { encoded1[i] = encoded[31 - i]; encoded1[31 - i] = encoded[i]; } - encoded1[0] &= 0x3F; // drop two highest bits + encoded1[0] &= 0x3F; // drop two highest bits BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r); 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); + 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_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); + 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); @@ -143,9 +143,9 @@ namespace crypto { BN_sub (x, p, v); BN_mod_sub (x, x, A, p, ctx); - } - - bn2buf (x, key, 32); + } + + bn2buf (x, key, 32); for (size_t i = 0; i < 16; i++) // To Little Endian { uint8_t tmp = key[i]; @@ -156,7 +156,7 @@ namespace crypto else ret = false; - BN_CTX_end (ctx); + BN_CTX_end (ctx); BN_CTX_free (ctx); return ret; @@ -170,21 +170,21 @@ namespace crypto BN_add_word (t, 1); if (!BN_cmp (t, p)) - BN_mod_mul (r, r, sqrtn1, p, ctx); + BN_mod_mul (r, r, sqrtn1, p, ctx); if (BN_cmp (r, p12) > 0) // r > (p-1)/2 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, but a = 0 only - if (BN_is_zero(a)) return 0; + 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)) + if (BN_is_word(r, 1)) return 1; - else if (BN_is_zero(r)) + else if (BN_is_zero(r)) return 0; return -1; } @@ -204,4 +204,3 @@ namespace crypto } } } - diff --git a/libi2pd/Elligator.h b/libi2pd/Elligator.h index 7cdcbbfe..56fbc2eb 100644 --- a/libi2pd/Elligator.h +++ b/libi2pd/Elligator.h @@ -20,11 +20,11 @@ namespace crypto bool Encode (const uint8_t * key, uint8_t * encoded, bool highY = false, bool random = true) const; bool Decode (const uint8_t * encoded, uint8_t * key) const; - private: + private: void SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const; int Legendre (const BIGNUM * a, BN_CTX * ctx) const; // a/p - + private: BIGNUM * p, * p38, * p12, * p14, * sqrtn1, * A, * nA, * u, * iu; @@ -35,5 +35,3 @@ namespace crypto } #endif - - diff --git a/libi2pd/FS.h b/libi2pd/FS.h index 6f112218..054ac2a3 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -17,133 +17,136 @@ namespace i2p { namespace fs { - extern std::string dirSep; - - /** - * @brief Class to work with NetDb & Router profiles - * - * Usage: - * - * const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; - * auto h = HashedStorage("name", "y", "z-", ".txt"); - * h.SetPlace("/tmp/hs-test"); - * h.GetName() -> gives "name" - * h.GetRoot() -> gives "/tmp/hs-test/name" - * h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet - * h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt - * h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists - * std::vector files; - * h.Traverse(files); <- finds all files in storage and saves in given vector - */ - class HashedStorage { - protected: - std::string root; /**< path to storage with it's name included */ - std::string name; /**< name of the storage */ - std::string prefix1; /**< hashed directory prefix */ - std::string prefix2; /**< prefix of file in storage */ - std::string suffix; /**< suffix of file in storage (extension) */ - - public: - typedef std::function FilenameVisitor; - HashedStorage(const char *n, const char *p1, const char *p2, const char *s): - name(n), prefix1(p1), prefix2(p2), suffix(s) {}; - - /** create subdirs in storage */ - bool Init(const char* chars, size_t cnt); - const std::string & GetRoot() const { return root; } - const std::string & GetName() const { return name; } - /** set directory where to place storage directory */ - void SetPlace(const std::string & path); - /** path to file with given ident */ - std::string Path(const std::string & ident) const; - /** remove file by ident */ - void Remove(const std::string & ident); - /** find all files in storage and store list in provided vector */ - void Traverse(std::vector & files); - /** visit every file in this storage with a visitor */ - void Iterate(FilenameVisitor v); - }; - - /** @brief Returns current application name, default 'i2pd' */ + extern std::string dirSep; + + /** + * @brief Class to work with NetDb & Router profiles + * + * Usage: + * + * const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; + * auto h = HashedStorage("name", "y", "z-", ".txt"); + * h.SetPlace("/tmp/hs-test"); + * h.GetName() -> gives "name" + * h.GetRoot() -> gives "/tmp/hs-test/name" + * h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet + * h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt + * h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists + * std::vector files; + * h.Traverse(files); <- finds all files in storage and saves in given vector + */ + class HashedStorage + { + protected: + + std::string root; /**< path to storage with it's name included */ + std::string name; /**< name of the storage */ + std::string prefix1; /**< hashed directory prefix */ + std::string prefix2; /**< prefix of file in storage */ + std::string suffix; /**< suffix of file in storage (extension) */ + + public: + + typedef std::function FilenameVisitor; + HashedStorage(const char *n, const char *p1, const char *p2, const char *s): + name(n), prefix1(p1), prefix2(p2), suffix(s) {}; + + /** create subdirs in storage */ + bool Init(const char* chars, size_t cnt); + const std::string & GetRoot() const { return root; } + const std::string & GetName() const { return name; } + /** set directory where to place storage directory */ + void SetPlace(const std::string & path); + /** path to file with given ident */ + std::string Path(const std::string & ident) const; + /** remove file by ident */ + void Remove(const std::string & ident); + /** find all files in storage and store list in provided vector */ + void Traverse(std::vector & files); + /** visit every file in this storage with a visitor */ + void Iterate(FilenameVisitor v); + }; + + /** @brief Returns current application name, default 'i2pd' */ const std::string & GetAppName (); - /** @brief Set application name, affects autodetection of datadir */ + /** @brief Set application name, affects autodetection of datadir */ void SetAppName (const std::string& name); - /** @brief Returns datadir path */ - const std::string & GetDataDir(); - - /** - * @brief Set datadir either from cmdline option or using autodetection - * @param cmdline_param Value of cmdline parameter --datadir= - * @param isService Value of cmdline parameter --service - * - * Examples of autodetected paths: - * - * Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\ - * Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\ - * Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/ - * Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/ - */ - void DetectDataDir(const std::string & cmdline_datadir, bool isService = false); - - /** - * @brief Create subdirectories inside datadir - */ - bool Init(); - - /** - * @brief Get list of files in directory - * @param path Path to directory - * @param files Vector to store found files - * @return true on success and false if directory not exists - */ - bool ReadDir(const std::string & path, std::vector & files); - - /** - * @brief Remove file with given path - * @param path Absolute path to file - * @return true on success, false if file not exists, throws exception on error - */ - bool Remove(const std::string & path); - - /** - * @brief Check existence of file - * @param path Absolute path to file - * @return true if file exists, false otherwise - */ - bool Exists(const std::string & path); - - uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch - - bool CreateDirectory (const std::string& path); - - template - void _ExpandPath(std::stringstream & path, T c) { - path << i2p::fs::dirSep << c; - } - - template - void _ExpandPath(std::stringstream & path, T c, Other ... other) { - _ExpandPath(path, c); - _ExpandPath(path, other ...); - } - - /** - * @brief Get path relative to datadir - * - * Examples (with datadir = "/tmp/i2pd"): - * - * i2p::fs::Path("test") -> '/tmp/i2pd/test' - * i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt' - */ - template - std::string DataDirPath(Other ... components) { - std::stringstream s(""); - s << i2p::fs::GetDataDir(); - _ExpandPath(s, components ...); - - return s.str(); - } + /** @brief Returns datadir path */ + const std::string & GetDataDir(); + + /** + * @brief Set datadir either from cmdline option or using autodetection + * @param cmdline_param Value of cmdline parameter --datadir= + * @param isService Value of cmdline parameter --service + * + * Examples of autodetected paths: + * + * Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\ + * Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\ + * Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/ + * Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/ + */ + void DetectDataDir(const std::string & cmdline_datadir, bool isService = false); + + /** + * @brief Create subdirectories inside datadir + */ + bool Init(); + + /** + * @brief Get list of files in directory + * @param path Path to directory + * @param files Vector to store found files + * @return true on success and false if directory not exists + */ + bool ReadDir(const std::string & path, std::vector & files); + + /** + * @brief Remove file with given path + * @param path Absolute path to file + * @return true on success, false if file not exists, throws exception on error + */ + bool Remove(const std::string & path); + + /** + * @brief Check existence of file + * @param path Absolute path to file + * @return true if file exists, false otherwise + */ + bool Exists(const std::string & path); + + uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch + + bool CreateDirectory (const std::string& path); + + template + void _ExpandPath(std::stringstream & path, T c) { + path << i2p::fs::dirSep << c; + } + + template + void _ExpandPath(std::stringstream & path, T c, Other ... other) { + _ExpandPath(path, c); + _ExpandPath(path, other ...); + } + + /** + * @brief Get path relative to datadir + * + * Examples (with datadir = "/tmp/i2pd"): + * + * i2p::fs::Path("test") -> '/tmp/i2pd/test' + * i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt' + */ + template + std::string DataDirPath(Other ... components) { + std::stringstream s(""); + s << i2p::fs::GetDataDir(); + _ExpandPath(s, components ...); + + return s.str(); + } template std::string StorageRootPath (const Storage& storage, Filename... filenames) diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index bc99bb52..e5ac9990 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -179,4 +179,3 @@ namespace data } } } - diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 8ba4a8a1..5d07155e 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -38,9 +38,9 @@ namespace garlic if (!m_SharedRoutingPath) return nullptr; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED || - !m_SharedRoutingPath->outboundTunnel->IsEstablished () || + !m_SharedRoutingPath->outboundTunnel->IsEstablished () || ts*1000LL > m_SharedRoutingPath->remoteLease->endDate || - ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT) + ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT) m_SharedRoutingPath = nullptr; if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++; return m_SharedRoutingPath; @@ -68,7 +68,7 @@ namespace garlic return true; } return false; - } + } void GarlicRoutingSession::CleanupUnconfirmedLeaseSet (uint64_t ts) { @@ -78,8 +78,8 @@ namespace garlic GetOwner ()->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); m_LeaseSetUpdateMsgID = 0; } - } - + } + std::shared_ptr GarlicRoutingSession::CreateEncryptedDeliveryStatusMsg (uint32_t msgID) { auto msg = CreateDeliveryStatusMsg (msgID); @@ -94,12 +94,12 @@ namespace garlic msg = garlic.WrapSingleMessage (msg); } return msg; - } - - ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner, - std::shared_ptr destination, int numTags, bool attachLeaseSet): - GarlicRoutingSession (owner, attachLeaseSet), - m_Destination (destination), m_NumTags (numTags) + } + + ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner, + std::shared_ptr destination, int numTags, bool attachLeaseSet): + GarlicRoutingSession (owner, attachLeaseSet), + m_Destination (destination), m_NumTags (numTags) { // create new session tags and session key RAND_bytes (m_SessionKey, 32); @@ -115,7 +115,7 @@ namespace garlic m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch (); } - std::shared_ptr ElGamalAESSession::WrapSingleMessage (std::shared_ptr msg) + std::shared_ptr ElGamalAESSession::WrapSingleMessage (std::shared_ptr msg) { auto m = NewI2NPMessage (); m->Align (12); // in order to get buf aligned to 16 (12 + 4) @@ -181,7 +181,7 @@ namespace garlic return m; } - size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr msg) + size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr msg) { size_t blockSize = 0; bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3); @@ -329,10 +329,10 @@ namespace garlic // create msg auto msg = CreateEncryptedDeliveryStatusMsg (msgID); if (msg) - { + { memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); size += msg->GetLength (); - } + } // fill clove uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec uint32_t cloveID; @@ -353,7 +353,7 @@ namespace garlic return size; } - ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags () + ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags () { auto tags = new UnconfirmedTags (m_NumTags); tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch (); @@ -487,7 +487,7 @@ namespace garlic LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes"); } else - { + { bool found = false; if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)) { @@ -500,15 +500,15 @@ namespace garlic found = true; auto session = it1->second.tagset->GetSession (); if (!session || !session->HandleNextMessage (buf, length, it1->second.tagset, it1->second.index)) - LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); + LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); m_ECIESx25519Tags.erase (it1); } - } - - if (!found) // assume new session + } + + if (!found) // assume new session { - // AES tag not found. Handle depending on encryption type - // try ElGamal/AES first if leading block is 514 + // AES tag not found. Handle depending on encryption type + // try ElGamal/AES first if leading block is 514 ElGamalBlock elGamal; if (mod == 2 && length >= 514 && SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)) @@ -521,16 +521,16 @@ namespace garlic HandleAESBlock (buf + 514, length - 514, decryption, msg->from); } else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)) - { - // otherwise ECIESx25519 + { + // otherwise ECIESx25519 auto session = std::make_shared (this, false); // incoming if (!session->HandleNextMessage (buf, length, nullptr, 0)) - LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); - } + LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); + } else - LogPrint (eLogError, "Garlic: Failed to decrypt message"); + LogPrint (eLogError, "Garlic: Failed to decrypt message"); } - } + } } void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, @@ -703,41 +703,41 @@ namespace garlic std::shared_ptr GarlicDestination::GetRoutingSession ( std::shared_ptr destination, bool attachLeaseSet) { - if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET && - SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)) - { - ECIESX25519AEADRatchetSessionPtr session; - uint8_t staticKey[32]; - destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key - auto it = m_ECIESx25519Sessions.find (staticKey); + if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET && + SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)) + { + ECIESX25519AEADRatchetSessionPtr session; + uint8_t staticKey[32]; + destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key + auto it = m_ECIESx25519Sessions.find (staticKey); if (it != m_ECIESx25519Sessions.end ()) - session = it->second; - if (!session) + session = it->second; + if (!session) { session = std::make_shared (this, true); session->SetRemoteStaticKey (staticKey); - } + } session->SetDestination (destination->GetIdentHash ()); // TODO: remove - return session; - } - else - { - ElGamalAESSessionPtr session; - { - std::unique_lock l(m_SessionsMutex); - auto it = m_Sessions.find (destination->GetIdentHash ()); - if (it != m_Sessions.end ()) - session = it->second; - } - if (!session) - { - session = std::make_shared (this, destination, - attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests - std::unique_lock l(m_SessionsMutex); - m_Sessions[destination->GetIdentHash ()] = session; - } - return session; - } + return session; + } + else + { + ElGamalAESSessionPtr session; + { + std::unique_lock l(m_SessionsMutex); + auto it = m_Sessions.find (destination->GetIdentHash ()); + if (it != m_Sessions.end ()) + session = it->second; + } + if (!session) + { + session = std::make_shared (this, destination, + attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests + std::unique_lock l(m_SessionsMutex); + m_Sessions[destination->GetIdentHash ()] = session; + } + return session; + } } void GarlicDestination::CleanupExpiredTags () @@ -791,7 +791,7 @@ namespace garlic if (it->second.tagset->IsExpired (ts) || ts > it->second.creationTime + ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT) it = m_ECIESx25519Tags.erase (it); else - ++it; + ++it; } for (auto it = m_ECIESx25519Sessions.begin (); it != m_ECIESx25519Sessions.end ();) @@ -800,7 +800,7 @@ namespace garlic { it->second->SetOwner (nullptr); it = m_ECIESx25519Sessions.erase (it); - } + } else ++it; } @@ -925,28 +925,28 @@ namespace garlic std::vector files; i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - for (auto it: files) + for (auto it: files) if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT) i2p::fs::Remove (it); } - void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len) - { - const uint8_t * buf1 = buf; + 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"); + LogPrint (eLogDebug, "Garlic: type destination"); buf += 32; // TODO: check destination -#if (__cplusplus >= 201703L) // C++ 17 or higher - [[fallthrough]]; -#endif +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif // no break here case eGarlicDeliveryTypeLocal: { - LogPrint (eLogDebug, "Garlic: type local"); + LogPrint (eLogDebug, "Garlic: type local"); I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid buf += (4 + 4); // msgID + expiration ptrdiff_t offset = buf - buf1; @@ -957,8 +957,8 @@ namespace garlic break; } case eGarlicDeliveryTypeTunnel: - { - LogPrint (eLogDebug, "Garlic: type tunnel"); + { + LogPrint (eLogDebug, "Garlic: type tunnel"); // gwHash and gwTunnel sequence is reverted const uint8_t * gwHash = buf; buf += 32; @@ -968,47 +968,47 @@ namespace garlic LogPrint (eLogError, "Garlic: message is too short"); break; } - uint32_t gwTunnel = bufbe32toh (buf); buf += 4; - I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid + uint32_t gwTunnel = bufbe32toh (buf); buf += 4; + I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid buf += (4 + 4); // msgID + expiration - offset += 13; + offset += 13; if (GetTunnelPool ()) - { - auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel (); - if (tunnel) - tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset)); + { + 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"); - } + LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove"); + } else LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel"); - break; - } + break; + } default: LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); - } - } + } + } - void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset) - { + void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset) + { auto index = tagset->GetNextIndex (); uint64_t tag = tagset->GetNextSessionTag (); - m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()}); - } + m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()}); + } void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session) { i2p::data::Tag<32> staticKeyTag (staticKey); auto it = m_ECIESx25519Sessions.find (staticKeyTag); if (it != m_ECIESx25519Sessions.end ()) - { + { if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ())) m_ECIESx25519Sessions.erase (it); else { - LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists"); + LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists"); return; - } + } } m_ECIESx25519Sessions.emplace (staticKeyTag, session); } @@ -1020,7 +1020,7 @@ namespace garlic { it->second->SetOwner (nullptr); m_ECIESx25519Sessions.erase (it); - } - } + } + } } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 86c9e432..55ebe795 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -87,8 +87,8 @@ namespace garlic class GarlicDestination; class GarlicRoutingSession { - protected: - + protected: + enum LeaseSetUpdateStatus { eLeaseSetUpToDate = 0, @@ -103,10 +103,10 @@ namespace garlic GarlicRoutingSession (); virtual ~GarlicRoutingSession (); virtual std::shared_ptr WrapSingleMessage (std::shared_ptr msg) = 0; - virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession + virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession virtual bool MessageConfirmed (uint32_t msgID); virtual bool IsRatchets () const { return false; }; - + void SetLeaseSetUpdated () { if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; @@ -115,23 +115,23 @@ namespace garlic bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; }; uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; } void CleanupUnconfirmedLeaseSet (uint64_t ts); - + std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); GarlicDestination * GetOwner () const { return m_Owner; } void SetOwner (GarlicDestination * owner) { m_Owner = owner; } - - protected: - - LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; } - void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; } - uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; } - void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; } - void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; } + + protected: + + LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; } + void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; } + uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; } + void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; } + void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; } std::shared_ptr CreateEncryptedDeliveryStatusMsg (uint32_t msgID); - + private: GarlicDestination * m_Owner; @@ -143,38 +143,39 @@ namespace garlic std::shared_ptr m_SharedRoutingPath; public: + // for HTTP only virtual size_t GetNumOutgoingTags () const { return 0; }; }; - //using GarlicRoutingSessionPtr = std::shared_ptr; - typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 + //using GarlicRoutingSessionPtr = std::shared_ptr; + typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 - class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this - { - struct UnconfirmedTags - { - UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; }; - ~UnconfirmedTags () { delete[] sessionTags; }; - uint32_t msgID; - int numTags; - SessionTag * sessionTags; - uint32_t tagsCreationTime; - }; + class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this + { + struct UnconfirmedTags + { + UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; }; + ~UnconfirmedTags () { delete[] sessionTags; }; + uint32_t msgID; + int numTags; + SessionTag * sessionTags; + uint32_t tagsCreationTime; + }; - public: + public: - ElGamalAESSession (GarlicDestination * owner, std::shared_ptr destination, + ElGamalAESSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet); ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption ~ElGamalAESSession () {}; - std::shared_ptr WrapSingleMessage (std::shared_ptr msg); - - bool MessageConfirmed (uint32_t msgID); + std::shared_ptr WrapSingleMessage (std::shared_ptr msg); + + bool MessageConfirmed (uint32_t msgID); bool CleanupExpiredTags (); // returns true if something left bool CleanupUnconfirmedTags (); // returns true if something has been deleted - private: + private: size_t CreateAESBlock (uint8_t * buf, std::shared_ptr msg); size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr msg, UnconfirmedTags * newTags); @@ -183,32 +184,33 @@ namespace garlic void TagsConfirmed (uint32_t msgID); UnconfirmedTags * GenerateSessionTags (); - - private: - - std::shared_ptr m_Destination; - i2p::crypto::AESKey m_SessionKey; + private: + + std::shared_ptr m_Destination; + + i2p::crypto::AESKey m_SessionKey; std::list m_SessionTags; int m_NumTags; std::map > m_UnconfirmedTagsMsgs; // msgID->tags - i2p::crypto::CBCEncryption m_Encryption; + i2p::crypto::CBCEncryption m_Encryption; + + public: - public: // for HTTP only - size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; - }; - typedef std::shared_ptr ElGamalAESSessionPtr; + size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; + }; + typedef std::shared_ptr ElGamalAESSessionPtr; - class ECIESX25519AEADRatchetSession; - typedef std::shared_ptr ECIESX25519AEADRatchetSessionPtr; + class ECIESX25519AEADRatchetSession; + typedef std::shared_ptr ECIESX25519AEADRatchetSessionPtr; class RatchetTagSet; typedef std::shared_ptr RatchetTagSetPtr; struct ECIESX25519AEADRatchetIndexTagset - { - int index; - RatchetTagSetPtr tagset; + { + int index; + RatchetTagSetPtr tagset; uint64_t creationTime; // seconds since epoch }; @@ -226,12 +228,12 @@ namespace garlic void CleanupExpiredTags (); void RemoveDeliveryStatusSession (uint32_t msgID); std::shared_ptr WrapMessage (std::shared_ptr destination, - std::shared_ptr msg, bool attachLeaseSet = false); + std::shared_ptr msg, bool attachLeaseSet = false); void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); - void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset); + void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void RemoveECIESx25519Session (const uint8_t * staticKey); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); @@ -266,10 +268,10 @@ namespace garlic int m_NumTags; std::mutex m_SessionsMutex; std::unordered_map m_Sessions; - std::unordered_map, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session + std::unordered_map, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session // incoming std::unordered_map, std::hash > > m_Tags; - std::unordered_map m_ECIESx25519Tags; // session tag -> session + std::unordered_map m_ECIESx25519Tags; // session tag -> session // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::unordered_map m_DeliveryStatusSessions; // msgID -> session diff --git a/libi2pd/Gost.h b/libi2pd/Gost.h index 30386104..a4cc9741 100644 --- a/libi2pd/Gost.h +++ b/libi2pd/Gost.h @@ -13,11 +13,11 @@ namespace crypto enum GOSTR3410ParamSet { - eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1 + eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1 // XchA = A, XchB = C - //eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0 - //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 - eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1 + //eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0 + //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 + eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1 eGOSTR3410NumParamSets }; diff --git a/libi2pd/Gzip.cpp b/libi2pd/Gzip.cpp index f36620ae..5709719b 100644 --- a/libi2pd/Gzip.cpp +++ b/libi2pd/Gzip.cpp @@ -40,13 +40,13 @@ namespace data { LogPrint (eLogError, "Gzip: Incorrect length"); return 0; - } + } if (len > outLen) len = outLen; memcpy (out, in + 15, len); return len; } else - { + { if (m_IsDirty) inflateReset (&m_Inflator); m_IsDirty = true; m_Inflator.next_in = const_cast(in); @@ -59,7 +59,7 @@ namespace data // else LogPrint (eLogError, "Gzip: Inflate error ", err); return 0; - } + } } void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os) @@ -126,7 +126,7 @@ namespace data { out[9] = 0xff; // OS is always unknown return outLen - m_Deflator.avail_out; - } + } // else LogPrint (eLogError, "Gzip: Deflate error ", err); return 0; @@ -147,21 +147,21 @@ namespace data auto flush = (it == bufs.back ()) ? Z_FINISH : Z_NO_FLUSH; err = deflate (&m_Deflator, flush); if (err) - { + { if (flush && err == Z_STREAM_END) { out[9] = 0xff; // OS is always unknown return outLen - m_Deflator.avail_out; - } + } break; } offset = outLen - m_Deflator.avail_out; - } + } // else LogPrint (eLogError, "Gzip: Deflate error ", err); return 0; - } - + } + size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen) { static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 }; @@ -176,7 +176,7 @@ namespace data } size_t GzipNoCompression (const std::vector >& bufs, uint8_t * out, size_t outLen) - { + { static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 }; memcpy (out, gzipHeader, 11); uint32_t crc = 0; @@ -186,9 +186,9 @@ namespace data len1 = len; len += it.second; if (outLen < len + 23) return 0; - memcpy (out + 15 + len1, it.first, it.second); + memcpy (out + 15 + len1, it.first, it.second); crc = crc32 (crc, it.first, it.second); - } + } if (len > 0xffff) return 0; htole32buf (out + len + 15, crc); htole32buf (out + len + 19, len); @@ -196,6 +196,6 @@ namespace data htole16buf (out + 13, 0xffff - len); return len + 23; } - + } // data } // i2p diff --git a/libi2pd/Gzip.h b/libi2pd/Gzip.h index 16776d35..6489b79b 100644 --- a/libi2pd/Gzip.h +++ b/libi2pd/Gzip.h @@ -4,9 +4,9 @@ #include #include -namespace i2p +namespace i2p { -namespace data +namespace data { class GzipInflator { @@ -45,7 +45,6 @@ namespace data size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen); // for < 64K size_t GzipNoCompression (const std::vector >& bufs, uint8_t * out, size_t outLen); // for total size < 64K - } // data } // i2p diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 3a139792..170bb864 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -180,9 +180,9 @@ namespace i2p // excluded if (cnt > 512) { - LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup"); + LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup"); cnt = 0; - } + } htobe16buf (buf, cnt); buf += 2; if (cnt > 0) @@ -205,7 +205,7 @@ namespace i2p } std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, - std::vector routers) + std::vector routers) { auto m = NewI2NPShortMessage (); uint8_t * buf = m->GetPayload (); @@ -268,7 +268,7 @@ namespace i2p auto m = NewI2NPShortMessage (); uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32); - payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet + payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); size_t size = DATABASE_STORE_HEADER_SIZE; memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); @@ -278,7 +278,7 @@ namespace i2p return m; } - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken, std::shared_ptr replyTunnel) + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken, std::shared_ptr replyTunnel) { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); @@ -347,11 +347,11 @@ namespace i2p auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, - bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), + bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, - clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, + clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80, - clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40); + clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40); i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0; } @@ -386,7 +386,7 @@ namespace i2p return; } - auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID); + auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID); if (tunnel) { // endpoint of inbound tunnel @@ -414,7 +414,7 @@ namespace i2p transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), eI2NPVariableTunnelBuildReply, buf, len, - bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); } else transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, @@ -440,7 +440,7 @@ namespace i2p transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), eI2NPTunnelBuildReply, buf, len, - bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); } else transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, @@ -592,13 +592,13 @@ namespace i2p switch (typeID) { case eI2NPVariableTunnelBuild: - HandleVariableTunnelBuildMsg (msgID, buf, size); + HandleVariableTunnelBuildMsg (msgID, buf, size); break; case eI2NPVariableTunnelBuildReply: HandleVariableTunnelBuildReplyMsg (msgID, buf, size); break; case eI2NPTunnelBuild: - HandleTunnelBuildMsg (buf, size); + HandleTunnelBuildMsg (buf, size); break; case eI2NPTunnelBuildReply: // TODO: @@ -667,7 +667,7 @@ namespace i2p Flush (); } - void I2NPMessagesHandler::PutNextMessage (std::shared_ptr msg) + void I2NPMessagesHandler::PutNextMessage (std::shared_ptr msg) { if (msg) { diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index c8957b5f..4ecba2eb 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -27,7 +27,7 @@ namespace i2p const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4; // I2NP NTCP2 header - const size_t I2NP_NTCP2_HEADER_SIZE = I2NP_HEADER_EXPIRATION_OFFSET + 4; + const size_t I2NP_NTCP2_HEADER_SIZE = I2NP_HEADER_EXPIRATION_OFFSET + 4; // Tunnel Gateway header const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0; @@ -75,7 +75,7 @@ namespace i2p enum I2NPMessageType { - eI2NPDummyMsg = 0, + eI2NPDummyMsg = 0, eI2NPDatabaseStore = 1, eI2NPDatabaseLookup = 2, eI2NPDatabaseSearchReply = 3, @@ -209,7 +209,7 @@ namespace tunnel SetExpiration (bufbe32toh (ntcp2 + I2NP_HEADER_EXPIRATION_OFFSET)*1000LL); SetSize (len - offset - I2NP_HEADER_SIZE); SetChks (0); - } + } void ToNTCP2 () { diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 0c2dc50e..77a1f7e2 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -356,7 +356,7 @@ namespace data } return nullptr; } - + void IdentityEx::CreateVerifier () const { if (m_Verifier) return; // don't create again @@ -369,15 +369,15 @@ namespace data else { // for P521 - uint8_t * signingKey = new uint8_t[keyLen]; + uint8_t * signingKey = new uint8_t[keyLen]; memcpy (signingKey, m_StandardIdentity.signingKey, 128); - size_t excessLen = keyLen - 128; + size_t excessLen = keyLen - 128; memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types verifier->SetPublicKey (signingKey); - delete[] signingKey; - } - } - UpdateVerifier (verifier); + delete[] signingKey; + } + } + UpdateVerifier (verifier); } void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const @@ -390,7 +390,7 @@ namespace data else del = true; } - if (del) + if (del) delete verifier; } @@ -426,7 +426,7 @@ namespace data LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)keyType); }; return nullptr; - } + } std::shared_ptr IdentityEx::CreateEncryptor (const uint8_t * key) const { @@ -460,9 +460,9 @@ namespace data return *this; } - size_t PrivateKeys::GetFullLen () const - { - size_t ret = m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); + size_t PrivateKeys::GetFullLen () const + { + size_t ret = m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); if (IsOfflineSignature ()) ret += m_OfflineSignature.size () + m_TransientSigningPrivateKeyLen; return ret; @@ -483,7 +483,7 @@ namespace data // check if signing private key is all zeros bool allzeros = true; for (size_t i = 0; i < signingPrivateKeySize; i++) - if (m_SigningPrivateKey[i]) + if (m_SigningPrivateKey[i]) { allzeros = false; break; @@ -500,7 +500,7 @@ namespace data if (keyLen + ret > len) return 0; transientVerifier->SetPublicKey (buf + ret); ret += keyLen; if (m_Public->GetSignatureLen () + ret > len) return 0; - if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret)) + if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret)) { LogPrint (eLogError, "Identity: offline signature verification failed"); return 0; @@ -511,7 +511,7 @@ namespace data size_t offlineInfoLen = buf + ret - offlineInfo; m_OfflineSignature.resize (offlineInfoLen); memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen); - // override signing private key + // override signing private key m_TransientSigningPrivateKeyLen = transientVerifier->GetPrivateKeyLen (); if (m_TransientSigningPrivateKeyLen + ret > len || m_TransientSigningPrivateKeyLen > 128) return 0; memcpy (m_SigningPrivateKey, buf + ret, m_TransientSigningPrivateKeyLen); @@ -586,10 +586,10 @@ namespace data else CreateSigner (m_Public->GetSigningKeyType ()); } - + void PrivateKeys::CreateSigner (SigningKeyType keyType) const { - if (m_Signer) return; + if (m_Signer) return; if (keyType == SIGNING_KEY_TYPE_DSA_SHA1) m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ()) @@ -599,7 +599,7 @@ namespace data // public key is not required auto signer = CreateSigner (keyType, m_SigningPrivateKey); if (signer) m_Signer.reset (signer); - } + } } i2p::crypto::Signer * PrivateKeys::CreateSigner (SigningKeyType keyType, const uint8_t * priv) @@ -630,8 +630,8 @@ namespace data return new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, priv); break; case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: - return new i2p::crypto::RedDSA25519Signer (priv); - break; + return new i2p::crypto::RedDSA25519Signer (priv); + break; default: LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported"); } @@ -719,8 +719,8 @@ namespace data case SIGNING_KEY_TYPE_RSA_SHA512_4096: LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA"); #if (__cplusplus >= 201703L) // C++ 17 or higher - [[fallthrough]]; -#endif + [[fallthrough]]; +#endif // no break here case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub); @@ -733,7 +733,7 @@ namespace data break; case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: i2p::crypto::CreateRedDSA25519RandomKeys (priv, pub); - break; + break; default: LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1"); i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1 @@ -765,7 +765,7 @@ namespace data PrivateKeys PrivateKeys::CreateOfflineKeys (SigningKeyType type, uint32_t expires) const { PrivateKeys keys (*this); - std::unique_ptr verifier (IdentityEx::CreateVerifier (type)); + std::unique_ptr verifier (IdentityEx::CreateVerifier (type)); if (verifier) { size_t pubKeyLen = verifier->GetPublicKeyLen (); @@ -775,7 +775,7 @@ namespace data htobe32buf (keys.m_OfflineSignature.data (), expires); // expires htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key - Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature + Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature // recreate signer keys.m_Signer = nullptr; keys.CreateSigner (type); diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index da14e141..08baba01 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -56,7 +56,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_RATCHET = 4; + const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET = 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 @@ -115,7 +115,7 @@ namespace data void RecalculateIdentHash(uint8_t * buff=nullptr); static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType); - static std::shared_ptr CreateEncryptor (CryptoKeyType keyType, const uint8_t * key); + static std::shared_ptr CreateEncryptor (CryptoKeyType keyType, const uint8_t * key); private: @@ -148,7 +148,7 @@ namespace data const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; }; size_t GetSignatureLen () const; // might not match identity bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; }; - uint8_t * GetPadding(); + uint8_t * GetPadding(); void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); } void Sign (const uint8_t * buf, int len, uint8_t * signature) const; @@ -163,12 +163,12 @@ namespace data static std::shared_ptr CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key); static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL); - static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub); + static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub); static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long static i2p::crypto::Signer * CreateSigner (SigningKeyType keyType, const uint8_t * priv); // offline keys - PrivateKeys CreateOfflineKeys (SigningKeyType type, uint32_t expires) const; + PrivateKeys CreateOfflineKeys (SigningKeyType type, uint32_t expires) const; const std::vector& GetOfflineSignature () const { return m_OfflineSignature; }; private: @@ -204,7 +204,7 @@ namespace data IdentHash CreateRoutingKey (const IdentHash& ident); XORMetric operator^(const IdentHash& key1, const IdentHash& key2); - // destination for delivery instuctions + // destination for delivery instructions class RoutingDestination { public: @@ -235,5 +235,4 @@ namespace data } } - #endif diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 6ce77792..1aa7fa6d 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -12,9 +12,8 @@ namespace i2p { namespace data { - LeaseSet::LeaseSet (bool storeLeases): - m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr), + m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr), m_Buffer (nullptr), m_BufferLen (0) { } @@ -62,7 +61,7 @@ namespace data { if (!m_EncryptionKey) m_EncryptionKey = new uint8_t[256]; memcpy (m_EncryptionKey, m_Buffer + size, 256); - } + } size += 256; // encryption key size += m_Identity->GetSigningPublicKeyLen (); // unused signing key uint8_t num = m_Buffer[size]; @@ -191,10 +190,10 @@ namespace data return m_ExpirationTime - now <= dlt; } - const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const - { - return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold); - } + const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const + { + return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold); + } const std::vector > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const { @@ -249,19 +248,19 @@ namespace data if (len <= m_BufferLen) m_BufferLen = len; else LogPrint (eLogError, "LeaseSet2: actual buffer size ", len , " exceeds full buffer size ", m_BufferLen); - } - + } + LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto): LeaseSet (storeLeases), m_StoreType (storeType), m_EncryptionType (preferredCrypto) - { - SetBuffer (buf, len); + { + SetBuffer (buf, len); if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) ReadFromBufferEncrypted (buf, len, nullptr, nullptr); else ReadFromBuffer (buf, len); } - LeaseSet2::LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, + LeaseSet2::LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret, CryptoKeyType preferredCrypto): LeaseSet (true), m_StoreType (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2), m_EncryptionType (preferredCrypto) { @@ -269,10 +268,10 @@ namespace data } void LeaseSet2::Update (const uint8_t * buf, size_t len, bool verifySignature) - { + { SetBuffer (buf, len); if (GetStoreType () != NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) - ReadFromBuffer (buf, len, false, verifySignature); + ReadFromBuffer (buf, len, false, verifySignature); // TODO: implement encrypted } @@ -281,13 +280,13 @@ namespace data uint64_t expiration; return ExtractPublishedTimestamp (buf, len, expiration) > m_PublishedTimestamp; } - + void LeaseSet2::ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity, bool verifySignature) { // standard LS2 header std::shared_ptr identity; if (readIdentity) - { + { identity = std::make_shared(buf, len); SetIdentity (identity); } @@ -304,7 +303,7 @@ namespace data // transient key m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset); if (!m_TransientVerifier) - { + { LogPrint (eLogError, "LeaseSet2: offline signature failed"); return; } @@ -314,7 +313,7 @@ namespace data { m_IsPublishedEncrypted = true; m_IsPublic = true; - } + } // type specific part size_t s = 0; switch (m_StoreType) @@ -331,11 +330,11 @@ namespace data if (!s) return; offset += s; if (verifySignature || m_TransientVerifier) - { + { // verify signature bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) : - VerifySignature (identity, buf, len, offset); - SetIsValid (verified); + VerifySignature (identity, buf, len, offset); + SetIsValid (verified); } offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen (); SetBufferLen (offset); @@ -346,10 +345,10 @@ namespace data { if (signatureOffset + verifier->GetSignatureLen () > len) return false; // we assume buf inside DatabaseStore message, so buf[-1] is valid memory - // change it for signature verification, and restore back + // change it for signature verification, and restore back uint8_t c = buf[-1]; const_cast(buf)[-1] = m_StoreType; - bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset); + bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset); const_cast(buf)[-1] = c; if (!verified) LogPrint (eLogWarning, "LeaseSet2: verification failed"); @@ -360,7 +359,7 @@ namespace data { size_t offset = 0; // properties - uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2; + uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2; offset += propertiesLen; // skip for now. TODO: implement properties if (offset + 1 >= len) return 0; // key sections @@ -371,7 +370,7 @@ namespace data { uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption key type if (offset + 2 >= len) return 0; - uint16_t encryptionKeyLen = bufbe16toh (buf + offset); offset += 2; + uint16_t encryptionKeyLen = bufbe16toh (buf + offset); offset += 2; if (offset + encryptionKeyLen >= len) return 0; if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only { @@ -384,10 +383,10 @@ namespace data if (keyType == preferredKeyType) preferredKeyFound = true; } } - offset += encryptionKeyLen; - } + offset += encryptionKeyLen; + } // leases - if (offset + 1 >= len) return 0; + if (offset + 1 >= len) return 0; int numLeases = buf[offset]; offset++; auto ts = i2p::util::GetMillisecondsSinceEpoch (); if (IsStoreLeases ()) @@ -413,9 +412,9 @@ namespace data { size_t offset = 0; // properties - uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2; + uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2; offset += propertiesLen; // skip for now. TODO: implement properties - // entries + // entries if (offset + 1 >= len) return 0; int numEntries = buf[offset]; offset++; for (int i = 0; i < numEntries; i++) @@ -423,12 +422,12 @@ namespace data if (offset + 40 >= len) return 0; offset += 32; // hash offset += 3; // flags - offset += 1; // cost + offset += 1; // cost offset += 4; // expires } // revocations if (offset + 1 >= len) return 0; - int numRevocations = buf[offset]; offset++; + int numRevocations = buf[offset]; offset++; for (int i = 0; i < numRevocations; i++) { if (offset + 32 > len) return 0; @@ -446,7 +445,7 @@ namespace data uint16_t blindedKeyType = bufbe16toh (stA1); offset += 2; std::unique_ptr blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType)); if (!blindedVerifier) return; - auto blindedKeyLen = blindedVerifier->GetPublicKeyLen (); + auto blindedKeyLen = blindedVerifier->GetPublicKeyLen (); if (offset + blindedKeyLen >= len) return; const uint8_t * blindedPublicKey = buf + offset; blindedVerifier->SetPublicKey (blindedPublicKey); offset += blindedKeyLen; @@ -461,7 +460,7 @@ namespace data { // transient key m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset); - if (!m_TransientVerifier) + if (!m_TransientVerifier) { LogPrint (eLogError, "LeaseSet2: offline signature failed"); return; @@ -470,16 +469,16 @@ namespace data // outer ciphertext if (offset + 2 > len) return; uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2; - const uint8_t * outerCiphertext = buf + offset; - offset += lenOuterCiphertext; + const uint8_t * outerCiphertext = buf + offset; + offset += lenOuterCiphertext; // verify signature bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) : - VerifySignature (blindedVerifier, buf, len, offset); + VerifySignature (blindedVerifier, buf, len, offset); SetIsValid (verified); // handle ciphertext if (verified && key && lenOuterCiphertext >= 32) { - SetIsValid (false); // we must verify it again in Layer 2 + SetIsValid (false); // we must verify it again in Layer 2 if (blindedKeyType == key->GetBlindedSigType ()) { // verify blinding @@ -491,13 +490,13 @@ namespace data { LogPrint (eLogError, "LeaseSet2: blinded public key doesn't match"); return; - } - } + } + } else { LogPrint (eLogError, "LeaseSet2: Unexpected blinded key type ", blindedKeyType, " instead ", key->GetBlindedSigType ()); return; - } + } // outer key // outerInput = subcredential || publishedTimestamp uint8_t subcredential[36]; @@ -518,10 +517,10 @@ namespace data // innerSalt = innerCiphertext[0:32] // keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44) uint8_t innerInput[68]; - size_t authDataLen = ExtractClientAuthData (outerPlainText.data (), lenOuterPlaintext, secret, subcredential, innerInput); + size_t authDataLen = ExtractClientAuthData (outerPlainText.data (), lenOuterPlaintext, secret, subcredential, innerInput); if (authDataLen > 0) { - memcpy (innerInput + 32, subcredential, 36); + memcpy (innerInput + 32, subcredential, 36); i2p::crypto::HKDF (outerPlainText.data () + 1 + authDataLen, innerInput, 68, "ELS2_L2K", keys); } else @@ -537,20 +536,20 @@ namespace data if (innerPlainText[0] == NETDB_STORE_TYPE_STANDARD_LEASESET2 || innerPlainText[0] == NETDB_STORE_TYPE_META_LEASESET2) { // override store type and buffer - m_StoreType = innerPlainText[0]; + m_StoreType = innerPlainText[0]; SetBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1); // parse and verify Layer 2 ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1); } else LogPrint (eLogError, "LeaseSet2: unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet"); - } + } else { // we set actual length of encrypted buffer offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : blindedVerifier->GetSignatureLen (); SetBufferLen (offset); - } + } } // helper for ExtractClientAuthData @@ -563,12 +562,12 @@ namespace data { // clientKey_i = okm[0:31] // clientIV_i = okm[32:43] - i2p::crypto::ChaCha20 (authClients + i*40 + 8, 32, okm, okm + 32, authCookie); // clientCookie_i + i2p::crypto::ChaCha20 (authClients + i*40 + 8, 32, okm, okm + 32, authCookie); // clientCookie_i return true; - } + } } - return false; - } + return false; + } size_t LeaseSet2::ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const { @@ -581,7 +580,7 @@ namespace data const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients - if (offset > len) + if (offset > len) { LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data"); return 0; @@ -595,19 +594,19 @@ namespace data memcpy (authInput + 32, ck.GetPublicKey (), 32); // cpk_i memcpy (authInput + 64, subcredential, 36); uint8_t okm[64]; // 52 actual data - i2p::crypto::HKDF (ephemeralPublicKey, authInput, 100, "ELS2_XCA", okm); + i2p::crypto::HKDF (ephemeralPublicKey, authInput, 100, "ELS2_XCA", okm); if (!GetAuthCookie (authClients, numClients, okm, authCookie)) - LogPrint (eLogError, "LeaseSet2: Client cookie DH not found"); + LogPrint (eLogError, "LeaseSet2: Client cookie DH not found"); } else - LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: csk_i is not provided"); + LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: csk_i is not provided"); } else if (flag & 0x02) // PSK, bit 1 is set to 1 { const uint8_t * authSalt = buf + offset; offset += 32; // authSalt uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients - if (offset > len) + if (offset > len) { LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data"); return 0; @@ -619,7 +618,7 @@ namespace data memcpy (authInput, secret, 32); memcpy (authInput + 32, subcredential, 36); uint8_t okm[64]; // 52 actual data - i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm); + i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm); if (!GetAuthCookie (authClients, numClients, okm, authCookie)) LogPrint (eLogError, "LeaseSet2: Client cookie PSK not found"); } @@ -627,7 +626,7 @@ namespace data LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided"); } else - LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag); + LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag); } return offset - 1; } @@ -636,7 +635,7 @@ namespace data { auto encryptor = m_Encryptor; // TODO: atomic if (encryptor) - encryptor->Encrypt (data, encrypted, ctx, true); + encryptor->Encrypt (data, encrypted, ctx, true); } uint64_t LeaseSet2::ExtractExpirationTimestamp (const uint8_t * buf, size_t len) const @@ -648,7 +647,7 @@ namespace data uint64_t LeaseSet2::ExtractPublishedTimestamp (const uint8_t * buf, size_t len, uint64_t& expiration) const { - if (len < 8) return 0; + if (len < 8) return 0; if (m_StoreType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { // encrypted LS2 @@ -656,11 +655,11 @@ namespace data uint16_t blindedKeyType = bufbe16toh (buf + offset); offset += 2; std::unique_ptr blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType)); if (!blindedVerifier) return 0 ; - auto blindedKeyLen = blindedVerifier->GetPublicKeyLen (); + auto blindedKeyLen = blindedVerifier->GetPublicKeyLen (); if (offset + blindedKeyLen + 6 >= len) return 0; offset += blindedKeyLen; - uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; - uint16_t expires = bufbe16toh (buf + offset); offset += 2; + uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; + uint16_t expires = bufbe16toh (buf + offset); offset += 2; expiration = (timestamp + expires)* 1000LL; return timestamp; } @@ -670,13 +669,13 @@ namespace data if (!identity) return 0; size_t offset = identity->GetFullLen (); if (offset + 6 >= len) return 0; - uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; - uint16_t expires = bufbe16toh (buf + offset); offset += 2; + uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; + uint16_t expires = bufbe16toh (buf + offset); offset += 2; expiration = (timestamp + expires)* 1000LL; return timestamp; } - } - + } + LocalLeaseSet::LocalLeaseSet (std::shared_ptr identity, const uint8_t * encryptionPublicKey, std::vector > tunnels): m_ExpirationTime (0), m_Identity (identity) { @@ -770,36 +769,35 @@ namespace data return ident.Verify(ptr, leases - ptr, leases); } - LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, - const KeySections& encryptionKeys, - std::vector > tunnels, + LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, + const KeySections& encryptionKeys, std::vector > tunnels, bool isPublic, bool isPublishedEncrypted): LocalLeaseSet (keys.GetPublic (), nullptr, 0) { auto identity = keys.GetPublic (); - // assume standard LS2 + // assume standard LS2 int num = tunnels.size (); if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; size_t keySectionsLen = 0; for (const auto& it: encryptionKeys) - keySectionsLen += 2/*key type*/ + 2/*key len*/ + it.keyLen/*key*/; + keySectionsLen += 2/*key type*/ + 2/*key len*/ + it.keyLen/*key*/; m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ + 1/*num keys*/ + keySectionsLen + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen (); uint16_t flags = 0; - if (keys.IsOfflineSignature ()) + if (keys.IsOfflineSignature ()) { flags |= LEASESET2_FLAG_OFFLINE_KEYS; - m_BufferLen += keys.GetOfflineSignature ().size (); + m_BufferLen += keys.GetOfflineSignature ().size (); } - if (isPublishedEncrypted) + if (isPublishedEncrypted) { flags |= LEASESET2_FLAG_PUBLISHED_ENCRYPTED; - isPublic = true; + isPublic = true; } if (!isPublic) flags |= LEASESET2_FLAG_UNPUBLISHED_LEASESET; m_Buffer = new uint8_t[m_BufferLen + 1]; - m_Buffer[0] = storeType; + m_Buffer[0] = storeType; // LS2 header auto offset = identity->ToBuffer (m_Buffer + 1, m_BufferLen) + 1; auto timestamp = i2p::util::GetSecondsSinceEpoch (); @@ -814,14 +812,14 @@ namespace data offset += offlineSignature.size (); } htobe16buf (m_Buffer + offset, 0); offset += 2; // properties len - // keys + // keys m_Buffer[offset] = encryptionKeys.size (); offset++; // 1 key for (const auto& it: encryptionKeys) - { - htobe16buf (m_Buffer + offset, it.keyType); offset += 2; // key type - htobe16buf (m_Buffer + offset, it.keyLen); offset += 2; // key len + { + htobe16buf (m_Buffer + offset, it.keyType); offset += 2; // key type + htobe16buf (m_Buffer + offset, it.keyLen); offset += 2; // key len memcpy (m_Buffer + offset, it.encryptionPublicKey, it.keyLen); offset += it.keyLen; // key - } + } // leases uint32_t expirationTime = 0; // in seconds m_Buffer[offset] = num; offset++; // num leases @@ -835,11 +833,11 @@ namespace data if (ts > expirationTime) expirationTime = ts; htobe32buf (m_Buffer + offset, ts); offset += 4; // end date - } + } // update expiration - SetExpirationTime (expirationTime*1000LL); + SetExpirationTime (expirationTime*1000LL); auto expires = expirationTime - timestamp; - htobe16buf (expiresBuf, expires > 0 ? expires : 0); + htobe16buf (expiresBuf, expires > 0 ? expires : 0); // sign keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type } @@ -853,7 +851,7 @@ namespace data m_Buffer[0] = storeType; } - LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr ls, const i2p::data::PrivateKeys& keys, + LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr ls, const i2p::data::PrivateKeys& keys, int authType, std::shared_ptr > authKeys): LocalLeaseSet2 (ls->GetIdentity ()), m_InnerLeaseSet (ls) { @@ -863,16 +861,16 @@ namespace data { if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_DH) layer1Flags |= 0x01; // DH, authentication scheme 0, auth bit 1 else if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_PSK) layer1Flags |= 0x03; // PSK, authentication scheme 1, auth bit 1 - if (layer1Flags) + if (layer1Flags) lenOuterPlaintext += 32 + 2 + authKeys->size ()*40; // auth data len - } + } size_t lenOuterCiphertext = lenOuterPlaintext + 32; - - m_BufferLen = 2/*blinded sig type*/ + 32/*blinded pub key*/ + 4/*published*/ + 2/*expires*/ + 2/*flags*/ + 2/*lenOuterCiphertext*/ + lenOuterCiphertext + 64/*signature*/; - m_Buffer = new uint8_t[m_BufferLen + 1]; + + m_BufferLen = 2/*blinded sig type*/ + 32/*blinded pub key*/ + 4/*published*/ + 2/*expires*/ + 2/*flags*/ + 2/*lenOuterCiphertext*/ + lenOuterCiphertext + 64/*signature*/; + m_Buffer = new uint8_t[m_BufferLen + 1]; m_Buffer[0] = NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; BlindedPublicKey blindedKey (ls->GetIdentity ()); - auto timestamp = i2p::util::GetSecondsSinceEpoch (); + auto timestamp = i2p::util::GetSecondsSinceEpoch (); char date[9]; i2p::util::GetDateString (timestamp, date); uint8_t blindedPriv[64], blindedPub[128]; // 64 and 128 max @@ -883,25 +881,25 @@ namespace data memcpy (m_Buffer + offset, blindedPub, publicKeyLen); offset += publicKeyLen; // Blinded Public Key htobe32buf (m_Buffer + offset, timestamp); offset += 4; // published timestamp (seconds) auto nextMidnight = (timestamp/86400LL + 1)*86400LL; // 86400 = 24*3600 seconds - auto expirationTime = ls->GetExpirationTime ()/1000LL; + auto expirationTime = ls->GetExpirationTime ()/1000LL; if (expirationTime > nextMidnight) expirationTime = nextMidnight; SetExpirationTime (expirationTime*1000LL); htobe16buf (m_Buffer + offset, expirationTime > timestamp ? expirationTime - timestamp : 0); offset += 2; // expires uint16_t flags = 0; - htobe16buf (m_Buffer + offset, flags); offset += 2; // flags + htobe16buf (m_Buffer + offset, flags); offset += 2; // flags htobe16buf (m_Buffer + offset, lenOuterCiphertext); offset += 2; // lenOuterCiphertext // outerChipherText - // Layer 1 + // Layer 1 uint8_t subcredential[36]; blindedKey.GetSubcredential (blindedPub, 32, subcredential); htobe32buf (subcredential + 32, timestamp); // outerInput = subcredential || publishedTimestamp // keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44) uint8_t keys1[64]; // 44 bytes actual data - RAND_bytes (m_Buffer + offset, 32); // outerSalt = CSRNG(32) + RAND_bytes (m_Buffer + offset, 32); // outerSalt = CSRNG(32) i2p::crypto::HKDF (m_Buffer + offset, subcredential, 36, "ELS2_L1K", keys1); offset += 32; // outerSalt - uint8_t * outerPlainText = m_Buffer + offset; - m_Buffer[offset] = layer1Flags; offset++; // layer 1 flags + uint8_t * outerPlainText = m_Buffer + offset; + m_Buffer[offset] = layer1Flags; offset++; // layer 1 flags // auth data uint8_t innerInput[68]; // authCookie || subcredential || publishedTimestamp if (layer1Flags) @@ -909,20 +907,20 @@ namespace data RAND_bytes (innerInput, 32); // authCookie CreateClientAuthData (subcredential, authType, authKeys, innerInput, m_Buffer + offset); offset += 32 + 2 + authKeys->size ()*40; // auth clients - } + } // Layer 2 // keys = HKDF(outerSalt, outerInput, "ELS2_L2K", 44) uint8_t keys2[64]; // 44 bytes actual data - RAND_bytes (m_Buffer + offset, 32); // innerSalt = CSRNG(32) + RAND_bytes (m_Buffer + offset, 32); // innerSalt = CSRNG(32) if (layer1Flags) { memcpy (innerInput + 32, subcredential, 36); // + subcredential || publishedTimestamp - i2p::crypto::HKDF (m_Buffer + offset, innerInput, 68, "ELS2_L2K", keys2); + i2p::crypto::HKDF (m_Buffer + offset, innerInput, 68, "ELS2_L2K", keys2); } else i2p::crypto::HKDF (m_Buffer + offset, subcredential, 36, "ELS2_L2K", keys2); // no authCookie - offset += 32; // innerSalt - m_Buffer[offset] = ls->GetStoreType (); + offset += 32; // innerSalt + m_Buffer[offset] = ls->GetStoreType (); memcpy (m_Buffer + offset + 1, ls->GetBuffer (), ls->GetBufferLen ()); i2p::crypto::ChaCha20 (m_Buffer + offset, lenInnerPlaintext, keys2, keys2 + 32, m_Buffer + offset); // encrypt Layer 2 offset += lenInnerPlaintext; @@ -930,14 +928,14 @@ namespace data // signature blindedSigner->Sign (m_Buffer, offset, m_Buffer + offset); // store hash - m_StoreHash = blindedKey.GetStoreHash (date); + m_StoreHash = blindedKey.GetStoreHash (date); } LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr identity, const uint8_t * buf, size_t len): - LocalLeaseSet2 (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2, identity, buf, len) + LocalLeaseSet2 (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2, identity, buf, len) { - // fill inner LeaseSet2 - auto blindedKey = std::make_shared(identity); + // fill inner LeaseSet2 + auto blindedKey = std::make_shared(identity); i2p::data::LeaseSet2 ls (buf, len, blindedKey); // inner layer if (ls.IsValid ()) { @@ -945,10 +943,10 @@ namespace data m_StoreHash = blindedKey->GetStoreHash (); } else - LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer"); + LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer"); } - void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr > authKeys, const uint8_t * authCookie, uint8_t * authData) const + void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr > authKeys, const uint8_t * authCookie, uint8_t * authData) const { if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_DH) { @@ -963,9 +961,9 @@ namespace data ek.Agree (it, authInput); // sharedSecret = DH(esk, cpk_i) memcpy (authInput + 32, it, 32); uint8_t okm[64]; // 52 actual data - i2p::crypto::HKDF (ek.GetPublicKey (), authInput, 100, "ELS2_XCA", okm); + i2p::crypto::HKDF (ek.GetPublicKey (), authInput, 100, "ELS2_XCA", okm); memcpy (authData, okm + 44, 8); authData += 8; // clientID_i - i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i + i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i } } else // assume PSK @@ -980,10 +978,10 @@ namespace data { memcpy (authInput, it, 32); uint8_t okm[64]; // 52 actual data - i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm); + i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm); memcpy (authData, okm + 44, 8); authData += 8; // clientID_i - i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i - } + i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i + } } } } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 4d084da3..479594e1 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -48,11 +48,11 @@ namespace data }; }; - typedef std::function LeaseInspectFunc; + typedef std::function LeaseInspectFunc; const size_t MAX_LS_BUFFER_SIZE = 3072; const size_t LEASE_SIZE = 44; // 32 + 4 + 8 - const size_t LEASE2_SIZE = 40; // 32 + 4 + 4 + const size_t LEASE2_SIZE = 40; // 32 + 4 + 4 const uint8_t MAX_NUM_LEASES = 16; const uint8_t NETDB_STORE_TYPE_LEASESET = 1; @@ -70,7 +70,7 @@ namespace data size_t GetBufferLen () const { return m_BufferLen; }; bool IsValid () const { return m_IsValid; }; const std::vector > GetNonExpiredLeases (bool withThreshold = true) const; - const std::vector > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const; + const std::vector > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const; bool HasExpiredLeases () const; bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; @@ -80,7 +80,7 @@ namespace data { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; virtual uint8_t GetStoreType () const { return NETDB_STORE_TYPE_LEASESET; }; virtual uint32_t GetPublishedTimestamp () const { return 0; }; // should be set for LeaseSet2 only - virtual std::shared_ptr GetTransientVerifier () const { return nullptr; }; + virtual std::shared_ptr GetTransientVerifier () const { return nullptr; }; virtual bool IsPublishedEncrypted () const { return false; }; // implements RoutingDestination @@ -97,7 +97,7 @@ namespace data // called from LeaseSet2 LeaseSet (bool storeLeases); void SetBuffer (const uint8_t * buf, size_t len); - void SetBufferLen (size_t len); + void SetBufferLen (size_t len); void SetIdentity (std::shared_ptr identity) { m_Identity = identity; }; void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; }; void SetIsValid (bool isValid) { m_IsValid = isValid; }; @@ -130,7 +130,7 @@ namespace data const uint8_t NETDB_STORE_TYPE_META_LEASESET2 = 7; const uint16_t LEASESET2_FLAG_OFFLINE_KEYS = 0x0001; - const uint16_t LEASESET2_FLAG_UNPUBLISHED_LEASESET = 0x0002; + const uint16_t LEASESET2_FLAG_UNPUBLISHED_LEASESET = 0x0002; const uint16_t LEASESET2_FLAG_PUBLISHED_ENCRYPTED = 0x0004; class LeaseSet2: public LeaseSet @@ -167,7 +167,7 @@ namespace data private: - uint8_t m_StoreType; + uint8_t m_StoreType; uint32_t m_PublishedTimestamp = 0; bool m_IsPublic = true, m_IsPublishedEncrypted = false; std::shared_ptr m_TransientVerifier; @@ -175,7 +175,7 @@ namespace data std::shared_ptr m_Encryptor; // for standardLS2 }; - // also called from Streaming.cpp + // also called from Streaming.cpp template std::shared_ptr ProcessOfflineSignature (const Verifier& verifier, const uint8_t * buf, size_t len, size_t& offset) { @@ -191,7 +191,7 @@ namespace data transientVerifier->SetPublicKey (buf + offset); offset += keyLen; if (offset + verifier->GetSignatureLen () >= len) return nullptr; if (!verifier->Verify (signedData, keyLen + 6, buf + offset)) return nullptr; - offset += verifier->GetSignatureLen (); + offset += verifier->GetSignatureLen (); return transientVerifier; } @@ -238,17 +238,18 @@ namespace data { uint16_t keyType, keyLen; const uint8_t * encryptionPublicKey; - }; + }; typedef std::vector KeySections; - - LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, - const KeySections& encryptionKeys, - std::vector > tunnels, + + LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, + const KeySections& encryptionKeys, + std::vector > tunnels, bool isPublic, bool isPublishedEncrypted = false); - LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, const uint8_t * buf, size_t len); // from I2CP - + + LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, const uint8_t * buf, size_t len); // from I2CP + virtual ~LocalLeaseSet2 () { delete[] m_Buffer; }; - + uint8_t * GetBuffer () const { return m_Buffer + 1; }; size_t GetBufferLen () const { return m_BufferLen; }; @@ -269,13 +270,13 @@ namespace data const int ENCRYPTED_LEASESET_AUTH_TYPE_DH = 1; const int ENCRYPTED_LEASESET_AUTH_TYPE_PSK = 2; - typedef i2p::data::Tag<32> AuthPublicKey; + typedef i2p::data::Tag<32> AuthPublicKey; class LocalEncryptedLeaseSet2: public LocalLeaseSet2 { public: - LocalEncryptedLeaseSet2 (std::shared_ptr ls, const i2p::data::PrivateKeys& keys, int authType = ENCRYPTED_LEASESET_AUTH_TYPE_NONE, std::shared_ptr > authKeys = nullptr); + LocalEncryptedLeaseSet2 (std::shared_ptr ls, const i2p::data::PrivateKeys& keys, int authType = ENCRYPTED_LEASESET_AUTH_TYPE_NONE, std::shared_ptr > authKeys = nullptr); LocalEncryptedLeaseSet2 (std::shared_ptr identity, const uint8_t * buf, size_t len); // from I2CP diff --git a/libi2pd/LittleBigEndian.h b/libi2pd/LittleBigEndian.h index 69f10ee9..55039fb6 100644 --- a/libi2pd/LittleBigEndian.h +++ b/libi2pd/LittleBigEndian.h @@ -29,35 +29,35 @@ struct BigEndian; template struct LittleEndian { - union - { - unsigned char bytes[sizeof(T)]; - T raw_value; - }; - - LittleEndian(T t = T()) - { - operator =(t); - } - - LittleEndian(const LittleEndian & t) - { - raw_value = t.raw_value; - } - - LittleEndian(const BigEndian & t) - { - for (unsigned i = 0; i < sizeof(T); i++) - bytes[i] = t.bytes[sizeof(T)-1-i]; - } - - operator const T() const - { - T t = T(); - for (unsigned i = 0; i < sizeof(T); i++) - t |= T(bytes[i]) << (i << 3); - return t; - } + union + { + unsigned char bytes[sizeof(T)]; + T raw_value; + }; + + LittleEndian(T t = T()) + { + operator =(t); + } + + LittleEndian(const LittleEndian & t) + { + raw_value = t.raw_value; + } + + LittleEndian(const BigEndian & t) + { + for (unsigned i = 0; i < sizeof(T); i++) + bytes[i] = t.bytes[sizeof(T)-1-i]; + } + + operator const T() const + { + T t = T(); + for (unsigned i = 0; i < sizeof(T); i++) + t |= T(bytes[i]) << (i << 3); + return t; + } const T operator = (const T t) { @@ -66,68 +66,68 @@ struct LittleEndian return t; } - // operators - - const T operator += (const T t) - { - return (*this = *this + t); - } - - const T operator -= (const T t) - { - return (*this = *this - t); - } - - const T operator *= (const T t) - { - return (*this = *this * t); - } - - const T operator /= (const T t) - { - return (*this = *this / t); - } - - const T operator %= (const T t) - { - return (*this = *this % t); - } - - LittleEndian operator ++ (int) - { - LittleEndian tmp(*this); - operator ++ (); - return tmp; - } - - LittleEndian & operator ++ () - { - for (unsigned i = 0; i < sizeof(T); i++) - { - ++bytes[i]; - if (bytes[i] != 0) - break; - } - return (*this); - } - - LittleEndian operator -- (int) - { - LittleEndian tmp(*this); - operator -- (); - return tmp; - } - - LittleEndian & operator -- () - { - for (unsigned i = 0; i < sizeof(T); i++) - { - --bytes[i]; - if (bytes[i] != (T)(-1)) - break; - } - return (*this); - } + // operators + + const T operator += (const T t) + { + return (*this = *this + t); + } + + const T operator -= (const T t) + { + return (*this = *this - t); + } + + const T operator *= (const T t) + { + return (*this = *this * t); + } + + const T operator /= (const T t) + { + return (*this = *this / t); + } + + const T operator %= (const T t) + { + return (*this = *this % t); + } + + LittleEndian operator ++ (int) + { + LittleEndian tmp(*this); + operator ++ (); + return tmp; + } + + LittleEndian & operator ++ () + { + for (unsigned i = 0; i < sizeof(T); i++) + { + ++bytes[i]; + if (bytes[i] != 0) + break; + } + return (*this); + } + + LittleEndian operator -- (int) + { + LittleEndian tmp(*this); + operator -- (); + return tmp; + } + + LittleEndian & operator -- () + { + for (unsigned i = 0; i < sizeof(T); i++) + { + --bytes[i]; + if (bytes[i] != (T)(-1)) + break; + } + return (*this); + } }; #pragma pack(pop) @@ -137,105 +137,105 @@ struct LittleEndian template struct BigEndian { - union - { - unsigned char bytes[sizeof(T)]; - T raw_value; - }; - - BigEndian(T t = T()) - { - operator =(t); - } - - BigEndian(const BigEndian & t) - { - raw_value = t.raw_value; - } - - BigEndian(const LittleEndian & t) - { - for (unsigned i = 0; i < sizeof(T); i++) - bytes[i] = t.bytes[sizeof(T)-1-i]; - } - - operator const T() const - { - T t = T(); - for (unsigned i = 0; i < sizeof(T); i++) - t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3); - return t; - } - - const T operator = (const T t) - { - for (unsigned i = 0; i < sizeof(T); i++) - bytes[sizeof(T) - 1 - i] = t >> (i << 3); - return t; - } - - // operators - - const T operator += (const T t) - { - return (*this = *this + t); - } - - const T operator -= (const T t) - { - return (*this = *this - t); - } - - const T operator *= (const T t) - { - return (*this = *this * t); - } - - const T operator /= (const T t) - { - return (*this = *this / t); - } - - const T operator %= (const T t) - { - return (*this = *this % t); - } - - BigEndian operator ++ (int) - { - BigEndian tmp(*this); - operator ++ (); - return tmp; - } - - BigEndian & operator ++ () - { - for (unsigned i = 0; i < sizeof(T); i++) - { - ++bytes[sizeof(T) - 1 - i]; - if (bytes[sizeof(T) - 1 - i] != 0) - break; - } - return (*this); - } - - BigEndian operator -- (int) - { - BigEndian tmp(*this); - operator -- (); - return tmp; - } - - BigEndian & operator -- () - { - for (unsigned i = 0; i < sizeof(T); i++) - { - --bytes[sizeof(T) - 1 - i]; - if (bytes[sizeof(T) - 1 - i] != (T)(-1)) - break; - } - return (*this); - } + union + { + unsigned char bytes[sizeof(T)]; + T raw_value; + }; + + BigEndian(T t = T()) + { + operator =(t); + } + + BigEndian(const BigEndian & t) + { + raw_value = t.raw_value; + } + + BigEndian(const LittleEndian & t) + { + for (unsigned i = 0; i < sizeof(T); i++) + bytes[i] = t.bytes[sizeof(T)-1-i]; + } + + operator const T() const + { + T t = T(); + for (unsigned i = 0; i < sizeof(T); i++) + t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3); + return t; + } + + const T operator = (const T t) + { + for (unsigned i = 0; i < sizeof(T); i++) + bytes[sizeof(T) - 1 - i] = t >> (i << 3); + return t; + } + + // operators + + const T operator += (const T t) + { + return (*this = *this + t); + } + + const T operator -= (const T t) + { + return (*this = *this - t); + } + + const T operator *= (const T t) + { + return (*this = *this * t); + } + + const T operator /= (const T t) + { + return (*this = *this / t); + } + + const T operator %= (const T t) + { + return (*this = *this % t); + } + + BigEndian operator ++ (int) + { + BigEndian tmp(*this); + operator ++ (); + return tmp; + } + + BigEndian & operator ++ () + { + for (unsigned i = 0; i < sizeof(T); i++) + { + ++bytes[sizeof(T) - 1 - i]; + if (bytes[sizeof(T) - 1 - i] != 0) + break; + } + return (*this); + } + + BigEndian operator -- (int) + { + BigEndian tmp(*this); + operator -- (); + return tmp; + } + + BigEndian & operator -- () + { + for (unsigned i = 0; i < sizeof(T); i++) + { + --bytes[sizeof(T) - 1 - i]; + if (bytes[sizeof(T) - 1 - i] != (T)(-1)) + break; + } + return (*this); + } }; #pragma pack(pop) diff --git a/libi2pd/Log.cpp b/libi2pd/Log.cpp index 65602674..6f2eb5bd 100644 --- a/libi2pd/Log.cpp +++ b/libi2pd/Log.cpp @@ -110,18 +110,18 @@ namespace log { } } - std::string str_tolower(std::string s) { - std::transform(s.begin(), s.end(), s.begin(), - // static_cast(std::tolower) // wrong - // [](int c){ return std::tolower(c); } // wrong - // [](char c){ return std::tolower(c); } // wrong - [](unsigned char c){ return std::tolower(c); } // correct - ); - return s; - } - - void Log::SetLogLevel (const std::string& level_) { - std::string level=str_tolower(level_); + std::string str_tolower(std::string s) { + std::transform(s.begin(), s.end(), s.begin(), + // static_cast(std::tolower) // wrong + // [](int c){ return std::tolower(c); } // wrong + // [](char c){ return std::tolower(c); } // wrong + [](unsigned char c){ return std::tolower(c); } // correct + ); + return s; + } + + void Log::SetLogLevel (const std::string& level_) { + std::string level=str_tolower(level_); if (level == "none") { m_MinLevel = eLogNone; } else if (level == "error") { m_MinLevel = eLogError; } else if (level == "warn") { m_MinLevel = eLogWarning; } @@ -240,7 +240,7 @@ namespace log { static ThrowFunction g_ThrowFunction; ThrowFunction GetThrowFunction () { return g_ThrowFunction; } void SetThrowFunction (ThrowFunction f) { g_ThrowFunction = f; } - + } // log } // i2p diff --git a/libi2pd/Log.h b/libi2pd/Log.h index 556654e2..fbd122a8 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -155,9 +155,9 @@ namespace log { typedef std::function ThrowFunction; ThrowFunction GetThrowFunction (); - void SetThrowFunction (ThrowFunction f); + void SetThrowFunction (ThrowFunction f); } // log -} +} // i2p /** internal usage only -- folding args array to single string */ template @@ -203,7 +203,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept } /** - * @brief Throw fatal error message with the list of arguments + * @brief Throw fatal error message with the list of arguments * @param args Array of message parts */ template diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index e52f0111..eec3a5a5 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -114,7 +114,7 @@ namespace transport void NTCP2Establisher::KDF2Bob () { - KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ()); + KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ()); } void NTCP2Establisher::KDF3Alice () @@ -707,7 +707,7 @@ namespace transport auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ()); if (m_Server.AddNTCP2Session (shared_from_this (), true)) - { + { Established (); ReceiveLength (); } @@ -1200,7 +1200,7 @@ namespace transport continue; } - LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port); + LogPrint (eLogInfo, "NTCP2: Start listening v4 TCP port ", address->port); auto conn = std::make_shared(*this); m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); } @@ -1218,8 +1218,8 @@ namespace transport LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port); auto conn = std::make_shared (*this); m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); - } - catch ( std::exception & ex ) + } + catch ( std::exception & ex ) { LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what()); ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ()); @@ -1485,7 +1485,7 @@ namespace transport } }); auto readbuff = std::make_shared >(2); - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2), + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2), [this, readbuff, timer, conn, host, port, addrtype](const boost::system::error_code & ec, std::size_t transferred) { if(ec) @@ -1531,8 +1531,8 @@ namespace transport std::ostream out(&writebuff); out << req.to_string(); - boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), - [](const boost::system::error_code & ec, std::size_t transferred) + boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), + [](const boost::system::error_code & ec, std::size_t transferred) { (void) transferred; if(ec) @@ -1540,8 +1540,8 @@ namespace transport }); boost::asio::streambuf * readbuff = new boost::asio::streambuf; - boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", - [this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred) + boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", + [this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred) { if(ec) { diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 10170fda..8b8c6acb 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -126,7 +126,6 @@ namespace transport { public: - NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter = nullptr); ~NTCP2Session (); void Terminate (); diff --git a/libi2pd/NTCPSession.cpp b/libi2pd/NTCPSession.cpp index 4ab3c5d0..56c69e05 100644 --- a/libi2pd/NTCPSession.cpp +++ b/libi2pd/NTCPSession.cpp @@ -26,7 +26,7 @@ namespace transport { std::shared_ptr session; }; - + NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr in_RemoteRouter): TransportSession (in_RemoteRouter, NTCP_ESTABLISH_TIMEOUT), m_Server (server), m_Socket (m_Server.GetService ()), @@ -468,7 +468,7 @@ namespace transport LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock"); if (ecode != boost::asio::error::operation_aborted) { - // this router doesn't like us + // this router doesn't like us i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); Terminate (); } @@ -736,13 +736,11 @@ namespace transport } } - void NTCPSession::SendTimeSyncMessage () { Send (nullptr); } - void NTCPSession::SendI2NPMessages (const std::vector >& msgs) { m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessages, shared_from_this (), msgs)); @@ -821,8 +819,8 @@ namespace transport { m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port)); LogPrint (eLogInfo, "NTCP: Start listening v6 TCP port ", address->port); - } - catch ( std::exception & ex ) + } + catch ( std::exception & ex ) { /** fail to bind ip4 */ LogPrint(eLogError, "NTCP: Failed to bind to v4 port ", address->port, ": ", ex.what()); @@ -848,8 +846,8 @@ namespace transport LogPrint (eLogInfo, "NTCP: Start listening v6 TCP port ", address->port); auto conn = std::make_shared (*this); m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6, this, conn, std::placeholders::_1)); - } - catch ( std::exception & ex ) + } + catch ( std::exception & ex ) { LogPrint(eLogError, "NTCP: failed to bind to v6 port ", address->port, ": ", ex.what()); ThrowFatal (eLogError, "Unable to start IPv6 NTCP transport at port ", address->port, ": ", ex.what ()); @@ -904,7 +902,6 @@ namespace transport } } - void NTCPServer::Run () { while (m_IsRunning) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 86bf160e..30916f1a 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -216,10 +216,10 @@ namespace data LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); std::unique_lock l(m_FloodfillsMutex); if (wasFloodfill) - m_Floodfills.remove (r); - else + m_Floodfills.remove (r); + else m_Floodfills.push_back (r); - } + } } else { @@ -390,7 +390,7 @@ namespace data } } - m_Reseeder->Bootstrap (); + m_Reseeder->Bootstrap (); } void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills) @@ -532,12 +532,12 @@ namespace data auto total = m_RouterInfos.size (); uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); - auto uptime = i2p::context.GetUptime (); + auto uptime = i2p::context.GetUptime (); // routers don't expire if less than 90 or uptime is less than 1 hour bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes if (checkForExpiration && uptime > 3600) // 1 hour expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : - NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; + NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; for (auto& it: m_RouterInfos) { @@ -555,7 +555,7 @@ namespace data // find & mark expired routers if (it.second->UsesIntroducer ()) { - if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) + if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) // RouterInfo expires after 1 hour if uses introducer it.second->SetUnreachable (true); } @@ -873,7 +873,7 @@ namespace data std::shared_ptr replyMsg; if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) { - LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded"); + LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded"); std::set excludedRouters; for (int i = 0; i < numExcluded; i++) { @@ -894,7 +894,7 @@ namespace data } else { - if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP || + if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP) { auto router = FindRouter (ident); @@ -907,7 +907,7 @@ namespace data } } - if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP || + if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) { auto leaseSet = FindLeaseSet (ident); @@ -957,12 +957,12 @@ namespace data replyMsg = i2p::garlic::WrapECIESX25519AEADRatchetMessage (replyMsg, sessionKey, tag); } else - { + { const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag i2p::garlic::ElGamalAESSession garlic (sessionKey, sessionTag); replyMsg = garlic.WrapSingleMessage (replyMsg); - } - if (!replyMsg) + } + if (!replyMsg) LogPrint (eLogError, "NetDb: failed to wrap message"); } else @@ -1103,7 +1103,7 @@ namespace data { return !router->IsHidden () && router->IsSSUV6 (); }); - } + } std::shared_ptr NetDb::GetRandomIntroducer () const { diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 6e251ecb..47a6fab5 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -28,12 +28,12 @@ namespace i2p namespace data { const int NETDB_MIN_ROUTERS = 90; - const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds - const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60; - const int NETDB_MIN_EXPIRATION_TIMEOUT = 90*60; // 1.5 hours - const int NETDB_MAX_EXPIRATION_TIMEOUT = 27*60*60; // 27 hours - const int NETDB_PUBLISH_INTERVAL = 60*40; - const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0,9,36); // 0.9.36 + const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds + const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60; + const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours + const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours + const int NETDB_PUBLISH_INTERVAL = 60 * 40; + const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36 /** function for visiting a leaseset stored in a floodfill */ typedef std::function)> LeaseSetVisitor; @@ -63,13 +63,13 @@ namespace data std::shared_ptr FindRouterProfile (const IdentHash& ident) const; void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr); - void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr); + void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr); void HandleDatabaseStoreMsg (std::shared_ptr msg); void HandleDatabaseSearchReplyMsg (std::shared_ptr msg); void HandleDatabaseLookupMsg (std::shared_ptr msg); void HandleNTCP2RouterInfoMsg (std::shared_ptr m); - + std::shared_ptr GetRandomRouter () const; std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith) const; std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const; @@ -80,13 +80,13 @@ namespace data std::vector GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly = false) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; - std::shared_ptr GetRandomRouterInFamily(const std::string & fam) const; + std::shared_ptr GetRandomRouterInFamily(const std::string & fam) const; void SetUnreachable (const IdentHash& ident, bool unreachable); void PostI2NPMsg (std::shared_ptr msg); - /** set hidden mode, aka don't publish our RI to netdb and don't explore */ - void SetHidden(bool hide); + /** set hidden mode, aka don't publish our RI to netdb and don't explore */ + void SetHidden(bool hide); void Reseed (); Families& GetFamilies () { return m_Families; }; @@ -119,12 +119,13 @@ namespace data void ManageLeaseSets (); void ManageRequests (); - void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20); + void ReseedFromFloodfill(const RouterInfo & ri, int numRouters = 40, int numFloodfills = 20); std::shared_ptr AddRouterInfo (const uint8_t * buf, int len, bool& updated); std::shared_ptr AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated); - template - std::shared_ptr GetRandomRouter (Filter filter) const; + + template + std::shared_ptr GetRandomRouter (Filter filter) const; private: @@ -150,12 +151,12 @@ namespace data bool m_PersistProfiles; - /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ - std::shared_ptr m_FloodfillBootstrap; + /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ + std::shared_ptr m_FloodfillBootstrap; - /** true if in hidden mode */ - bool m_HiddenMode; + /** true if in hidden mode */ + bool m_HiddenMode; }; extern NetDb netdb; diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index f1853124..b1eb9380 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -14,8 +14,8 @@ namespace data std::shared_ptr msg; if(replyTunnel) msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, - replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, - &m_ExcludedPeers); + replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, + &m_ExcludedPeers); else msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers); if(router) @@ -158,4 +158,3 @@ namespace data } } } - diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index 7a7a55ab..c5e077bf 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -66,4 +66,3 @@ namespace data } #endif - diff --git a/libi2pd/Poly1305.cpp b/libi2pd/Poly1305.cpp index bf94c9a9..23098d74 100644 --- a/libi2pd/Poly1305.cpp +++ b/libi2pd/Poly1305.cpp @@ -7,12 +7,11 @@ */ -#if !OPENSSL_AEAD_CHACHA20_POLY1305 +#if !OPENSSL_AEAD_CHACHA20_POLY1305 namespace i2p { namespace crypto { - void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz) { Poly1305 p(key); diff --git a/libi2pd/Poly1305.h b/libi2pd/Poly1305.h index 800fbfd9..f91a037e 100644 --- a/libi2pd/Poly1305.h +++ b/libi2pd/Poly1305.h @@ -1,9 +1,9 @@ /** - This code is licensed under the MCGSI Public License - Copyright 2018 Jeff Becker - - Kovri go write your own code - + * This code is licensed under the MCGSI Public License + * Copyright 2018 Jeff Becker + * + * Kovri go write your own code + * */ #ifndef LIBI2PD_POLY1305_H #define LIBI2PD_POLY1305_H @@ -11,7 +11,7 @@ #include #include "Crypto.h" -#if !OPENSSL_AEAD_CHACHA20_POLY1305 +#if !OPENSSL_AEAD_CHACHA20_POLY1305 namespace i2p { namespace crypto @@ -24,7 +24,6 @@ namespace crypto namespace poly1305 { - struct LongBlock { unsigned long data[17]; @@ -252,8 +251,8 @@ namespace crypto poly1305::LongBlock m_HR; uint8_t m_Final; }; - void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz); + void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz); } } #endif diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 98f95dc3..4f26e520 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -32,73 +32,76 @@ namespace data { } - /** @brief tries to bootstrap into I2P network (from local files and servers, with respect of options) - */ - void Reseeder::Bootstrap () - { - std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName); - std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName); - - if (su3FileName.length() > 0) // bootstrap from SU3 file or URL - { - int num; - if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://") - { - num = ReseedFromSU3Url (su3FileName); // from https URL - } - else - { - num = ProcessSU3File (su3FileName.c_str ()); - } - if (num == 0) - LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName); - } - else if (zipFileName.length() > 0) // bootstrap from ZIP file - { - int num = ProcessZIPFile (zipFileName.c_str ()); - if (num == 0) - LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName); - } - else // bootstrap from reseed servers - { - int num = ReseedFromServers (); - if (num == 0) - LogPrint (eLogWarning, "Reseed: failed to reseed from servers"); - } - } - - /** @brief bootstrap from random server, retry 10 times - * @return number of entries added to netDb - */ + /** + @brief tries to bootstrap into I2P network (from local files and servers, with respect of options) + */ + void Reseeder::Bootstrap () + { + std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName); + std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName); + + if (su3FileName.length() > 0) // bootstrap from SU3 file or URL + { + int num; + if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://") + { + num = ReseedFromSU3Url (su3FileName); // from https URL + } + else + { + num = ProcessSU3File (su3FileName.c_str ()); + } + if (num == 0) + LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName); + } + else if (zipFileName.length() > 0) // bootstrap from ZIP file + { + int num = ProcessZIPFile (zipFileName.c_str ()); + if (num == 0) + LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName); + } + else // bootstrap from reseed servers + { + int num = ReseedFromServers (); + if (num == 0) + LogPrint (eLogWarning, "Reseed: failed to reseed from servers"); + } + } + + /** + * @brief bootstrap from random server, retry 10 times + * @return number of entries added to netDb + */ int Reseeder::ReseedFromServers () { std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs); - std::vector httpsReseedHostList; - boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on); - - if (reseedURLs.length () == 0) - { - LogPrint (eLogWarning, "Reseed: No reseed servers specified"); - return 0; - } - - int reseedRetries = 0; - while (reseedRetries < 10) - { - auto ind = rand () % httpsReseedHostList.size (); - std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3"; - auto num = ReseedFromSU3Url (reseedUrl); - if (num > 0) return num; // success - reseedRetries++; - } - LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts"); - return 0; + std::vector httpsReseedHostList; + boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on); + + if (reseedURLs.length () == 0) + { + LogPrint (eLogWarning, "Reseed: No reseed servers specified"); + return 0; + } + + int reseedRetries = 0; + while (reseedRetries < 10) + { + auto ind = rand () % httpsReseedHostList.size (); + std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3"; + auto num = ReseedFromSU3Url (reseedUrl); + if (num > 0) return num; // success + reseedRetries++; + } + LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts"); + return 0; } - /** @brief bootstrap from HTTPS URL with SU3 file - * @param url - * @return number of entries added to netDb - */ + /** + * @brief bootstrap from HTTPS URL with SU3 file + * @param url + * @return number of entries added to netDb + */ int Reseeder::ReseedFromSU3Url (const std::string& url) { LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url); @@ -702,4 +705,3 @@ namespace data } } } - diff --git a/libi2pd/Reseed.h b/libi2pd/Reseed.h index a69969bf..5f402988 100644 --- a/libi2pd/Reseed.h +++ b/libi2pd/Reseed.h @@ -21,7 +21,7 @@ namespace data Reseeder(); ~Reseeder(); - void Bootstrap (); + void Bootstrap (); int ReseedFromServers (); int ReseedFromSU3Url (const std::string& url); int ProcessSU3File (const char * filename); diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b86ed8f2..b855fc29 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -338,10 +338,10 @@ namespace i2p { case low : /* not set */; break; case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P' - case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; - #if (__cplusplus >= 201703L) // C++ 17 or higher - [[fallthrough]]; - #endif + case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif // no break here, extra + high means 'X' case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break; } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 28c324c4..6382189b 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -15,7 +15,7 @@ namespace i2p { const char ROUTER_INFO[] = "router.info"; const char ROUTER_KEYS[] = "router.keys"; - const char NTCP2_KEYS[] = "ntcp2.keys"; + const char NTCP2_KEYS[] = "ntcp2.keys"; const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes enum RouterStatus @@ -36,12 +36,12 @@ namespace i2p { private: - struct NTCP2PrivateKeys + struct NTCP2PrivateKeys { uint8_t staticPublicKey[32]; uint8_t staticPrivateKey[32]; uint8_t iv[16]; - }; + }; public: @@ -63,7 +63,7 @@ namespace i2p const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; }; const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; }; const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; }; - i2p::crypto::X25519Keys& GetStaticKeys (); + i2p::crypto::X25519Keys& GetStaticKeys (); uint32_t GetUptime () const; // in seconds uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; @@ -77,7 +77,7 @@ namespace i2p void SetNetID (int netID) { m_NetID = netID; }; bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const; - void UpdatePort (int port); // called from Daemon + void UpdatePort (int port); // called from Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon void PublishNTCP2Address (int port, bool publish = true, bool v4only = false); void UpdateNTCP2Address (bool enable); @@ -124,7 +124,7 @@ namespace i2p // implements GarlicDestination void HandleI2NPMessage (const uint8_t * buf, size_t len); - bool HandleCloveI2NPMessage (I2NPMessageType 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: @@ -141,7 +141,7 @@ namespace i2p i2p::data::PrivateKeys m_Keys; std::shared_ptr m_Decryptor; uint64_t m_LastUpdateTime; // in seconds - bool m_AcceptsTunnels, m_IsFloodfill; + bool m_AcceptsTunnels, m_IsFloodfill; std::chrono::time_point m_StartupTime; uint64_t m_BandwidthLimit; // allowed bandwidth int m_ShareRatio; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 9b3b7e89..bf81a8af 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -35,12 +35,12 @@ namespace data } RouterInfo::RouterInfo (const uint8_t * buf, int len): - m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), + m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0), m_Version (0) { m_Addresses = boost::make_shared(); // create empty list if (len <= MAX_RI_BUFFER_SIZE) - { + { m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; memcpy (m_Buffer, buf, len); m_BufferLen = len; @@ -173,7 +173,6 @@ namespace data LogPrint (eLogError, "RouterInfo: malformed message"); m_IsUnreachable = true; } - } void RouterInfo::ReadFromStream (std::istream& s) @@ -192,7 +191,7 @@ namespace data s.read ((char *)&address->cost, sizeof (address->cost)); s.read ((char *)&address->date, sizeof (address->date)); bool isNTCP2Only = false; - char transportStyle[6]; + char transportStyle[6]; auto transportStyleLen = ReadString (transportStyle, 6, s) - 1; if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2 { @@ -231,13 +230,13 @@ namespace data address->host.to_string (ecode); if (!ecode) #endif - { + { // add supported protocol if (address->host.is_v4 ()) supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; else supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6; - } + } } } else if (!strcmp (key, "port")) @@ -262,15 +261,15 @@ namespace data { if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ()); supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6; - Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32); - } + Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32); + } else if (!strcmp (key, "i")) // ntcp2 iv { if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ()); supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6; - Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16); + Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16); address->ntcp2->isPublished = true; // presence if "i" means "published" - } + } else if (key[0] == 'i') { // introducers @@ -278,7 +277,7 @@ namespace data { LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped"); continue; - } + } introducers = true; size_t l = strlen(key); unsigned char index = key[l-1] - '0'; // TODO: @@ -309,7 +308,7 @@ namespace data } if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true; - if (supportedTransports) + if (supportedTransports) { addresses->push_back(address); m_SupportedTransports |= supportedTransports; @@ -349,13 +348,13 @@ namespace data while (*ch) { if (*ch >= '0' && *ch <= '9') - { - m_Version *= 10; + { + m_Version *= 10; m_Version += (*ch - '0'); - } + } ch++; - } - } + } + } // check netId else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != i2p::context.GetNetID ()) { @@ -384,9 +383,10 @@ namespace data SetUnreachable (true); } - bool RouterInfo::IsFamily(const std::string & fam) const { - return m_Family == fam; - } + bool RouterInfo::IsFamily(const std::string & fam) const + { + return m_Family == fam; + } void RouterInfo::ExtractCaps (const char * value) { @@ -580,7 +580,7 @@ namespace data properties << '='; WriteString (boost::lexical_cast(address.port), properties); properties << ';'; - } + } if (address.IsNTCP2 ()) { // publish s and v for NTCP2 @@ -588,7 +588,7 @@ namespace data WriteString (address.ntcp2->staticKey.ToBase64 (), properties); properties << ';'; WriteString ("v", properties); properties << '='; WriteString ("2", properties); properties << ';'; - } + } uint16_t size = htobe16 (properties.str ().size ()); s.write ((char *)&size, sizeof (size)); @@ -742,7 +742,7 @@ namespace data addr->ntcp2->isNTCP2Only = true; // NTCP2 only address if (port) addr->ntcp2->isPublished = true; memcpy (addr->ntcp2->staticKey, staticKey, 32); - memcpy (addr->ntcp2->iv, iv, 16); + memcpy (addr->ntcp2->iv, iv, 16); m_Addresses->push_back(std::move(addr)); } @@ -854,7 +854,7 @@ namespace data m_SupportedTransports |= eNTCPV6 | eSSUV6 | eNTCP2V6; } - void RouterInfo::EnableV4 () + void RouterInfo::EnableV4 () { if (!IsV4 ()) m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4; @@ -877,7 +877,7 @@ namespace data } } - void RouterInfo::DisableV4 () + void RouterInfo::DisableV4 () { if (IsV4 ()) { @@ -926,7 +926,7 @@ namespace data }); } - template + template std::shared_ptr RouterInfo::GetAddress (Filter filter) const { // TODO: make it more generic using comparator @@ -937,7 +937,7 @@ namespace data #endif for (const auto& address : *addresses) if (filter (address)) return address; - + return nullptr; } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index f8598b1e..5bdb0f8f 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -203,8 +203,8 @@ namespace data void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; bool IsNewer (const uint8_t * buf, size_t len) const; - /** return true if we are in a router family and the signature is valid */ - bool IsFamily(const std::string & fam) const; + /** return true if we are in a router family and the signature is valid */ + bool IsFamily(const std::string & fam) const; // implements RoutingDestination std::shared_ptr GetIdentity () const { return m_RouterIdentity; }; diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index 74cbe39b..4a33ff3a 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -45,15 +45,15 @@ namespace transport void SSUServer::OpenSocket () { - try + try { m_Socket.open (boost::asio::ip::udp::v4()); m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE)); m_Socket.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE)); m_Socket.bind (m_Endpoint); LogPrint (eLogInfo, "SSU: Start listening v4 port ", m_Endpoint.port()); - } - catch ( std::exception & ex ) + } + catch ( std::exception & ex ) { LogPrint (eLogError, "SSU: failed to bind to v4 port ", m_Endpoint.port(), ": ", ex.what()); ThrowFatal ("Unable to start IPv4 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ()); @@ -62,7 +62,7 @@ namespace transport void SSUServer::OpenSocketV6 () { - try + try { m_SocketV6.open (boost::asio::ip::udp::v6()); m_SocketV6.set_option (boost::asio::ip::v6_only (true)); @@ -70,8 +70,8 @@ namespace transport m_SocketV6.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE)); m_SocketV6.bind (m_EndpointV6); LogPrint (eLogInfo, "SSU: Start listening v6 port ", m_EndpointV6.port()); - } - catch ( std::exception & ex ) + } + catch ( std::exception & ex ) { LogPrint (eLogError, "SSU: failed to bind to v6 port ", m_EndpointV6.port(), ": ", ex.what()); ThrowFatal ("Unable to start IPv6 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ()); @@ -184,7 +184,7 @@ namespace transport m_Socket.close (); OpenSocket (); Receive (); - } + } } } } @@ -359,10 +359,10 @@ namespace transport { if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous { - if (session) - { - session->FlushData (); - session = nullptr; + if (session) + { + session->FlushData (); + session = nullptr; } auto it = sessions->find (packet->from); if (it != sessions->end ()) @@ -826,4 +826,3 @@ namespace transport } } } - diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h index 10e5ec06..942d0e64 100644 --- a/libi2pd/SSU.h +++ b/libi2pd/SSU.h @@ -40,7 +40,7 @@ namespace transport public: SSUServer (int port); - SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor + SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor ~SSUServer (); void Start (); void Stop (); @@ -135,4 +135,3 @@ namespace transport } #endif - diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index 866da277..4eb90522 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -496,7 +496,7 @@ namespace transport } // decay if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES || - i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL) + i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL) m_ReceivedMessages.clear (); ScheduleIncompleteMessagesCleanup (); @@ -504,4 +504,3 @@ namespace transport } } } - diff --git a/libi2pd/SSUData.h b/libi2pd/SSUData.h index fbd167bf..98d60c41 100644 --- a/libi2pd/SSUData.h +++ b/libi2pd/SSUData.h @@ -128,4 +128,3 @@ namespace transport } #endif - diff --git a/libi2pd/SSUSession.cpp b/libi2pd/SSUSession.cpp index 88dbcf04..e29af479 100644 --- a/libi2pd/SSUSession.cpp +++ b/libi2pd/SSUSession.cpp @@ -336,7 +336,7 @@ namespace transport m_SignedData->Insert (payload, 4); // insert Alice's signed on time payload += 4; // signed-on time size_t paddingSize = (payload - buf) + m_RemoteIdentity->GetSignatureLen (); - paddingSize &= 0x0F; // %16 + paddingSize &= 0x0F; // %16 if (paddingSize > 0) paddingSize = 16 - paddingSize; payload += paddingSize; // verify signature @@ -934,7 +934,7 @@ namespace transport for (const auto& it: msgs) if (it) { - if (it->GetLength () <= SSU_MAX_I2NP_MESSAGE_SIZE) + if (it->GetLength () <= SSU_MAX_I2NP_MESSAGE_SIZE) m_Data.Send (it); else LogPrint (eLogError, "SSU: I2NP message of size ", it->GetLength (), " can't be sent. Dropped"); @@ -1206,4 +1206,3 @@ namespace transport } } } - diff --git a/libi2pd/SSUSession.h b/libi2pd/SSUSession.h index 8f81838a..4f73158a 100644 --- a/libi2pd/SSUSession.h +++ b/libi2pd/SSUSession.h @@ -28,7 +28,7 @@ namespace transport const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes const int SSU_CLOCK_SKEW = 60; // in seconds - const size_t SSU_MAX_I2NP_MESSAGE_SIZE = 32768; + const size_t SSU_MAX_I2NP_MESSAGE_SIZE = 32768; // payload types (4 bits) const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0; @@ -81,12 +81,12 @@ namespace transport void Done (); void Failed (); const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; - + bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); }; void SendI2NPMessages (const std::vector >& msgs); void SendPeerTest (); // Alice - SessionState GetState () const { return m_State; }; + SessionState GetState () const { return m_State; }; size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; @@ -158,10 +158,7 @@ namespace transport std::unique_ptr m_SignedData; // we need it for SessionConfirmed only std::map > m_RelayRequests; // nonce->Charlie }; - - } } #endif - diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 21d08f30..64aff5bc 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -6,11 +6,11 @@ namespace i2p { namespace crypto { -#if OPENSSL_EDDSA +#if OPENSSL_EDDSA EDDSA25519Verifier::EDDSA25519Verifier (): m_Pkey (nullptr) { - m_MDCtx = EVP_MD_CTX_create (); + m_MDCtx = EVP_MD_CTX_create (); } EDDSA25519Verifier::~EDDSA25519Verifier () @@ -23,21 +23,21 @@ namespace crypto { m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); - } - + } + bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len); } - -#else + +#else EDDSA25519Verifier::EDDSA25519Verifier () { } EDDSA25519Verifier::~EDDSA25519Verifier () { - } + } void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey) { @@ -45,8 +45,8 @@ namespace crypto BN_CTX * ctx = BN_CTX_new (); m_PublicKey = GetEd25519 ()->DecodePublicKey (m_PublicKeyEncoded, ctx); BN_CTX_free (ctx); - } - + } + bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[64]; @@ -83,19 +83,19 @@ namespace crypto EDDSA25519SignerCompat::~EDDSA25519SignerCompat () { - } - + } + void EDDSA25519SignerCompat::Sign (const uint8_t * buf, int len, uint8_t * signature) const { GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature); } - -#if OPENSSL_EDDSA + +#if OPENSSL_EDDSA EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey): m_Fallback (nullptr) - { + { m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); - uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; + uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; size_t len = EDDSA25519_PUBLIC_KEY_LENGTH; EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len); if (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH)) @@ -105,10 +105,10 @@ namespace crypto m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey); } else - { - m_MDCtx = EVP_MD_CTX_create (); + { + m_MDCtx = EVP_MD_CTX_create (); EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); - } + } } EDDSA25519Signer::~EDDSA25519Signer () @@ -118,22 +118,20 @@ namespace crypto { EVP_MD_CTX_destroy (m_MDCtx); EVP_PKEY_free (m_Pkey); - } + } } void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const { if (m_Fallback) return m_Fallback->Sign (buf, len, signature); else - { - size_t l = 64; + { + size_t l = 64; uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232 - EVP_DigestSign (m_MDCtx, sig, &l, buf, len); + EVP_DigestSign (m_MDCtx, sig, &l, buf, len); memcpy (signature, sig, 64); - } - } -#endif + } + } +#endif } } - - diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 0c5f27d6..26184639 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -46,9 +46,9 @@ namespace crypto { m_PublicKey = CreateDSA (); } - + void SetPublicKey (const uint8_t * signingKey) - { + { DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL); } @@ -163,9 +163,9 @@ namespace crypto { m_PublicKey = EC_KEY_new_by_curve_name (curve); } - + void SetPublicKey (const uint8_t * signingKey) - { + { BIGNUM * x = BN_bin2bn (signingKey, keyLen/2, NULL); BIGNUM * y = BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL); EC_KEY_set_public_key_affine_coordinates (m_PublicKey, x, y); @@ -287,7 +287,7 @@ namespace crypto EDDSA25519Verifier (); void SetPublicKey (const uint8_t * signingKey); ~EDDSA25519Verifier (); - + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const; size_t GetPublicKeyLen () const { return EDDSA25519_PUBLIC_KEY_LENGTH; }; @@ -298,10 +298,10 @@ namespace crypto #if OPENSSL_EDDSA EVP_PKEY * m_Pkey; EVP_MD_CTX * m_MDCtx; -#else +#else EDDSAPoint m_PublicKey; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; -#endif +#endif }; class EDDSA25519SignerCompat: public Signer @@ -311,17 +311,17 @@ namespace crypto EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr); // we pass signingPublicKey to check if it matches private key ~EDDSA25519SignerCompat (); - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const; const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation private: - + uint8_t m_ExpandedPrivateKey[64]; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; }; -#if OPENSSL_EDDSA +#if OPENSSL_EDDSA class EDDSA25519Signer: public Signer { public: @@ -329,23 +329,23 @@ namespace crypto EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr); // we pass signingPublicKey to check if it matches private key ~EDDSA25519Signer (); - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const; private: EVP_PKEY * m_Pkey; - EVP_MD_CTX * m_MDCtx; + EVP_MD_CTX * m_MDCtx; EDDSA25519SignerCompat * m_Fallback; }; #else typedef EDDSA25519SignerCompat EDDSA25519Signer; - -#endif - + +#endif + inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { -#if OPENSSL_EDDSA +#if OPENSSL_EDDSA EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL); EVP_PKEY_keygen_init (pctx); @@ -355,12 +355,12 @@ namespace crypto EVP_PKEY_get_raw_public_key (pkey, signingPublicKey, &len); len = EDDSA25519_PRIVATE_KEY_LENGTH; EVP_PKEY_get_raw_private_key (pkey, signingPrivateKey, &len); - EVP_PKEY_free (pkey); -#else + EVP_PKEY_free (pkey); +#else RAND_bytes (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH); EDDSA25519Signer signer (signingPrivateKey); memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH); -#endif +#endif } @@ -399,18 +399,18 @@ namespace crypto GOSTR3410Verifier (GOSTR3410ParamSet paramSet): m_ParamSet (paramSet), m_PublicKey (nullptr) { - } + } - void SetPublicKey (const uint8_t * signingKey) + void SetPublicKey (const uint8_t * signingKey) { BIGNUM * x = BN_bin2bn (signingKey, GetPublicKeyLen ()/2, NULL); BIGNUM * y = BN_bin2bn (signingKey + GetPublicKeyLen ()/2, GetPublicKeyLen ()/2, NULL); m_PublicKey = GetGOSTR3410Curve (m_ParamSet)->CreatePoint (x, y); BN_free (x); BN_free (y); } - ~GOSTR3410Verifier () - { - if (m_PublicKey) EC_POINT_free (m_PublicKey); + ~GOSTR3410Verifier () + { + if (m_PublicKey) EC_POINT_free (m_PublicKey); } bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const @@ -501,18 +501,18 @@ namespace crypto auto publicKey = GetEd25519 ()->GeneratePublicKey (m_PrivateKey, ctx); GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); BN_CTX_free (ctx); - } + } ~RedDSA25519Signer () {}; - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { - GetEd25519 ()->SignRedDSA (m_PrivateKey, m_PublicKeyEncoded, buf, len, signature); + GetEd25519 ()->SignRedDSA (m_PrivateKey, m_PublicKeyEncoded, buf, len, signature); } - + const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation private: - + uint8_t m_PrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH]; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; }; @@ -521,10 +521,9 @@ namespace crypto { GetEd25519 ()->CreateRedDSAPrivateKey (signingPrivateKey); RedDSA25519Signer signer (signingPrivateKey); - memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH); + memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH); } } } #endif - diff --git a/libi2pd/Siphash.h b/libi2pd/Siphash.h index 70822466..78b22b90 100644 --- a/libi2pd/Siphash.h +++ b/libi2pd/Siphash.h @@ -1,9 +1,9 @@ /** - This code is licensed under the MCGSI Public License - Copyright 2018 Jeff Becker - - Kovri go write your own code - + * This code is licensed under the MCGSI Public License + * Copyright 2018 Jeff Becker + * + * Kovri go write your own code + * */ #ifndef SIPHASH_H #define SIPHASH_H @@ -14,140 +14,140 @@ #if !OPENSSL_SIPHASH namespace i2p { -namespace crypto +namespace crypto { - namespace siphash - { - constexpr int crounds = 2; - constexpr int drounds = 4; - - inline uint64_t rotl(const uint64_t & x, int b) - { - uint64_t ret = x << b; - ret |= x >> (64 - b); - return ret; - } - - inline void u32to8le(const uint32_t & v, uint8_t * p) - { - p[0] = (uint8_t) v; - p[1] = (uint8_t) (v >> 8); - p[2] = (uint8_t) (v >> 16); - p[3] = (uint8_t) (v >> 24); - } - - inline void u64to8le(const uint64_t & v, uint8_t * p) - { - p[0] = v & 0xff; - p[1] = (v >> 8) & 0xff; - p[2] = (v >> 16) & 0xff; - p[3] = (v >> 24) & 0xff; - p[4] = (v >> 32) & 0xff; - p[5] = (v >> 40) & 0xff; - p[6] = (v >> 48) & 0xff; - p[7] = (v >> 56) & 0xff; - } - - inline uint64_t u8to64le(const uint8_t * p) - { - uint64_t i = 0; - int idx = 0; - while(idx < 8) - { - i |= ((uint64_t) p[idx]) << (idx * 8); - ++idx; - } - return i; - } - - inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3) - { - _v0 += _v1; - _v1 = rotl(_v1, 13); - _v1 ^= _v0; - _v0 = rotl(_v0, 32); - _v2 += _v3; - _v3 = rotl(_v3, 16); - _v3 ^= _v2; - _v0 += _v3; - _v3 = rotl(_v3, 21); - _v3 ^= _v0; - _v2 += _v1; - _v1 = rotl(_v1, 17); - _v1 ^= _v2; - _v2 = rotl(_v2, 32); - } - } - - /** hashsz must be 8 or 16 */ - template - inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key) - { - uint64_t v0 = 0x736f6d6570736575ULL; - uint64_t v1 = 0x646f72616e646f6dULL; - uint64_t v2 = 0x6c7967656e657261ULL; - uint64_t v3 = 0x7465646279746573ULL; - const uint64_t k0 = siphash::u8to64le(key); - const uint64_t k1 = siphash::u8to64le(key + 8); - uint64_t msg; - int i; - const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t)); - auto left = bufsz & 7; - uint64_t b = ((uint64_t)bufsz) << 56; - v3 ^= k1; - v2 ^= k0; - v1 ^= k1; - v0 ^= k0; - - if(hashsz == 16) v1 ^= 0xee; - - while(buf != end) - { - msg = siphash::u8to64le(buf); - v3 ^= msg; - for(i = 0; i < siphash::crounds; ++i) - siphash::round(v0, v1, v2, v3); - - v0 ^= msg; - buf += 8; - } - - while(left) - { - --left; - b |= ((uint64_t)(buf[left])) << (left * 8); - } - - v3 ^= b; - - for(i = 0; i < siphash::crounds; ++i) - siphash::round(v0, v1, v2, v3); - - v0 ^= b; - - - if(hashsz == 16) - v2 ^= 0xee; - else - v2 ^= 0xff; - - for(i = 0; i < siphash::drounds; ++i) - siphash::round(v0, v1, v2, v3); - - b = v0 ^ v1 ^ v2 ^ v3; - - siphash::u64to8le(b, h); - - if(hashsz == 8) return; - - v1 ^= 0xdd; - - for (i = 0; i < siphash::drounds; ++i) - siphash::round(v0, v1, v2, v3); - - b = v0 ^ v1 ^ v2 ^ v3; - siphash::u64to8le(b, h + 8); - } + namespace siphash + { + constexpr int crounds = 2; + constexpr int drounds = 4; + + inline uint64_t rotl(const uint64_t & x, int b) + { + uint64_t ret = x << b; + ret |= x >> (64 - b); + return ret; + } + + inline void u32to8le(const uint32_t & v, uint8_t * p) + { + p[0] = (uint8_t) v; + p[1] = (uint8_t) (v >> 8); + p[2] = (uint8_t) (v >> 16); + p[3] = (uint8_t) (v >> 24); + } + + inline void u64to8le(const uint64_t & v, uint8_t * p) + { + p[0] = v & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; + p[4] = (v >> 32) & 0xff; + p[5] = (v >> 40) & 0xff; + p[6] = (v >> 48) & 0xff; + p[7] = (v >> 56) & 0xff; + } + + inline uint64_t u8to64le(const uint8_t * p) + { + uint64_t i = 0; + int idx = 0; + while(idx < 8) + { + i |= ((uint64_t) p[idx]) << (idx * 8); + ++idx; + } + return i; + } + + inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3) + { + _v0 += _v1; + _v1 = rotl(_v1, 13); + _v1 ^= _v0; + _v0 = rotl(_v0, 32); + _v2 += _v3; + _v3 = rotl(_v3, 16); + _v3 ^= _v2; + _v0 += _v3; + _v3 = rotl(_v3, 21); + _v3 ^= _v0; + _v2 += _v1; + _v1 = rotl(_v1, 17); + _v1 ^= _v2; + _v2 = rotl(_v2, 32); + } + } + + /** hashsz must be 8 or 16 */ + template + inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key) + { + uint64_t v0 = 0x736f6d6570736575ULL; + uint64_t v1 = 0x646f72616e646f6dULL; + uint64_t v2 = 0x6c7967656e657261ULL; + uint64_t v3 = 0x7465646279746573ULL; + const uint64_t k0 = siphash::u8to64le(key); + const uint64_t k1 = siphash::u8to64le(key + 8); + uint64_t msg; + int i; + const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t)); + auto left = bufsz & 7; + uint64_t b = ((uint64_t)bufsz) << 56; + v3 ^= k1; + v2 ^= k0; + v1 ^= k1; + v0 ^= k0; + + if(hashsz == 16) v1 ^= 0xee; + + while(buf != end) + { + msg = siphash::u8to64le(buf); + v3 ^= msg; + for(i = 0; i < siphash::crounds; ++i) + siphash::round(v0, v1, v2, v3); + + v0 ^= msg; + buf += 8; + } + + while(left) + { + --left; + b |= ((uint64_t)(buf[left])) << (left * 8); + } + + v3 ^= b; + + for(i = 0; i < siphash::crounds; ++i) + siphash::round(v0, v1, v2, v3); + + v0 ^= b; + + + if(hashsz == 16) + v2 ^= 0xee; + else + v2 ^= 0xff; + + for(i = 0; i < siphash::drounds; ++i) + siphash::round(v0, v1, v2, v3); + + b = v0 ^ v1 ^ v2 ^ v3; + + siphash::u64to8le(b, h); + + if(hashsz == 8) return; + + v1 ^= 0xdd; + + for (i = 0; i < siphash::drounds; ++i) + siphash::round(v0, v1, v2, v3); + + b = v0 ^ v1 ^ v2 ^ v3; + siphash::u64to8le(b, h + 8); + } } } #endif diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 00ee35b0..ac527cb4 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -34,7 +34,7 @@ namespace stream else { // partially - rem = len - offset; + rem = len - offset; memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset); nextBuffer->offset += (len - offset); offset = len; // break @@ -60,7 +60,7 @@ namespace stream m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), - m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), + m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU) @@ -73,7 +73,7 @@ namespace stream m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), - m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE), + m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU) { @@ -228,7 +228,7 @@ namespace stream Terminate (); return; } - + packet->offset = packet->GetPayload () - packet->buf; if (packet->GetLength () > 0) { @@ -258,7 +258,7 @@ namespace stream bool Stream::ProcessOptions (uint16_t flags, Packet * packet) { const uint8_t * optionData = packet->GetOptionData (); - size_t optionSize = packet->GetOptionSize (); + size_t optionSize = packet->GetOptionSize (); if (flags & PACKET_FLAG_DELAY_REQUESTED) optionData += 2; @@ -269,7 +269,7 @@ namespace stream m_RemoteIdentity = std::make_shared(optionData, optionSize); if (m_RemoteIdentity->IsRSA ()) { - LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded"); + LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded"); return false; } optionData += m_RemoteIdentity->GetFullLen (); @@ -306,11 +306,11 @@ namespace stream size_t offset = 0; m_TransientVerifier = i2p::data::ProcessOfflineSignature (m_RemoteIdentity, optionData, optionSize - (optionData - packet->GetOptionData ()), offset); optionData += offset; - if (!m_TransientVerifier) + if (!m_TransientVerifier) { LogPrint (eLogError, "Streaming: offline signature failed"); return false; - } + } } } @@ -322,7 +322,7 @@ namespace stream { memcpy (signature, optionData, signatureLen); memset (const_cast(optionData), 0, signatureLen); - bool verified = m_TransientVerifier ? + bool verified = m_TransientVerifier ? m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) : m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature); if (!verified) @@ -340,7 +340,7 @@ namespace stream return false; } } - return true; + return true; } void Stream::ProcessAck (Packet * packet) @@ -435,7 +435,7 @@ namespace stream m_SendBuffer.Add (buf, len, handler); } else if (handler) - handler(boost::system::error_code ()); + handler(boost::system::error_code ()); m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ())); } @@ -471,14 +471,14 @@ namespace stream size++; // resend delay if (m_Status == eStreamStatusNew) { - // initial packet + // initial packet m_Status = eStreamStatusOpen; if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());; if (m_RemoteLeaseSet) - { + { m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU; - } + } uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED | PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED; if (isNoAck) flags |= PACKET_FLAG_NO_ACK; @@ -488,7 +488,7 @@ namespace stream size += 2; // flags size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen (); size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); - uint8_t * optionsSize = packet + size; // set options size later + uint8_t * optionsSize = packet + size; // set options size later size += 2; // options size m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen); size += identityLen; // from @@ -654,7 +654,7 @@ namespace stream size += 4; // receiveStreamID htobe32buf (packet + size, m_SequenceNumber++); size += 4; // sequenceNum - htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0); + htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0); size += 4; // ack Through packet[size] = 0; size++; // NACK count @@ -748,7 +748,7 @@ namespace stream auto ts = i2p::util::GetMillisecondsSinceEpoch (); if (!m_CurrentRemoteLease || !m_CurrentRemoteLease->endDate || // excluded from LeaseSet - ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD) + ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD) UpdateCurrentRemoteLease (true); if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD) { @@ -785,7 +785,7 @@ namespace stream if (ts > m_RoutingSession->GetLeaseSetSubmissionTime () + i2p::garlic::LEASET_CONFIRMATION_TIMEOUT) { // LeaseSet was not confirmed, should try other tunnels - LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit"); + LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit"); m_RoutingSession->SetSharedRoutingPath (nullptr); m_CurrentOutboundTunnel = nullptr; m_CurrentRemoteLease = nullptr; @@ -848,9 +848,9 @@ namespace stream break; case 2: m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time -#if (__cplusplus >= 201703L) // C++ 17 or higher - [[fallthrough]]; -#endif +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif // no break here case 4: if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); @@ -911,7 +911,7 @@ namespace stream // LeaseSet updated m_RemoteIdentity = m_RemoteLeaseSet->GetIdentity (); m_TransientVerifier = m_RemoteLeaseSet->GetTransientVerifier (); - } + } } if (m_RemoteLeaseSet) { @@ -926,7 +926,7 @@ namespace stream m_LocalDestination.GetOwner ()->RequestDestinationWithEncryptedLeaseSet ( std::make_shared(m_RemoteIdentity)); else - m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); + m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); leases = m_RemoteLeaseSet->GetNonExpiredLeases (true); // then with threshold } if (!leases.empty ()) @@ -994,7 +994,7 @@ namespace stream { std::unique_lock l(m_StreamsMutex); for (auto it: m_Streams) - it.second->Terminate (false); // we delete here + it.second->Terminate (false); // we delete here m_Streams.clear (); m_IncomingStreams.clear (); } @@ -1136,8 +1136,8 @@ namespace stream return false; DeleteStream (it->second); return true; - } - + } + void StreamingDestination::SetAcceptor (const Acceptor& acceptor) { m_Acceptor = acceptor; // we must set it immediately for IsAcceptorSet @@ -1164,7 +1164,7 @@ namespace stream m_Owner->GetService ().post([acceptor, this](void) { if (!m_PendingIncomingStreams.empty ()) - { + { acceptor (m_PendingIncomingStreams.front ()); m_PendingIncomingStreams.pop_front (); if (m_PendingIncomingStreams.empty ()) diff --git a/libi2pd/Tag.h b/libi2pd/Tag.h index 010b160f..eefab6de 100644 --- a/libi2pd/Tag.h +++ b/libi2pd/Tag.h @@ -16,93 +16,91 @@ namespace i2p { namespace data { - -template -class Tag -{ - BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes"); - -public: - - Tag () = default; - Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); } - - bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); } - bool operator!= (const Tag& other) const { return !(*this == other); } - bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; } - - uint8_t * operator()() { return m_Buf; } - const uint8_t * operator()() const { return m_Buf; } - - operator uint8_t * () { return m_Buf; } - operator const uint8_t * () const { return m_Buf; } - - const uint8_t * data() const { return m_Buf; } - const uint64_t * GetLL () const { return ll; } - - bool IsZero () const - { - for (size_t i = 0; i < sz/8; ++i) - if (ll[i]) return false; - return true; - } - - void Fill(uint8_t c) + template + class Tag { - memset(m_Buf, c, sz); - } - - void Randomize() - { - RAND_bytes(m_Buf, sz); - } - - std::string ToBase64 () const - { - char str[sz*2]; - size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2); - return std::string (str, str + l); - } - - std::string ToBase32 () const - { - char str[sz*2]; - size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2); - return std::string (str, str + l); - } - - size_t FromBase32 (const std::string& s) - { - return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz); - } - - size_t FromBase64 (const std::string& s) - { - return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); - } - -private: - - union // 8 bytes aligned - { - uint8_t m_Buf[sz]; - uint64_t ll[sz/8]; + BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes"); + + public: + + Tag () = default; + Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); } + + bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); } + bool operator!= (const Tag& other) const { return !(*this == other); } + bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; } + + uint8_t * operator()() { return m_Buf; } + const uint8_t * operator()() const { return m_Buf; } + + operator uint8_t * () { return m_Buf; } + operator const uint8_t * () const { return m_Buf; } + + const uint8_t * data() const { return m_Buf; } + const uint64_t * GetLL () const { return ll; } + + bool IsZero () const + { + for (size_t i = 0; i < sz/8; ++i) + if (ll[i]) return false; + return true; + } + + void Fill(uint8_t c) + { + memset(m_Buf, c, sz); + } + + void Randomize() + { + RAND_bytes(m_Buf, sz); + } + + std::string ToBase64 () const + { + char str[sz*2]; + size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2); + return std::string (str, str + l); + } + + std::string ToBase32 () const + { + char str[sz*2]; + size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2); + return std::string (str, str + l); + } + + size_t FromBase32 (const std::string& s) + { + return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz); + } + + size_t FromBase64 (const std::string& s) + { + return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); + } + + private: + + union // 8 bytes aligned + { + uint8_t m_Buf[sz]; + uint64_t ll[sz/8]; + }; }; -}; - } // data } // i2p namespace std { - // hash for std::unordered_map - template struct hash > - { - size_t operator()(const i2p::data::Tag& s) const - { - return s.GetLL ()[0]; - } - }; + // hash for std::unordered_map + template struct hash > + { + size_t operator()(const i2p::data::Tag& s) const + { + return s.GetLL ()[0]; + } + }; } #endif /* TAG_H__ */ diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index acc9cb10..9e435e21 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -24,26 +24,26 @@ namespace util static uint64_t GetLocalMillisecondsSinceEpoch () { return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); + std::chrono::system_clock::now().time_since_epoch()).count (); } static uint32_t GetLocalHoursSinceEpoch () { return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); + std::chrono::system_clock::now().time_since_epoch()).count (); } static uint64_t GetLocalSecondsSinceEpoch () { return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); + std::chrono::system_clock::now().time_since_epoch()).count (); } static int64_t g_TimeOffset = 0; // in seconds static void SyncTimeWithNTP (const std::string& address) { - LogPrint (eLogInfo, "Timestamp: NTP request to ", address); + LogPrint (eLogInfo, "Timestamp: NTP request to ", address); boost::asio::io_service service; boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp"); boost::system::error_code ec; @@ -148,11 +148,11 @@ namespace util } void NTPTimeSync::Sync () - { + { if (m_NTPServersList.size () > 0) SyncTimeWithNTP (m_NTPServersList[rand () % m_NTPServersList.size ()]); else - m_IsRunning = false; + m_IsRunning = false; if (m_IsRunning) { @@ -200,4 +200,3 @@ namespace util } } } - diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index 31dc86aa..7d183cd3 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -15,8 +15,8 @@ namespace util uint32_t GetHoursSinceEpoch (); uint64_t GetSecondsSinceEpoch (); - void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes - void GetDateString (uint64_t timestamp, char * date); // timestap is seconds since epoch, returns date as YYYYMMDD string, 9 bytes + void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes + void GetDateString (uint64_t timestamp, char * date); // timestap is seconds since epoch, returns date as YYYYMMDD string, 9 bytes class NTPTimeSync { @@ -26,17 +26,17 @@ namespace util ~NTPTimeSync (); void Start (); - void Stop (); + void Stop (); private: - + void Run (); - void Sync (); + void Sync (); private: bool m_IsRunning; - std::unique_ptr m_Thread; + std::unique_ptr m_Thread; boost::asio::io_service m_Service; boost::asio::deadline_timer m_Timer; int m_SyncInterval; @@ -46,4 +46,3 @@ namespace util } #endif - diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index 1adc4178..02aac23f 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -12,7 +12,7 @@ namespace i2p namespace tunnel { TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * layerKey,const uint8_t * ivKey): TunnelBase (receiveTunnelID, nextTunnelID, nextIdent) { @@ -88,7 +88,7 @@ namespace tunnel std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey, + const uint8_t * layerKey,const uint8_t * ivKey, bool isGateway, bool isEndpoint) { if (isEndpoint) diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 55c39c7a..69b772cb 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -68,15 +68,15 @@ namespace transport std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; } - std::shared_ptr GetRemoteIdentity () + std::shared_ptr GetRemoteIdentity () { std::lock_guard l(m_RemoteIdentityMutex); - return m_RemoteIdentity; + return m_RemoteIdentity; } - void SetRemoteIdentity (std::shared_ptr ident) + void SetRemoteIdentity (std::shared_ptr ident) { std::lock_guard l(m_RemoteIdentityMutex); - m_RemoteIdentity = ident; + m_RemoteIdentity = ident; } size_t GetNumSentBytes () const { return m_NumSentBytes; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index bb74e2ad..15820584 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -220,10 +220,10 @@ namespace transport return; } else - { + { m_NTCP2Server = new NTCP2Server (); m_NTCP2Server->Start (); - } + } } // create acceptors @@ -390,7 +390,7 @@ namespace transport { auto r = netdb.FindRouter (ident); { - std::unique_lock l(m_PeersMutex); + std::unique_lock l(m_PeersMutex); it = m_Peers.insert (std::pair(ident, { 0, r, {}, i2p::util::GetSecondsSinceEpoch (), {} })).first; } @@ -553,13 +553,13 @@ namespace transport { auto router = i2p::data::netdb.GetRandomPeerTestRouter (isv4); // v4 only if v4 if (router) - m_SSUServer->CreateSession (router, true, isv4); // peer test + m_SSUServer->CreateSession (router, true, isv4); // peer test else { // if not peer test capable routers found pick any router = i2p::data::netdb.GetRandomRouter (); if (router && router->IsSSU ()) - m_SSUServer->CreateSession (router); // no peer test + m_SSUServer->CreateSession (router); // no peer test } } if (i2p::context.SupportsV6 ()) @@ -574,7 +574,7 @@ namespace transport if (addr) m_SSUServer->GetServiceV6 ().post ([this, router, addr] { - m_SSUServer->CreateDirectSession (router, { addr->host, (uint16_t)addr->port }, false); + m_SSUServer->CreateDirectSession (router, { addr->host, (uint16_t)addr->port }, false); }); } } @@ -713,7 +713,7 @@ namespace transport { profile->TunnelNonReplied(); } - std::unique_lock l(m_PeersMutex); + std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); } else diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 117092ad..37cfa269 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -103,7 +103,7 @@ namespace transport uint64_t GetTotalReceivedBytes () const { return m_TotalReceivedBytes; }; uint64_t GetTotalTransitTransmittedBytes () const { return m_TotalTransitTransmittedBytes; } void UpdateTotalTransitTransmittedBytes (uint32_t add) { m_TotalTransitTransmittedBytes += add; }; - uint32_t GetInBandwidth () const { return m_InBandwidth; }; + uint32_t GetInBandwidth () const { return m_InBandwidth; }; uint32_t GetOutBandwidth () const { return m_OutBandwidth; }; uint32_t GetTransitBandwidth () const { return m_TransitBandwidth; }; bool IsBandwidthExceeded () const; @@ -111,16 +111,16 @@ namespace transport size_t GetNumPeers () const { return m_Peers.size (); }; std::shared_ptr GetRandomPeer () const; - /** get a trusted first hop for restricted routes */ - std::shared_ptr GetRestrictedPeer() const; - /** do we want to use restricted routes? */ - bool RoutesRestricted() const; - /** restrict routes to use only these router families for first hops */ - void RestrictRoutesToFamilies(std::set families); - /** restrict routes to use only these routers for first hops */ - void RestrictRoutesToRouters(std::set routers); + /** get a trusted first hop for restricted routes */ + std::shared_ptr GetRestrictedPeer() const; + /** do we want to use restricted routes? */ + bool RoutesRestricted() const; + /** restrict routes to use only these router families for first hops */ + void RestrictRoutesToFamilies(std::set families); + /** restrict routes to use only these routers for first hops */ + void RestrictRoutesToRouters(std::set routers); - bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const; + bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const; void PeerTest (); diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index 324d5315..6e453d91 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -64,8 +64,7 @@ namespace tunnel m.hash = i2p::data::IdentHash (fragment); fragment += 32; // to hash break; - default: - ; + default: ; } bool isFragmented = flag & 0x08; diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index 7d0069a9..3f4069e1 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -51,7 +51,7 @@ namespace tunnel // create fragments const std::shared_ptr & msg = block.data; size_t fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length - + if (!messageCreated && fullMsgLen > m_RemainingSize) // check if we should complete previous message { size_t numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE; @@ -172,7 +172,7 @@ namespace tunnel SHA256(payload, size+16, hash); memcpy (buf+20, hash, 4); // checksum payload[-1] = 0; // zero - ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1 + ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1 if (paddingSize > 0) { // non-zero padding @@ -219,4 +219,3 @@ namespace tunnel } } } - diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 7256b2db..54459960 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -16,7 +16,6 @@ namespace i2p { namespace tunnel { - TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels): m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true), @@ -67,7 +66,8 @@ namespace tunnel m_Tests.clear (); } - bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) { + bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) + { if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0) { m_NumInboundHops = inHops; @@ -78,7 +78,7 @@ namespace tunnel } return false; } - + void TunnelPool::TunnelCreated (std::shared_ptr createdTunnel) { if (!m_IsActive) return; @@ -180,8 +180,8 @@ namespace tunnel { if (it->IsEstablished () && it != excluded) { - tunnel = it; - i++; + tunnel = it; + i++; } if (i > ind && tunnel) break; } @@ -411,7 +411,7 @@ namespace tunnel { std::lock_guard lock(m_CustomPeerSelectorMutex); if (m_CustomPeerSelector) - return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound); + return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound); } // explicit peers in use if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound); diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index d6fb91cc..149a5efa 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -75,23 +75,23 @@ namespace tunnel /** i2cp reconfigure */ bool Reconfigure(int inboundHops, int outboundHops, int inboundQuant, int outboundQuant); - + void SetCustomPeerSelector(ITunnelPeerSelector * selector); void UnsetCustomPeerSelector(); bool HasCustomPeerSelector(); - /** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */ - void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; } + /** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */ + void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; } - /** @brief return true if this tunnel pool has a latency requirement */ - bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; } + /** @brief return true if this tunnel pool has a latency requirement */ + bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; } - /** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */ - std::shared_ptr GetLowestLatencyInboundTunnel(std::shared_ptr exclude=nullptr) const; - std::shared_ptr GetLowestLatencyOutboundTunnel(std::shared_ptr exclude=nullptr) const; + /** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */ + std::shared_ptr GetLowestLatencyInboundTunnel(std::shared_ptr exclude = nullptr) const; + std::shared_ptr GetLowestLatencyOutboundTunnel(std::shared_ptr exclude = nullptr) const; - // for overriding tunnel peer selection - std::shared_ptr SelectNextHop (std::shared_ptr prevHop) const; + // for overriding tunnel peer selection + std::shared_ptr SelectNextHop (std::shared_ptr prevHop) const; private: @@ -118,8 +118,8 @@ namespace tunnel std::mutex m_CustomPeerSelectorMutex; ITunnelPeerSelector * m_CustomPeerSelector; - uint64_t m_MinLatency=0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms - uint64_t m_MaxLatency=0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms + uint64_t m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms + uint64_t m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms public: diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index 0a76bda7..3bac4878 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -31,8 +31,8 @@ namespace api bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); i2p::crypto::InitCrypto (precomputation); - int netID; i2p::config::GetOption("netid", netID); - i2p::context.SetNetID (netID); + int netID; i2p::config::GetOption("netid", netID); + i2p::context.SetNetID (netID); i2p::context.Init (); } @@ -133,4 +133,3 @@ namespace api } } } - diff --git a/libi2pd/api.h b/libi2pd/api.h index f64590d1..444667f0 100644 --- a/libi2pd/api.h +++ b/libi2pd/api.h @@ -35,4 +35,3 @@ namespace api } #endif - diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index c1b741fc..37898167 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -64,9 +64,9 @@ namespace util { m_IsRunning = true; m_Thread.reset (new std::thread (std::bind (& RunnableService::Run, this))); - } + } } - + void RunnableService::StopIOService () { if (m_IsRunning) @@ -79,7 +79,7 @@ namespace util m_Thread = nullptr; } } - } + } void RunnableService::Run () { @@ -94,28 +94,28 @@ namespace util LogPrint (eLogError, m_Name, ": runtime exception: ", ex.what ()); } } - } - + } + namespace net { #ifdef WIN32 bool IsWindowsXPorLater() { - static bool isRequested = false; - static bool isXP = false; - if (!isRequested) - { - // request - OSVERSIONINFO osvi; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - - isXP = osvi.dwMajorVersion <= 5; - isRequested = true; - } - return isXP; + static bool isRequested = false; + static bool isXP = false; + if (!isRequested) + { + // request + OSVERSIONINFO osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + isXP = osvi.dwMajorVersion <= 5; + isRequested = true; + } + return isXP; } int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback) @@ -246,22 +246,24 @@ namespace net std::string localAddressUniversal = localAddress.to_string(); #endif - typedef int (* IPN)(int af, const char *src, void *dst); + 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 (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found if(localAddress.is_v4()) { sockaddr_in inputAddress; - inetpton(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; - inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); return GetMTUWindowsIpv6(inputAddress, fallback); - } else { + } + else + { LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported"); return fallback; } @@ -355,7 +357,7 @@ namespace net if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af) { // match - char 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); @@ -379,7 +381,6 @@ namespace net LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname); } return boost::asio::ip::address::from_string(fallback); - #endif } } diff --git a/libi2pd/util.h b/libi2pd/util.h index 2202ccd9..aa83ed7b 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -132,34 +132,34 @@ namespace util boost::asio::io_service& GetIOService () { return m_Service; } bool IsRunning () const { return m_IsRunning; }; - + void StartIOService (); void StopIOService (); private: void Run (); - + private: std::string m_Name; volatile bool m_IsRunning; std::unique_ptr m_Thread; boost::asio::io_service m_Service; - }; + }; class RunnableServiceWithWork: public RunnableService { protected: - RunnableServiceWithWork (const std::string& name): - RunnableService (name), m_Work (GetIOService ()) {} - + RunnableServiceWithWork (const std::string& name): + RunnableService (name), m_Work (GetIOService ()) {} + private: boost::asio::io_service::work m_Work; - }; - + }; + namespace net { int GetMTU (const boost::asio::ip::address& localAddress); diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 0e40c76e..8e14c526 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -31,7 +31,7 @@ namespace client std::string etagsPath, indexPath, localPath; public: - AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32") + AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32") { i2p::config::GetOption("persist.addressbook", m_IsPersist); } @@ -77,10 +77,10 @@ namespace client std::shared_ptr AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const { - if (!m_IsPersist) + if (!m_IsPersist) { LogPrint(eLogDebug, "Addressbook: Persistence is disabled"); - return nullptr; + return nullptr; } std::string filename = storage.Path(ident.ToBase32()); std::ifstream f(filename, std::ifstream::binary); @@ -121,7 +121,7 @@ namespace client void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident) { - if (!m_IsPersist) return; + if (!m_IsPersist) return; storage.Remove( ident.ToBase32() ); } @@ -189,7 +189,7 @@ namespace client } for (const auto& it: addresses) - { + { f << it.first << ","; if (it.second->IsIdentHash ()) f << it.second->identHash.ToBase32 (); @@ -251,12 +251,12 @@ namespace client if (blindedPublicKey->IsValid ()) addressType = eAddressBlindedPublicKey; } - } + } Address::Address (const i2p::data::IdentHash& hash) { addressType = eAddressIndentHash; - identHash = hash; + identHash = hash; } AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false), @@ -322,7 +322,7 @@ namespace client { auto pos = address.find(".b32.i2p"); if (pos != std::string::npos) - { + { auto addr = std::make_shared(address.substr (0, pos)); return addr->IsValid () ? addr : nullptr; } @@ -333,10 +333,10 @@ namespace client { auto addr = FindAddress (address); if (!addr) - LookupAddress (address); // TODO: + LookupAddress (address); // TODO: return addr; - } - } + } + } // if not .b32 we assume full base64 address i2p::data::IdentityEx dest; if (!dest.FromBase64 (address)) @@ -359,10 +359,10 @@ namespace client { m_Addresses[address] = std::make_shared
(jump.substr (0, pos)); LogPrint (eLogInfo, "Addressbook: added ", address," -> ", jump); - } + } else - { - // assume base64 + { + // assume base64 auto ident = std::make_shared(); if (ident->FromBase64 (jump)) { @@ -487,18 +487,18 @@ namespace client LogPrint (eLogWarning, "Addressbook: subscriptions.txt usage is deprecated, use config file instead"); } else if (!i2p::config::IsDefault("addressbook.subscriptions")) - { - // using config file items - std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs); - std::vector subsList; - boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on); - - for (size_t i = 0; i < subsList.size (); i++) - { - m_Subscriptions.push_back (std::make_shared (*this, subsList[i])); - } - LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded"); - } + { + // using config file items + std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs); + std::vector subsList; + boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on); + + for (size_t i = 0; i < subsList.size (); i++) + { + m_Subscriptions.push_back (std::make_shared (*this, subsList[i])); + } + LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded"); + } } else LogPrint (eLogError, "Addressbook: subscriptions already loaded"); @@ -515,7 +515,7 @@ namespace client if (dot != std::string::npos) { auto domain = it.first.substr (dot + 1); - auto it1 = m_Addresses.find (domain); // find domain in our addressbook + auto it1 = m_Addresses.find (domain); // find domain in our addressbook if (it1 != m_Addresses.end () && it1->second->IsIdentHash ()) { auto dest = context.FindLocalDestination (it1->second->identHash); @@ -610,7 +610,7 @@ namespace client { // download it from default subscription LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription."); - std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL); + std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL); if (!m_DefaultSubscription) m_DefaultSubscription = std::make_shared(*this, defaultSubURL); m_IsDownloading = true; @@ -743,13 +743,13 @@ namespace client i2p::http::URL url; // must be run in separate thread LogPrint (eLogInfo, "Addressbook: Downloading hosts database from ", m_Link); - if (!url.parse(m_Link)) + if (!url.parse(m_Link)) { LogPrint(eLogError, "Addressbook: failed to parse url: ", m_Link); return false; } auto addr = m_Book.GetAddress (url.host); - if (!addr || !addr->IsIdentHash ()) + if (!addr || !addr->IsIdentHash ()) { LogPrint (eLogError, "Addressbook: Can't resolve ", url.host); return false; @@ -802,7 +802,7 @@ namespace client /* convert url to relative */ url.schema = ""; url.host = ""; - req.uri = url.to_string(); + req.uri = url.to_string(); auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port); std::string request = req.to_string(); stream->Send ((const uint8_t *) request.data(), request.length()); @@ -920,7 +920,7 @@ namespace client { auto datagram = m_LocalDestination->GetDatagramDestination (); if (datagram) - datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT); + datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT); } } diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index 82ba167b..fb69dad3 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -37,8 +37,8 @@ namespace client i2p::data::IdentHash identHash; std::shared_ptr blindedPublicKey; - Address (const std::string& b32); - Address (const i2p::data::IdentHash& hash); + Address (const std::string& b32); + Address (const i2p::data::IdentHash& hash); bool IsIdentHash () const { return addressType == eAddressIndentHash; }; bool IsValid () const { return addressType != eAddressInvalid; }; }; @@ -160,5 +160,3 @@ namespace client } #endif - - diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index c7bbdb46..e5d5404b 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -50,10 +50,10 @@ namespace client void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr receiver) { receiver->socket->async_read_some (boost::asio::buffer( - receiver->buffer + receiver->bufferOffset, - BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset), + receiver->buffer + receiver->bufferOffset, + BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset), std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this, - std::placeholders::_1, std::placeholders::_2, receiver)); + std::placeholders::_1, std::placeholders::_2, receiver)); } void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred, @@ -255,7 +255,7 @@ namespace client std::bind(&BOBCommandSession::HandleReceivedLine, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - + void BOBCommandSession::HandleReceivedLine(const boost::system::error_code& ecode, std::size_t bytes_transferred) { if(ecode) @@ -267,14 +267,14 @@ namespace client else { std::string line; - + std::istream is(&m_ReceiveBuffer); std::getline(is, line); - + std::string command, operand; std::istringstream iss(line); iss >> command >> operand; - + // process command auto& handlers = m_Owner.GetCommandHandlers(); auto it = handlers.find(command); @@ -346,7 +346,7 @@ namespace client std::ostream os(&m_SendBuffer); os << data << std::endl; } - + void BOBCommandSession::BuildStatusLine(bool currentTunnel, BOBDestination *dest, std::string &out) { // helper lambdas @@ -355,7 +355,7 @@ namespace client const auto destExists = [](const BOBDestination * const dest) { return dest != nullptr; }; const auto destReady = [](const BOBDestination * const dest) { return dest->GetLocalDestination()->IsReady(); }; const auto bool_str = [](const bool v) { return v ? "true" : "false"; }; // bool -> str - + // tunnel info const std::string nickname = currentTunnel ? m_Nickname : dest->GetNickname(); const bool quiet = currentTunnel ? m_IsQuiet : dest->GetQuiet(); @@ -367,7 +367,7 @@ namespace client const bool starting = destExists(dest) && !destReady(dest); const bool running = destExists(dest) && destReady(dest); const bool stopping = false; - + // build line std::stringstream ss; ss << "DATA " @@ -433,11 +433,11 @@ namespace client return; } } - + if (!m_CurrentDestination) { m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command - m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet); + m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet); m_Owner.AddDestination (m_Nickname, m_CurrentDestination); } if (m_InPort) @@ -613,25 +613,24 @@ namespace client } auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); if (addr->IsIdentHash ()) - { + { // we might have leaseset already auto leaseSet = localDestination->FindLeaseSet (addr->identHash); if (leaseSet) - { + { SendReplyOK (leaseSet->GetIdentity ()->ToBase64 ().c_str ()); return; } } // trying to request - auto s = shared_from_this (); - auto requstCallback = - [s](std::shared_ptr ls) - { - if (ls) - s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ()); - else - s->SendReplyError ("LeaseSet Not found"); - }; + auto s = shared_from_this (); + auto requstCallback = [s](std::shared_ptr ls) + { + if (ls) + s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ()); + else + s->SendReplyError ("LeaseSet Not found"); + }; if (addr->IsIdentHash ()) localDestination->RequestDestination (addr->identHash, requstCallback); else @@ -794,7 +793,7 @@ namespace client BOBCommandChannel::~BOBCommandChannel () { - if (IsRunning ()) + if (IsRunning ()) Stop (); for (const auto& it: m_Destinations) delete it.second; @@ -856,8 +855,7 @@ namespace client session->SendVersion (); } else - LogPrint (eLogError, "BOB: accept error: ", ecode.message ()); + LogPrint (eLogError, "BOB: accept error: ", ecode.message ()); } } } - diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index 15a0afaf..a3d58148 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -39,7 +39,7 @@ namespace client const char BOB_COMMAND_OPTION[] = "option"; const char BOB_COMMAND_STATUS[] = "status"; const char BOB_COMMAND_HELP[] = "help"; - + const char BOB_HELP_ZAP[] = "zap - Shuts down BOB."; const char BOB_HELP_QUIT[] = "quit - Quits this session with BOB."; const char BOB_HELP_START[] = "start - Starts the current nicknamed tunnel."; @@ -75,15 +75,15 @@ namespace client class BOBI2PInboundTunnel: public BOBI2PTunnel { - struct AddressReceiver - { - std::shared_ptr socket; - char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address - uint8_t * data; // pointer to buffer - size_t dataLen, bufferOffset; + struct AddressReceiver + { + std::shared_ptr socket; + char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address + uint8_t * data; // pointer to buffer + size_t dataLen, bufferOffset; - AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {}; - }; + AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {}; + }; public: @@ -115,7 +115,7 @@ namespace client { public: - BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr localDestination, bool quiet); + BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr localDestination, bool quiet); void Start (); void Stop (); @@ -162,7 +162,7 @@ namespace client std::shared_ptr m_LocalDestination; BOBI2POutboundTunnel * m_OutboundTunnel; BOBI2PInboundTunnel * m_InboundTunnel; - + std::string m_Nickname; std::string m_InHost, m_OutHost; int m_InPort, m_OutPort; @@ -215,14 +215,14 @@ namespace client void SendReplyOK (const char * msg = nullptr); void SendReplyError (const char * msg); void SendRaw (const char * data); - + void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out); private: BOBCommandChannel& m_Owner; boost::asio::ip::tcp::socket m_Socket; - boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer; + boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer; bool m_IsOpen, m_IsQuiet, m_IsActive; std::string m_Nickname, m_InHost, m_OutHost; int m_InPort, m_OutPort; @@ -269,4 +269,3 @@ namespace client } #endif - diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 51f10f5e..03c756a1 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -52,18 +52,18 @@ namespace client // SAM bool sam; i2p::config::GetOption("sam.enabled", sam); - if (sam) + if (sam) { std::string samAddr; i2p::config::GetOption("sam.address", samAddr); uint16_t samPort; i2p::config::GetOption("sam.port", samPort); - bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread); + bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread); LogPrint(eLogInfo, "Clients: starting SAM bridge at ", samAddr, ":", samPort); - try + try { m_SamBridge = new SAMBridge (samAddr, samPort, singleThread); m_SamBridge->Start (); - } - catch (std::exception& e) + } + catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in SAM bridge: ", e.what()); ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ()); @@ -76,12 +76,12 @@ namespace client std::string bobAddr; i2p::config::GetOption("bob.address", bobAddr); uint16_t bobPort; i2p::config::GetOption("bob.port", bobPort); LogPrint(eLogInfo, "Clients: starting BOB command channel at ", bobAddr, ":", bobPort); - try + try { m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort); m_BOBCommandChannel->Start (); - } - catch (std::exception& e) + } + catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in BOB bridge: ", e.what()); ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ()); @@ -95,12 +95,12 @@ namespace client std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr); uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort); LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort); - try + try { m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort); m_I2CPServer->Start (); - } - catch (std::exception& e) + } + catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what()); ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ()); @@ -407,13 +407,13 @@ namespace client template std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const { - return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value)); + return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value)); } template std::string ClientContext::GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const { - return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value); + return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value); } template @@ -423,13 +423,13 @@ namespace client { if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group)) options[it.first] = it.second.get_value (""); - } + } } - + template void ClientContext::ReadI2CPOptions (const Section& section, std::map& options) const { - options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH); + options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH); options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH); options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY); options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY); @@ -528,10 +528,10 @@ namespace client { std::string type = section.second.get (I2P_TUNNELS_SECTION_TYPE); if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT - || type == I2P_TUNNELS_SECTION_TYPE_SOCKS - || type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS - || type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY - || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) + || type == I2P_TUNNELS_SECTION_TYPE_SOCKS + || type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS + || type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY + || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { // mandatory params std::string dest; @@ -640,9 +640,9 @@ namespace client } } else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER - || type == I2P_TUNNELS_SECTION_TYPE_HTTP - || type == I2P_TUNNELS_SECTION_TYPE_IRC - || type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) + || type == I2P_TUNNELS_SECTION_TYPE_HTTP + || type == I2P_TUNNELS_SECTION_TYPE_IRC + || type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) { // mandatory params std::string host = section.second.get (I2P_SERVER_TUNNEL_HOST); @@ -699,7 +699,7 @@ namespace client continue; } - std::shared_ptr serverTunnel; + std::shared_ptr serverTunnel; if (type == I2P_TUNNELS_SECTION_TYPE_HTTP) serverTunnel = std::make_shared (name, host, port, localDestination, hostOverride, inPort, gzip); else if (type == I2P_TUNNELS_SECTION_TYPE_IRC) @@ -745,7 +745,7 @@ namespace client ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ()); } ins.first->second->isUpdated = true; - LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); + LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); } } @@ -769,9 +769,9 @@ namespace client std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); - i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper); + i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); if (httpProxyKeys.length () > 0) { @@ -786,12 +786,12 @@ namespace client else LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); } - try + try { m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, httpAddresshelper, localDestination); m_HttpProxy->Start(); - } - catch (std::exception& e) + } + catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); ThrowFatal ("Unable to start HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort, ": ", e.what ()); @@ -826,13 +826,13 @@ namespace client else LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key"); } - try + try { m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort, socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); m_SocksProxy->Start(); - } - catch (std::exception& e) + } + catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); ThrowFatal ("Unable to start SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort, ": ", e.what ()); diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 1a56575f..110f0970 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -75,10 +75,11 @@ namespace client const std::map * params = nullptr); // same as previous but on external io_service std::shared_ptr CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, const std::map * params = nullptr); - std::shared_ptr CreateNewLocalDestination (boost::asio::io_service& service, - const i2p::data::PrivateKeys& keys, bool isPublic = true, + std::shared_ptr CreateNewLocalDestination (boost::asio::io_service& service, + const i2p::data::PrivateKeys& keys, bool isPublic = true, const std::map * params = nullptr); // same as previous but on external io_service - std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params = nullptr); + std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, + const std::string & name, const std::map * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, @@ -114,7 +115,7 @@ namespace client template void VisitTunnels (Visitor v); // Visitor: (I2PService *) -> bool, true means retain - void CreateNewSharedLocalDestination (); + void CreateNewSharedLocalDestination (); void AddLocalDestination (std::shared_ptr localDestination); private: @@ -141,6 +142,7 @@ namespace client std::unique_ptr m_CleanupUDPTimer; public: + // for HTTP const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; }; const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; }; diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index af4d2913..0c915921 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -191,7 +191,7 @@ namespace proxy { res.body = ss.str(); std::string response = res.to_string(); boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(), - std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); + std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm) @@ -406,7 +406,7 @@ namespace proxy { void HTTPReqHandler::ForwardToUpstreamProxy() { LogPrint(eLogDebug, "HTTPProxy: forward to upstream"); - // build http requset + // build http request m_ClientRequestURL = m_RequestURL; LogPrint(eLogDebug, "HTTPProxy: ", m_ClientRequestURL.host); @@ -458,7 +458,7 @@ namespace proxy { if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port)); m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) { - m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamSocksProxyConnect, this, std::placeholders::_1)); + m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamSocksProxyConnect, this, std::placeholders::_1)); })); } else @@ -562,14 +562,16 @@ namespace proxy { if(m_ClientRequest.method == "CONNECT") { m_ClientResponse.code = 200; m_send_buf = m_ClientResponse.to_string(); - boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred) { + boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred) + { if(ec) GenericProxyError("socks proxy error", ec.message().c_str()); else HandoverToUpstreamProxy(); }); } else { m_send_buf = m_ClientRequestBuffer.str(); LogPrint(eLogDebug, "HTTPProxy: send ", m_send_buf.size(), " bytes"); - boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred) { + boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred) + { if(ec) GenericProxyError("failed to send request to upstream", ec.message().c_str()); else HandoverToUpstreamProxy(); }); diff --git a/libi2pd_client/HTTPProxy.h b/libi2pd_client/HTTPProxy.h index 590166e3..4504eedd 100644 --- a/libi2pd_client/HTTPProxy.h +++ b/libi2pd_client/HTTPProxy.h @@ -6,6 +6,7 @@ namespace proxy { class HTTPProxy: public i2p::client::TCPIPAcceptor { public: + HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination); HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr localDestination = nullptr) : HTTPProxy(name, address, port, "", true, localDestination) {} ; @@ -15,11 +16,13 @@ namespace proxy { bool GetHelperSupport() { return m_Addresshelper; } protected: + // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); const char* GetName() { return m_Name.c_str (); } private: + std::string m_Name; std::string m_OutproxyUrl; bool m_Addresshelper; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index f4c8a91e..2cea5098 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -24,7 +24,7 @@ namespace client { I2CPDestination::I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): - RunnableService ("I2CP"), LeaseSetDestination (GetIOService (), isPublic, ¶ms), + RunnableService ("I2CP"), LeaseSetDestination (GetIOService (), isPublic, ¶ms), m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()) { } @@ -33,26 +33,26 @@ namespace client { if (IsRunning ()) Stop (); - } - + } + void I2CPDestination::Start () { if (!IsRunning ()) - { + { LeaseSetDestination::Start (); StartIOService (); - } + } } - + void I2CPDestination::Stop () { if (IsRunning ()) - { + { LeaseSetDestination::Stop (); StopIOService (); - } - } - + } + } + void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key) { memcpy (m_EncryptionPrivateKey, key, 256); @@ -98,7 +98,7 @@ namespace client auto ls = (storeType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) ? std::make_shared (m_Identity, buf, len): std::make_shared (storeType, m_Identity, buf, len); - ls->SetExpirationTime (m_LeaseSetExpirationTime); + ls->SetExpirationTime (m_LeaseSetExpirationTime); SetLeaseSet (ls); } @@ -221,7 +221,7 @@ namespace client auto s = shared_from_this (); m_Socket->async_read_some (boost::asio::buffer (m_Header, 1), [s](const boost::system::error_code& ecode, std::size_t bytes_transferred) - { + { if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE) s->ReceiveHeader (); else @@ -247,15 +247,15 @@ namespace client if (m_PayloadLen > 0) { if (m_PayloadLen <= I2CP_MAX_MESSAGE_LENGTH) - { + { m_Payload = new uint8_t[m_PayloadLen]; ReceivePayload (); } else { - LogPrint (eLogError, "I2CP: Unexpected payload length ", m_PayloadLen); + LogPrint (eLogError, "I2CP: Unexpected payload length ", m_PayloadLen); Terminate (); - } + } } else // no following payload { @@ -323,7 +323,7 @@ namespace client memcpy (buf + I2CP_HEADER_SIZE, payload, len); boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, buf)); + std::placeholders::_1, std::placeholders::_2, buf)); } else LogPrint (eLogError, "I2CP: Can't write to the socket"); @@ -510,8 +510,8 @@ namespace client } else LogPrint(eLogError, "I2CP: short message"); - SendSessionStatusMessage (status); - } + SendSessionStatusMessage (status); + } void I2CPSession::SendSessionStatusMessage (uint8_t status) { @@ -568,12 +568,12 @@ namespace client { LogPrint (eLogError, "I2CP: invalid LeaseSet2 of type ", storeType); return; - } + } offset += ls.GetBufferLen (); // private keys int numPrivateKeys = buf[offset]; offset++; uint16_t currentKeyType = 0; - const uint8_t * currentKey = nullptr; + const uint8_t * currentKey = nullptr; for (int i = 0; i < numPrivateKeys; i++) { if (offset + 4 > len) return; @@ -586,7 +586,7 @@ namespace client currentKey = buf + offset; } offset += keyLen; - } + } // TODO: support multiple keys if (currentKey) { @@ -594,7 +594,7 @@ namespace client m_Destination->SetEncryptionType (currentKeyType); } - m_Destination->LeaseSet2Created (storeType, ls.GetBuffer (), ls.GetBufferLen ()); + m_Destination->LeaseSet2Created (storeType, ls.GetBuffer (), ls.GetBufferLen ()); } } else @@ -779,14 +779,14 @@ namespace client memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len); boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, buf)); + std::placeholders::_1, std::placeholders::_2, buf)); } I2CPServer::I2CPServer (const std::string& interface, int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, #ifdef ANDROID - I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address + I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address #else I2CPSession::proto::endpoint(boost::asio::ip::address::from_string(interface), port)) #endif @@ -823,10 +823,10 @@ namespace client m_IsRunning = false; m_Acceptor.cancel (); { - auto sessions = m_Sessions; + auto sessions = m_Sessions; for (auto& it: sessions) it.second->Stop (); - } + } m_Sessions.clear (); m_Service.stop (); if (m_Thread) @@ -899,4 +899,3 @@ namespace client } } } - diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 7f590555..08dbaa21 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -25,7 +25,7 @@ namespace client const uint8_t I2CP_PROTOCOL_BYTE = 0x2A; const size_t I2CP_SESSION_BUFFER_SIZE = 4096; const size_t I2CP_MAX_MESSAGE_LENGTH = 65535; - + const size_t I2CP_HEADER_LENGTH_OFFSET = 0; const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4; const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; @@ -69,10 +69,10 @@ namespace client I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params); ~I2CPDestination (); - + void Start (); void Stop (); - + void SetEncryptionPrivateKey (const uint8_t * key); void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; }; void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession @@ -82,7 +82,7 @@ namespace client // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const; bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; }; - // TODO: implement GetEncryptionPublicKey + // TODO: implement GetEncryptionPublicKey std::shared_ptr GetIdentity () const { return m_Identity; }; protected: @@ -220,4 +220,3 @@ namespace client } #endif - diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 31f34710..7a30decd 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -115,22 +115,24 @@ namespace client { if(m_ConnectTimeout && !m_LocalDestination->IsReady()) { - AddReadyCallback([this, streamRequestComplete, address, port] (const boost::system::error_code & ec) { + AddReadyCallback([this, streamRequestComplete, address, port] (const boost::system::error_code & ec) + { if(ec) { LogPrint(eLogWarning, "I2PService::CreateStream() ", ec.message()); streamRequestComplete(nullptr); } else - { if (address->IsIdentHash ()) + { + if (address->IsIdentHash ()) this->m_LocalDestination->CreateStream(streamRequestComplete, address->identHash, port); else - this->m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port); + this->m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port); } }); } else - { + { if (address->IsIdentHash ()) m_LocalDestination->CreateStream (streamRequestComplete, address->identHash, port); else @@ -180,7 +182,7 @@ namespace client { m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE), std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); + std::placeholders::_1, std::placeholders::_2)); } else LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket"); @@ -191,7 +193,7 @@ namespace client if (m_down) { m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE), std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); + std::placeholders::_1, std::placeholders::_2)); } else LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket"); @@ -205,8 +207,8 @@ namespace client boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), boost::asio::transfer_all(), std::bind(&TCPIPPipe::HandleUpstreamWrite, - shared_from_this(), - std::placeholders::_1)); + shared_from_this(), + std::placeholders::_1)); } else LogPrint(eLogError, "TCPIPPipe: upstream write: no socket"); @@ -220,8 +222,8 @@ namespace client boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), boost::asio::transfer_all(), std::bind(&TCPIPPipe::HandleDownstreamWrite, - shared_from_this(), - std::placeholders::_1)); + shared_from_this(), + std::placeholders::_1)); } else LogPrint(eLogError, "TCPIPPipe: downstream write: no socket"); diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index e0dfd2da..be935b93 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -18,10 +18,12 @@ namespace client class I2PService : public std::enable_shared_from_this { public: + typedef std::function ReadyCallback; public: - I2PService (std::shared_ptr localDestination = nullptr); + + I2PService (std::shared_ptr localDestination = nullptr); I2PService (i2p::data::SigningKeyType kt); virtual ~I2PService (); @@ -42,7 +44,7 @@ namespace client void AddReadyCallback(ReadyCallback cb); inline std::shared_ptr GetLocalDestination () { return m_LocalDestination; } - inline std::shared_ptr GetLocalDestination () const { return m_LocalDestination; } + inline std::shared_ptr GetLocalDestination () const { return m_LocalDestination; } inline void SetLocalDestination (std::shared_ptr dest) { if (m_LocalDestination) m_LocalDestination->Release (); @@ -59,21 +61,24 @@ namespace client virtual const char* GetName() { return "Generic I2P Service"; } private: + void TriggerReadyCheckTimer(); void HandleReadyCheckTimer(const boost::system::error_code & ec); private: + std::shared_ptr m_LocalDestination; std::unordered_set > m_Handlers; std::mutex m_HandlersMutex; std::vector > m_ReadyCallbacks; boost::asio::deadline_timer m_ReadyTimer; - bool m_ReadyTimerTriggered; + bool m_ReadyTimerTriggered; uint32_t m_ConnectTimeout; - const size_t NEVER_TIMES_OUT = 0; - + const size_t NEVER_TIMES_OUT = 0; + public: + bool isUpdated; // transient, used during reload only }; @@ -81,6 +86,7 @@ namespace client class I2PServiceHandler { public: + I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { } virtual ~I2PServiceHandler() { } //If you override this make sure you call it from the children @@ -89,6 +95,7 @@ namespace client void Terminate () { Kill (); }; protected: + // Call when terminating or handing over to avoid race conditions inline bool Kill () { return m_Dead.exchange(true); } // Call to know if the handler is dead @@ -99,6 +106,7 @@ namespace client inline I2PService * GetOwner() { return m_Service; } private: + I2PService *m_Service; std::atomic m_Dead; //To avoid cleaning up multiple times }; @@ -109,11 +117,13 @@ namespace client class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this { public: + TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); ~TCPIPPipe(); void Start(); protected: + void Terminate(); void AsyncReceiveUpstream(); void AsyncReceiveDownstream(); @@ -125,6 +135,7 @@ namespace client void DownstreamWrite(size_t len); private: + uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE]; uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE]; std::shared_ptr m_up, m_down; @@ -135,6 +146,7 @@ namespace client class TCPIPAcceptor: public I2PService { public: + TCPIPAcceptor (const std::string& address, int port, std::shared_ptr localDestination = nullptr) : I2PService(localDestination), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), @@ -149,14 +161,16 @@ namespace client //If you override this make sure you call it from the children void Stop (); - const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; + const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } protected: + virtual std::shared_ptr CreateHandler(std::shared_ptr socket) = 0; private: + void Accept(); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); boost::asio::ip::tcp::endpoint m_LocalEndpoint; diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index dc2a8811..b7a15c26 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -168,7 +168,7 @@ namespace client { m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2), + std::placeholders::_1, std::placeholders::_2), I2P_TUNNEL_CONNECTION_MAX_IDLE); } else // closed by peer @@ -257,7 +257,7 @@ namespace client if (!m_ConnectionSent && !line.compare(0, 10, "Connection")) { /* close connection, if not Connection: (U|u)pgrade (for websocket) */ - auto x = line.find("pgrade"); + auto x = line.find("pgrade"); if (x != std::string::npos && std::tolower(line[x - 1]) == 'u') m_OutHeader << line << "\r\n"; else @@ -281,7 +281,7 @@ namespace client if (endOfHeader) { if (!m_ConnectionSent) m_OutHeader << "Connection: close\r\n"; - if (!m_ProxyConnectionSent) m_OutHeader << "Proxy-Connection: close\r\n"; + if (!m_ProxyConnectionSent) m_OutHeader << "Proxy-Connection: close\r\n"; m_OutHeader << "\r\n"; // end of header m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header m_InHeader.str (""); @@ -462,7 +462,7 @@ namespace client } /* HACK: maybe we should create a caching IdentHash provider in AddressBook */ - std::shared_ptr I2PClientTunnel::GetAddress () + std::shared_ptr I2PClientTunnel::GetAddress () { if (!m_Address) { @@ -477,7 +477,7 @@ namespace client { auto address = GetAddress (); if (address) - return std::make_shared(this, address, m_DestinationPort, socket); + return std::make_shared(this, address, m_DestinationPort, socket); else return nullptr; } @@ -826,7 +826,7 @@ namespace client { LogPrint(eLogError, "UDP Tunnel: ", m_RemoteDest, " not found"); return; - } + } m_RemoteIdent = new i2p::data::IdentHash; *m_RemoteIdent = addr->identHash; LogPrint(eLogInfo, "UDP Tunnel: resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index fbe2f7bb..94f63e48 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -30,6 +30,7 @@ namespace client class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this { public: + I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr leaseSet, int port = 0); // to I2P I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, @@ -41,6 +42,7 @@ namespace client void Connect (bool isUniqueLocal = true); protected: + void Terminate (); void Receive (); @@ -55,6 +57,7 @@ namespace client std::shared_ptr GetSocket () const { return m_Socket; }; private: + uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE]; std::shared_ptr m_Socket; std::shared_ptr m_Stream; @@ -65,15 +68,18 @@ namespace client class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection { public: + I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr socket, std::shared_ptr stream): I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false), m_ConnectionSent (false), m_ProxyConnectionSent (false) {}; protected: + void Write (const uint8_t * buf, size_t len); private: + std::stringstream m_InHeader, m_OutHeader; bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent; }; @@ -81,14 +87,17 @@ namespace client class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection { public: + I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& host); protected: + void Write (const uint8_t * buf, size_t len); private: + std::string m_Host; std::stringstream m_InHeader, m_OutHeader; bool m_HeaderSent; @@ -98,14 +107,17 @@ namespace client class I2PTunnelConnectionIRC: public I2PTunnelConnection { public: + I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); protected: + void Write (const uint8_t * buf, size_t len); private: + std::shared_ptr m_From; std::stringstream m_OutPacket, m_InPacket; bool m_NeedsWebIrc; @@ -116,10 +128,12 @@ namespace client class I2PClientTunnel: public TCPIPAcceptor { protected: + // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); public: + I2PClientTunnel (const std::string& name, const std::string& destination, const std::string& address, int port, std::shared_ptr localDestination, int destinationPort = 0); ~I2PClientTunnel () {} @@ -130,9 +144,11 @@ namespace client const char* GetName() { return m_Name.c_str (); } private: + std::shared_ptr GetAddress (); private: + std::string m_Name, m_Destination; std::shared_ptr m_Address; int m_DestinationPort; @@ -160,9 +176,9 @@ namespace client uint8_t m_Buffer[I2P_UDP_MAX_MTU]; UDPSession(boost::asio::ip::udp::endpoint localEndpoint, - const std::shared_ptr & localDestination, - boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident, - uint16_t ourPort, uint16_t theirPort); + const std::shared_ptr & localDestination, + boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident, + uint16_t ourPort, uint16_t theirPort); void HandleReceived(const boost::system::error_code & ecode, std::size_t len); void Receive(); }; @@ -195,6 +211,7 @@ namespace client class I2PUDPServerTunnel { public: + I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::address localAddress, @@ -210,10 +227,12 @@ namespace client void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; } private: + void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); private: + bool m_IsUniqueLocal; const std::string m_Name; boost::asio::ip::address m_LocalAddress; @@ -226,6 +245,7 @@ namespace client class I2PUDPClientTunnel { public: + I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, bool gzip); @@ -240,6 +260,7 @@ namespace client void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); private: + typedef std::pair UDPConvo; void RecvFromLocal(); void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); @@ -263,6 +284,7 @@ namespace client class I2PServerTunnel: public I2PService { public: + I2PServerTunnel (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, int inport = 0, bool gzip = true); @@ -282,6 +304,7 @@ namespace client const char* GetName() { return m_Name.c_str (); } private: + void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, std::shared_ptr resolver); @@ -290,6 +313,7 @@ namespace client virtual std::shared_ptr CreateI2PConnection (std::shared_ptr stream); private: + bool m_IsUniqueLocal; std::string m_Name, m_Address; int m_Port; @@ -302,28 +326,34 @@ namespace client class I2PServerTunnelHTTP: public I2PServerTunnel { public: + I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, const std::string& host, int inport = 0, bool gzip = true); private: + std::shared_ptr CreateI2PConnection (std::shared_ptr stream); private: + std::string m_Host; }; class I2PServerTunnelIRC: public I2PServerTunnel { public: + I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, const std::string& webircpass, int inport = 0, bool gzip = true); private: + std::shared_ptr CreateI2PConnection (std::shared_ptr stream); private: + std::string m_WebircPass; }; } diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index 5cec178f..a4c82504 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -14,10 +14,10 @@ namespace client void MatchedTunnelDestination::ResolveCurrentLeaseSet() { - auto addr = i2p::client::context.GetAddressBook().GetAddress (m_RemoteName); + auto addr = i2p::client::context.GetAddressBook().GetAddress (m_RemoteName); if(addr && addr->IsIdentHash ()) { - m_RemoteIdent = addr->identHash; + m_RemoteIdent = addr->identHash; auto ls = FindLeaseSet(m_RemoteIdent); if(ls) HandleFoundCurrentLeaseSet(ls); @@ -39,7 +39,7 @@ namespace client { m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1)); m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) { - if(!ec) ResolveCurrentLeaseSet(); + if(!ec) ResolveCurrentLeaseSet(); }); } } @@ -50,7 +50,7 @@ namespace client ClientDestination::Start(); m_ResolveTimer = std::make_shared(GetService()); GetTunnelPool()->SetCustomPeerSelector(this); - ResolveCurrentLeaseSet(); + ResolveCurrentLeaseSet(); } void MatchedTunnelDestination::Stop() diff --git a/libi2pd_client/MatchedDestination.h b/libi2pd_client/MatchedDestination.h index 9d61799a..53cae203 100644 --- a/libi2pd_client/MatchedDestination.h +++ b/libi2pd_client/MatchedDestination.h @@ -8,26 +8,30 @@ namespace i2p namespace client { /** - client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination + * client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination */ class MatchedTunnelDestination : public RunnableClientDestination, public i2p::tunnel::ITunnelPeerSelector { - public: - MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName, const std::map * params = nullptr); - void Start(); - void Stop(); - - bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound); - - private: - void ResolveCurrentLeaseSet(); - void HandleFoundCurrentLeaseSet(std::shared_ptr ls); - - private: - std::string m_RemoteName; - i2p::data::IdentHash m_RemoteIdent; - std::shared_ptr m_RemoteLeaseSet; - std::shared_ptr m_ResolveTimer; + public: + + MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName, + const std::map * params = nullptr); + void Start(); + void Stop(); + + bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound); + + private: + + void ResolveCurrentLeaseSet(); + void HandleFoundCurrentLeaseSet(std::shared_ptr ls); + + private: + + std::string m_RemoteName; + i2p::data::IdentHash m_RemoteIdent; + std::shared_ptr m_RemoteLeaseSet; + std::shared_ptr m_ResolveTimer; }; } } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index d0942221..086cbe69 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -17,7 +17,7 @@ namespace client { SAMSocket::SAMSocket (SAMBridge& owner): m_Owner (owner), m_Socket(owner.GetService()), m_Timer (m_Owner.GetService ()), - m_BufferOffset (0), + m_BufferOffset (0), m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), m_IsAccepting (false), m_Stream (nullptr) { @@ -26,7 +26,7 @@ namespace client SAMSocket::~SAMSocket () { m_Stream = nullptr; - } + } void SAMSocket::Terminate (const char* reason) { @@ -54,8 +54,7 @@ namespace client } break; } - default: - ; + default: ; } m_SocketType = eSAMSocketTypeTerminated; if (m_Socket.is_open ()) @@ -68,7 +67,7 @@ namespace client } void SAMSocket::ReceiveHandshake () - { + { m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), std::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -152,7 +151,7 @@ namespace client size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ()); #endif boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (), - std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (), + std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } else @@ -170,7 +169,7 @@ namespace client { return id == m_ID; } - + void SAMSocket::HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) @@ -350,7 +349,7 @@ namespace client } std::shared_ptr forward = nullptr; - if ((type == eSAMSessionTypeDatagram || type == eSAMSessionTypeRaw) && + if ((type == eSAMSessionTypeDatagram || type == eSAMSessionTypeRaw) && params.find(SAM_VALUE_HOST) != params.end() && params.find(SAM_VALUE_PORT) != params.end()) { // udp forward selected @@ -372,7 +371,7 @@ namespace client } forward = std::make_shared(addr, port); } - + //ensure we actually received a destination if (destination.empty()) { @@ -381,7 +380,7 @@ namespace client } if (destination != SAM_VALUE_TRANSIENT) - { + { //ensure it's a base64 string i2p::data::PrivateKeys keys; if (!keys.FromBase64(destination)) @@ -389,7 +388,7 @@ namespace client SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true); return; } - } + } // create destination auto session = m_Owner.CreateSession (id, type, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms); @@ -542,7 +541,7 @@ namespace client m_SocketType = eSAMSocketTypeAcceptor; if (!session->localDestination->IsAcceptingStreams ()) { - m_IsAccepting = true; + m_IsAccepting = true; session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); @@ -567,7 +566,7 @@ namespace client { i2p::data::IdentityEx dest; dest.FromBase64 (params[SAM_PARAM_DESTINATION]); - if (session->Type == eSAMSessionTypeDatagram) + if (session->Type == eSAMSessionTypeDatagram) d->SendDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ()); else // raw d->SendRawDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ()); @@ -598,20 +597,20 @@ namespace client if (it != params.end ()) { if (!m_Owner.ResolveSignatureType (it->second, signatureType)) - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); } it = params.find (SAM_PARAM_CRYPTO_TYPE); if (it != params.end ()) { try - { + { cryptoType = std::stoi(it->second); } - catch (const std::exception& ex) + catch (const std::exception& ex) { - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ()); - } - } + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ()); + } + } auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType); #ifdef _MSC_VER size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, @@ -647,12 +646,12 @@ namespace client else dest->RequestDestination (addr->identHash, std::bind (&SAMSocket::HandleNamingLookupLeaseSetRequestComplete, - shared_from_this (), std::placeholders::_1, name)); + shared_from_this (), std::placeholders::_1, name)); } else dest->RequestDestinationWithEncryptedLeaseSet (addr->blindedPublicKey, std::bind (&SAMSocket::HandleNamingLookupLeaseSetRequestComplete, - shared_from_this (), std::placeholders::_1, name)); + shared_from_this (), std::placeholders::_1, name)); } else { @@ -762,7 +761,7 @@ namespace client if (m_Stream) { if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || - m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular + m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular { m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE), std::bind (&SAMSocket::HandleI2PReceive, shared_from_this(), @@ -800,7 +799,7 @@ namespace client { delete [] buff; } - + void SAMSocket::WriteI2PData(size_t sz) { boost::asio::async_write ( @@ -809,7 +808,7 @@ namespace client boost::asio::transfer_all(), std::bind(&SAMSocket::HandleWriteI2PData, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - + void SAMSocket::HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) @@ -955,7 +954,7 @@ namespace client auto ep = session->UDPEndpoint; if (ep) // udp forward enabled - m_Owner.SendTo(buf, len, ep); + m_Owner.SendTo(buf, len, ep); else { #ifdef _MSC_VER @@ -978,7 +977,7 @@ namespace client { m_Owner.GetService ().post (std::bind( !ec ? &SAMSocket::Receive : &SAMSocket::TerminateClose, shared_from_this())); } - + SAMSession::SAMSession (SAMBridge & parent, const std::string & id, SAMSessionType type, std::shared_ptr dest): m_Bridge(parent), localDestination (dest), @@ -986,7 +985,7 @@ namespace client Name(id), Type (type) { } - + SAMSession::~SAMSession () { i2p::client::context.DeleteLocalDestination (localDestination); @@ -1001,7 +1000,7 @@ namespace client } SAMBridge::SAMBridge (const std::string& address, int port, bool singleThread): - RunnableService ("SAM"), m_IsSingleThread (singleThread), + RunnableService ("SAM"), m_IsSingleThread (singleThread), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)), m_DatagramEndpoint (boost::asio::ip::address::from_string(address), port-1), m_DatagramSocket (GetIOService (), m_DatagramEndpoint), m_SignatureTypes @@ -1063,7 +1062,7 @@ namespace client std::unique_lock lock(m_OpenSocketsMutex); m_OpenSockets.remove_if([socket](const std::shared_ptr & item) -> bool { return item == socket; }); } - + void SAMBridge::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket) { if (!ecode) @@ -1089,7 +1088,7 @@ namespace client Accept (); } - std::shared_ptr SAMBridge::CreateSession (const std::string& id, SAMSessionType type, + std::shared_ptr SAMBridge::CreateSession (const std::string& id, SAMSessionType type, const std::string& destination, const std::map * params) { std::shared_ptr localDestination = nullptr; @@ -1097,7 +1096,7 @@ namespace client { i2p::data::PrivateKeys keys; if (!keys.FromBase64 (destination)) return nullptr; - localDestination = m_IsSingleThread ? + localDestination = m_IsSingleThread ? i2p::client::context.CreateNewLocalDestination (GetIOService (), keys, true, params) : i2p::client::context.CreateNewLocalDestination (keys, true, params); } @@ -1110,24 +1109,24 @@ namespace client { auto it = params->find (SAM_PARAM_SIGNATURE_TYPE); if (it != params->end ()) - { + { if (!ResolveSignatureType (it->second, signatureType)) - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); - } + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); + } it = params->find (SAM_PARAM_CRYPTO_TYPE); if (it != params->end ()) - { + { try - { + { cryptoType = std::stoi(it->second); } - catch (const std::exception& ex) + catch (const std::exception& ex) { - LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ()); - } - } + LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ()); + } + } } - localDestination = m_IsSingleThread ? + localDestination = m_IsSingleThread ? i2p::client::context.CreateNewLocalDestination (GetIOService (), true, signatureType, cryptoType, params) : i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, params); } @@ -1165,11 +1164,11 @@ namespace client { auto timer = std::make_shared(GetService ()); timer->expires_from_now (boost::posix_time::seconds(5)); // postpone destination clean for 5 seconds - timer->async_wait ([timer, session](const boost::system::error_code& ecode) + timer->async_wait ([timer, session](const boost::system::error_code& ecode) { // session's destructor is called here }); - } + } } } @@ -1193,7 +1192,7 @@ namespace client } return list; } - + void SAMBridge::SendTo(const uint8_t * buf, size_t len, std::shared_ptr remote) { if(remote) @@ -1261,7 +1260,7 @@ namespace client bool SAMBridge::ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const { try - { + { type = std::stoi (name); } catch (const std::invalid_argument& ex) @@ -1273,12 +1272,12 @@ namespace client else return false; } - catch (const std::exception& ex) + catch (const std::exception& ex) { - return false; - } - // name has been resolved - return true; + return false; + } + // name has been resolved + return true; } } } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 5a447c06..51a8bc57 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -87,7 +87,7 @@ namespace client typedef boost::asio::ip::tcp::socket Socket_t; SAMSocket (SAMBridge& owner); - ~SAMSocket (); + ~SAMSocket (); Socket_t& GetSocket () { return m_Socket; }; void ReceiveHandshake (); @@ -97,10 +97,11 @@ namespace client void Terminate (const char* reason); bool IsSession(const std::string & id) const; - - private: + + private: + void TerminateClose() { Terminate(nullptr); } - + void HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -137,7 +138,7 @@ namespace client void HandleWriteI2PDataImmediate(const boost::system::error_code & ec, uint8_t * buff); void HandleStreamSend(const boost::system::error_code & ec); - + private: SAMBridge& m_Owner; @@ -186,7 +187,7 @@ namespace client void Stop (); boost::asio::io_service& GetService () { return GetIOService (); }; - std::shared_ptr CreateSession (const std::string& id, SAMSessionType type, const std::string& destination, // empty string means transient + std::shared_ptr CreateSession (const std::string& id, SAMSessionType type, const std::string& destination, // empty string means transient const std::map * params); void CloseSession (const std::string& id); std::shared_ptr FindSession (const std::string& id) const; @@ -197,8 +198,8 @@ namespace client void SendTo(const uint8_t * buf, size_t len, std::shared_ptr remote); void RemoveSocket(const std::shared_ptr & socket); - - bool ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const; + + bool ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const; private: diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index a70ac2b7..272ac178 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -41,6 +41,7 @@ namespace proxy class SOCKSHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { private: + enum state { GET_SOCKSV, @@ -137,7 +138,7 @@ namespace proxy void HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr); void HandleUpstreamResolved(const boost::system::error_code & ecode, - boost::asio::ip::tcp::resolver::iterator itr); + boost::asio::ip::tcp::resolver::iterator itr); boost::asio::ip::tcp::resolver m_proxy_resolver; uint8_t m_sock_buff[socks_buffer_size]; @@ -165,6 +166,7 @@ namespace proxy const uint16_t m_UpstreamProxyPort; public: + SOCKSHandler(SOCKSServer * parent, std::shared_ptr sock, const std::string & upstreamAddr, const uint16_t upstreamPort, const bool useUpstream) : I2PServiceHandler(parent), m_proxy_resolver(parent->GetService()), @@ -652,8 +654,7 @@ namespace proxy LogPrint(eLogDebug, "SOCKS: async upstream sock read"); if (m_upstreamSock) { m_upstreamSock->async_read_some(boost::asio::buffer(m_upstream_response, SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE), - std::bind(&SOCKSHandler::HandleUpstreamSockRecv, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); + std::bind(&SOCKSHandler::HandleUpstreamSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else { LogPrint(eLogError, "SOCKS: no upstream socket for read"); SocksRequestFailed(SOCKS5_GEN_FAIL); @@ -773,7 +774,7 @@ namespace proxy SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort, std::shared_ptr localDestination) : - TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) + TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) { m_UseUpstreamProxy = false; if (outAddress.length() > 0 && outEnable) diff --git a/libi2pd_client/SOCKS.h b/libi2pd_client/SOCKS.h index 87f08de4..fc43415a 100644 --- a/libi2pd_client/SOCKS.h +++ b/libi2pd_client/SOCKS.h @@ -14,6 +14,7 @@ namespace proxy class SOCKSServer: public i2p::client::TCPIPAcceptor { public: + SOCKSServer(const std::string& name, const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort, std::shared_ptr localDestination = nullptr); ~SOCKSServer() {}; @@ -21,6 +22,7 @@ namespace proxy void SetUpstreamProxy(const std::string & addr, const uint16_t port); protected: + // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); const char* GetName() { return m_Name.c_str (); }