From 4c687036c49b0668890201519d2fd4a181517f85 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 25 Aug 2018 14:01:57 -0400 Subject: [PATCH 01/33] enable socks outproxy --- libi2pd_client/ClientContext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index fb8fff97..e5acb97b 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -502,7 +502,8 @@ namespace client if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS) { // socks proxy - clientTunnel = new i2p::proxy::SOCKSProxy(name, address, port, false, "", destinationPort, localDestination); + std::string outproxy = section.second.get("outproxy", ""); + clientTunnel = new i2p::proxy::SOCKSProxy(name, address, port, !outproxy.emtpy(), outproxy, destinationPort, localDestination); clientEndpoint = ((i2p::proxy::SOCKSProxy*)clientTunnel)->GetLocalEndpoint (); } else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY) From 23ae220aa7d6d329ccb90d7fde63f0824a877d04 Mon Sep 17 00:00:00 2001 From: asokolov Date: Wed, 7 Nov 2018 18:07:05 +0300 Subject: [PATCH 02/33] add webroot setting --- daemon/HTTPServer.cpp | 77 +++++++++++++++++++++++-------------------- libi2pd/Config.cpp | 1 + 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index b4c3f79b..0fbd2756 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -155,6 +155,8 @@ namespace http { static void ShowPageHead (std::stringstream& s) { + std::string webroot; + i2p::config::GetOption("http.webroot", webroot); s << "\r\n" "\r\n" /* TODO: Add support for locale */ @@ -173,16 +175,16 @@ namespace http { "
i2pd webconsole
\r\n" "
\r\n" "
\r\n" - " Main page
\r\n
\r\n" - " Router commands
\r\n" - " Local destinations
\r\n" - " LeaseSets
\r\n" - " Tunnels
\r\n" - " Transit tunnels
\r\n" - " Transports
\r\n" - " I2P tunnels
\r\n"; + " Main page
\r\n
\r\n" + " Router commands
\r\n" + " Local destinations
\r\n" + " LeaseSets
\r\n" + " Tunnels
\r\n" + " Transit tunnels
\r\n" + " Transports
\r\n" + " I2P tunnels
\r\n"; if (i2p::client::context.GetSAMBridge ()) - s << " SAM sessions
\r\n"; + s << " SAM sessions
\r\n"; s << "
\r\n" "
"; @@ -321,11 +323,12 @@ namespace http { void ShowLocalDestinations (std::stringstream& s) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); s << "Local Destinations:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetDestinations ()) { auto ident = it.second->GetIdentHash (); - s << ""; + s << ""; s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; } @@ -340,7 +343,7 @@ namespace http { { auto ident = dest->GetIdentHash (); auto& name = dest->GetNickname (); - s << "[ "; + s << "[ "; s << name << " ] ⇔ " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"
\r\n" << std::endl; } } @@ -510,33 +513,34 @@ namespace http { static void ShowCommands (std::stringstream& s, uint32_t token) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); /* commands */ s << "Router Commands
\r\n
\r\n"; - s << " Run peer test
\r\n"; + s << " Run peer test
\r\n"; //s << " Reload config
\r\n"; if (i2p::context.AcceptsTunnels ()) - s << " Decline transit tunnels
\r\n"; + s << " Decline transit tunnels
\r\n"; else - s << " Accept transit tunnels
\r\n"; + s << " Accept transit tunnels
\r\n"; #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) if (Daemon.gracefulShutdownInterval) - s << " Cancel graceful shutdown
"; + s << " Cancel graceful shutdown
"; else - s << " Start graceful shutdown
\r\n"; + s << " Start graceful shutdown
\r\n"; #elif defined(WIN32_APP) if (i2p::util::DaemonWin32::Instance().isGraceful) - s << " Cancel graceful shutdown
"; + s << " Cancel graceful shutdown
"; else - s << " Graceful shutdown
\r\n"; + s << " Graceful shutdown
\r\n"; #endif - s << " Force shutdown
\r\n"; + s << " Force shutdown
\r\n"; s << "
\r\nLogging level
\r\n"; - s << " [none] "; - s << " [error] "; - s << " [warn] "; - s << " [info] "; - s << " [debug]
\r\n"; + s << " [none] "; + s << " [error] "; + s << " [warn] "; + s << " [info] "; + s << " [debug]
\r\n"; } void ShowTransitTunnels (std::stringstream& s) @@ -653,6 +657,7 @@ namespace http { void ShowSAMSessions (std::stringstream& s) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { ShowError(s, "SAM disabled"); @@ -662,13 +667,14 @@ namespace http { for (auto& it: sam->GetSessions ()) { auto& name = it.second->localDestination->GetNickname (); - s << ""; + s << ""; s << name << " (" << it.first << ")
\r\n" << std::endl; } } static void ShowSAMSession (std::stringstream& s, const std::string& id) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); s << "SAM Session:
\r\n
\r\n"; auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { @@ -681,7 +687,7 @@ namespace http { return; } auto& ident = session->localDestination->GetIdentHash(); - s << ""; + s << ""; s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n"; s << "
\r\n"; s << "Streams:
\r\n"; @@ -701,11 +707,12 @@ namespace http { void ShowI2PTunnels (std::stringstream& s) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); s << "Client Tunnels:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetClientTunnels ()) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -714,7 +721,7 @@ namespace http { if (httpProxy) { auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << "HTTP Proxy" << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -723,7 +730,7 @@ namespace http { if (socksProxy) { auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << "SOCKS Proxy" << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -734,7 +741,7 @@ namespace http { for (auto& it: serverTunnels) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇒ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << ":" << it.second->GetLocalPort (); @@ -748,7 +755,7 @@ namespace http { for (auto& it: clientForwards) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -761,7 +768,7 @@ namespace http { for (auto& it: serverForwards) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -1026,9 +1033,9 @@ namespace http { return; } s << "SUCCESS: Command accepted

\r\n"; - s << "Back to commands list
\r\n"; - s << "

You will be redirected in 5 seconds"; - res.add_header("Refresh", "5; url=/?page=commands"); + s << "Back to commands list
\r\n"; + // s << "

You will be redirected in 5 seconds"; + // res.add_header("Refresh", "5; url=/?page=commands"); } void HTTPConnection::SendReply (HTTPRes& reply, std::string& content) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 9eaaf068..abeba94f 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -86,6 +86,7 @@ namespace config { ("http.pass", value()->default_value(""), "Password for basic auth (default: random, see logs)") ("http.strictheaders", value()->default_value(true), "Enable strict host checking on WebUI") ("http.hostname", value()->default_value("localhost"), "Expected hostname for WebUI") + ("http.webroot", value()->default_value("/"), "WebUI root path (default: / )") ; options_description httpproxy("HTTP Proxy options"); From a12a7e73f93f1c240b0a2b71c78e398479486cd8 Mon Sep 17 00:00:00 2001 From: asokolov Date: Fri, 9 Nov 2018 16:13:56 +0300 Subject: [PATCH 03/33] redirect with webroot --- daemon/HTTPServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 0fbd2756..d8dc8719 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1034,8 +1034,8 @@ namespace http { } s << "SUCCESS: Command accepted

\r\n"; s << "Back to commands list
\r\n"; - // s << "

You will be redirected in 5 seconds"; - // res.add_header("Refresh", "5; url=/?page=commands"); + s << "

You will be redirected in 5 seconds"; + res.add_header("Refresh", std::string("5; url=" + url.path + "?page=commands").c_str()); } void HTTPConnection::SendReply (HTTPRes& reply, std::string& content) From c994950aafbb41d1f8bb0534f403484a963b3217 Mon Sep 17 00:00:00 2001 From: asokolov Date: Fri, 9 Nov 2018 17:42:04 +0300 Subject: [PATCH 04/33] default webroot in config, webroot in automatic redirect instead of request path --- contrib/i2pd.conf | 2 ++ daemon/HTTPServer.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 40949cc1..7bd2c90f 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -93,6 +93,8 @@ ipv6 = false ## Address and port service will listen on address = 127.0.0.1 port = 7070 +## Path to web console, default "/" +# webroot = / ## Uncomment following lines to enable Web Console authentication # auth = true # user = i2pd diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index d8dc8719..ccf2640c 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1032,10 +1032,12 @@ namespace http { ShowError(s, "Unknown command: " + cmd); return; } + std::string webroot; i2p::config::GetOption("http.webroot", webroot); + std::string redirect = "5; url=" + webroot + "?page=commands"; s << "SUCCESS: Command accepted

\r\n"; - s << "Back to commands list
\r\n"; + s << "Back to commands list
\r\n"; s << "

You will be redirected in 5 seconds"; - res.add_header("Refresh", std::string("5; url=" + url.path + "?page=commands").c_str()); + res.add_header("Refresh", redirect.c_str()); } void HTTPConnection::SendReply (HTTPRes& reply, std::string& content) From d9887ec3700742295bef21b966dee948ac752421 Mon Sep 17 00:00:00 2001 From: l-n-s Date: Fri, 9 Nov 2018 14:05:10 -0500 Subject: [PATCH 05/33] bump i2pd version in appdata manifest --- qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml index 16ae602a..f6b98ed7 100644 --- a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml +++ b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml @@ -35,6 +35,7 @@ + From 51352a6819439ecf846022ebd770fac56df72bde Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 10 Nov 2018 03:25:51 +0000 Subject: [PATCH 06/33] update debian/rpm tunnels.d storing + testing rpm changes: manpage and configs store --- contrib/rpm/i2pd-git.spec | 32 ++++++++++++++++---------------- contrib/tunnels.d/IRC-Irc2P.conf | 2 +- contrib/tunnels.d/README | 5 ++++- debian/docs | 1 + debian/i2pd.dirs | 1 - debian/i2pd.install | 2 +- debian/i2pd.links | 2 +- 7 files changed, 24 insertions(+), 21 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 984ccffa..9d068c11 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -56,18 +56,18 @@ make %{?_smp_mflags} %install cd build chrpath -d i2pd -install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd -install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf -install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf -install -d -m 755 %{buildroot}%{_datadir}/i2pd -install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d -%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates -%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d -install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service -install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd -install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.d/README %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d/README +%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service +%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1 +%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd +%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +%{__install} -d -m 755 %{buildroot}%{_datadir}/%{name} +%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/%{name}/certificates ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates -ln -s %{_datadir}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d %pre @@ -90,14 +90,14 @@ getent passwd i2pd >/dev/null || \ %files -%doc LICENSE README.md +%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d %{_sbindir}/i2pd -%{_datadir}/i2pd/certificates %config(noreplace) %{_sysconfdir}/i2pd/* -%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/* -/%{_unitdir}/i2pd.service -%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%{_unitdir}/i2pd.service +%{_mandir}/man1/i2pd.1* %dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd +%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%{_datadir}/%{name}/certificates %{_sharedstatedir}/i2pd/certificates diff --git a/contrib/tunnels.d/IRC-Irc2P.conf b/contrib/tunnels.d/IRC-Irc2P.conf index 7255f9d5..97da71dc 100644 --- a/contrib/tunnels.d/IRC-Irc2P.conf +++ b/contrib/tunnels.d/IRC-Irc2P.conf @@ -4,4 +4,4 @@ #port = 6668 #destination = irc.postman.i2p #destinationport = 6667 -#keys = irc-keys.dat \ No newline at end of file +#keys = irc-keys.dat diff --git a/contrib/tunnels.d/README b/contrib/tunnels.d/README index 3ac3c1a3..7b07c4be 100644 --- a/contrib/tunnels.d/README +++ b/contrib/tunnels.d/README @@ -1 +1,4 @@ -In that directory you can store separated config files for every tunnel. \ No newline at end of file +# In that directory you can store separated config files for every tunnel. +# Please read documentation for more info. +# +# You can find examples in /usr/share/doc/i2pd/tunnels.d directory diff --git a/debian/docs b/debian/docs index b67deb18..dfa6f572 100644 --- a/debian/docs +++ b/debian/docs @@ -2,3 +2,4 @@ README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf +contrib/tunnels.d diff --git a/debian/i2pd.dirs b/debian/i2pd.dirs index 736e23bd..3b643352 100644 --- a/debian/i2pd.dirs +++ b/debian/i2pd.dirs @@ -1,3 +1,2 @@ etc/i2pd -etc/i2pd/tunnels.conf.d var/lib/i2pd diff --git a/debian/i2pd.install b/debian/i2pd.install index cae69c0e..d20b2c17 100644 --- a/debian/i2pd.install +++ b/debian/i2pd.install @@ -3,5 +3,5 @@ contrib/i2pd.conf etc/i2pd/ contrib/tunnels.conf etc/i2pd/ contrib/subscriptions.txt etc/i2pd/ contrib/certificates/ usr/share/i2pd/ -contrib/tunnels.d/ etc/i2pd/tunnels.conf.d +contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/ contrib/apparmor/usr.sbin.i2pd etc/apparmor.d diff --git a/debian/i2pd.links b/debian/i2pd.links index 083bc6ca..a149967f 100644 --- a/debian/i2pd.links +++ b/debian/i2pd.links @@ -1,5 +1,5 @@ etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt -etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.conf.d +etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d usr/share/i2pd/certificates var/lib/i2pd/certificates From 42b556574f7ebc4b39aa8acb9c6649a7f49ccd28 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 11 Nov 2018 22:28:34 +0300 Subject: [PATCH 07/33] add fedora copr mageia support --- contrib/rpm/i2pd-git.spec | 3 +++ contrib/rpm/i2pd.spec | 3 +++ 2 files changed, 6 insertions(+) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 9d068c11..7888878d 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -55,6 +55,9 @@ make %{?_smp_mflags} %install cd build +%if 0%{?mageia} +cd build +%endif chrpath -d i2pd %{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd %{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5daeef2c..f7577f0e 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -53,6 +53,9 @@ make %{?_smp_mflags} %install cd build +%if 0%{?mageia} +cd build +%endif chrpath -d i2pd install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf From 85394f2438576ac43f4fe359c4778c0e586c29d0 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Nov 2018 11:06:53 -0500 Subject: [PATCH 08/33] NTP time sync --- daemon/Daemon.cpp | 4 +++ libi2pd/Config.cpp | 13 +++++++++ libi2pd/Timestamp.cpp | 61 ++++++++++++++++++++++++++++++++++++++++--- libi2pd/Timestamp.h | 21 +++------------ 4 files changed, 78 insertions(+), 21 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 0b88e983..b1e694fd 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -23,6 +23,7 @@ #include "ClientContext.h" #include "Crypto.h" #include "UPnP.h" +#include "Timestamp.h" #include "util.h" #include "Event.h" @@ -282,6 +283,9 @@ namespace i2p d.UPnP->Start (); } + bool nettime; i2p::config::GetOption("nettime.enabled", nettime); + if (nettime) i2p::util::RequestNTPTimeSync (); + bool ntcp; i2p::config::GetOption("ntcp", ntcp); bool ssu; i2p::config::GetOption("ssu", ssu); LogPrint(eLogInfo, "Daemon: starting Transports"); diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 15777968..c1fd006c 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -241,6 +241,18 @@ namespace config { ("ntcp2.port", value()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)") ; + options_description nettime("Time sync options"); + nettime.add_options() + ("nettime.enabled", value()->default_value(false), "Disable time sync (default: disabled)") + ("nettime.ntpservers", value()->default_value( + "0.ntp.pool.org," + "1.ntp.pool.org," + "2.ntp.pool.org," + "3.ntp.pool.org" + ), "Comma separated list of NTCP servers") + ("nettime.ntpsyncinterval", value()->default_value(72), "NTP sync interval in hours (default: 72)") + ; + m_OptionsDesc .add(general) .add(limits) @@ -259,6 +271,7 @@ namespace config { .add(websocket) .add(exploratory) .add(ntcp2) + .add(nettime) ; } diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 9e9b4e63..18314745 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -1,6 +1,12 @@ #include #include +#include +#include +#include +#include #include +#include +#include "Config.h" #include "Log.h" #include "I2PEndian.h" #include "Timestamp.h" @@ -15,10 +21,30 @@ namespace i2p { namespace util { + static uint64_t GetLocalMillisecondsSinceEpoch () + { + return std::chrono::duration_cast( + 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 (); + } + + static uint64_t GetLocalSecondsSinceEpoch () + { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count (); + } + + static int64_t g_TimeOffset = 0; // in seconds - void SyncTimeWithNTP (const std::string& address) + static void SyncTimeWithNTP (const std::string& 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; @@ -48,19 +74,46 @@ namespace util } catch (std::exception& e) { - LogPrint (eLogError, "NTP error: ", e.what ()); + LogPrint (eLogError, "Timestamp: NTP error: ", e.what ()); } if (len >= 8) { - auto ourTs = GetSecondsSinceEpoch (); + auto ourTs = GetLocalSecondsSinceEpoch (); uint32_t ts = bufbe32toh (buf + 32); if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900 g_TimeOffset = ts - ourTs; - LogPrint (eLogInfo, address, " time offset from system time is ", g_TimeOffset, " seconds"); + LogPrint (eLogInfo, address, "Timestamp: time offset from system time is ", g_TimeOffset, " seconds"); } } } } + + void RequestNTPTimeSync () + { + std::string ntpservers; i2p::config::GetOption("nettime.ntpservers", ntpservers); + if (ntpservers.length () > 0) + { + std::vector ntpList; + boost::split (ntpList, ntpservers, boost::is_any_of(","), boost::token_compress_on); + if (ntpList.size () > 0) + std::async (std::launch::async, SyncTimeWithNTP, ntpList[rand () % ntpList.size ()]); + } + } + + uint64_t GetMillisecondsSinceEpoch () + { + return GetLocalMillisecondsSinceEpoch () + g_TimeOffset*1000; + } + + uint32_t GetHoursSinceEpoch () + { + return GetLocalHoursSinceEpoch () + g_TimeOffset/3600; + } + + uint64_t GetSecondsSinceEpoch () + { + return GetLocalSecondsSinceEpoch () + g_TimeOffset; + } } } diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index cddc6518..d7f200b9 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -2,29 +2,16 @@ #define TIMESTAMP_H__ #include -#include namespace i2p { namespace util { - inline uint64_t GetMillisecondsSinceEpoch () - { - return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); - } + uint64_t GetMillisecondsSinceEpoch (); + uint32_t GetHoursSinceEpoch (); + uint64_t GetSecondsSinceEpoch (); - inline uint32_t GetHoursSinceEpoch () - { - return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); - } - - inline uint64_t GetSecondsSinceEpoch () - { - return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); - } + void RequestNTPTimeSync (); } } From 8335bdf3d44ae7e7bd312f8bcc73774428539243 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Nov 2018 11:47:50 -0500 Subject: [PATCH 09/33] correct ntp servers --- libi2pd/Config.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index c1fd006c..3251886b 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -245,10 +245,10 @@ namespace config { nettime.add_options() ("nettime.enabled", value()->default_value(false), "Disable time sync (default: disabled)") ("nettime.ntpservers", value()->default_value( - "0.ntp.pool.org," - "1.ntp.pool.org," - "2.ntp.pool.org," - "3.ntp.pool.org" + "0.pool.ntp.org," + "1.pool.ntp.org," + "2.pool.ntp.org," + "3.pool.ntp.org" ), "Comma separated list of NTCP servers") ("nettime.ntpsyncinterval", value()->default_value(72), "NTP sync interval in hours (default: 72)") ; From 588d64a30b0a09cdb8a378338c25f58a7c07639b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Nov 2018 12:27:11 -0500 Subject: [PATCH 10/33] more NTP logging --- libi2pd/Timestamp.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 18314745..939e7f91 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -82,10 +82,14 @@ namespace util uint32_t ts = bufbe32toh (buf + 32); if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900 g_TimeOffset = ts - ourTs; - LogPrint (eLogInfo, address, "Timestamp: time offset from system time is ", g_TimeOffset, " seconds"); + LogPrint (eLogInfo, "Timestamp: ", address, " time offset from system time is ", g_TimeOffset, " seconds"); } } + else + LogPrint (eLogError, "Timestamp: Couldn't open UDP socket"); } + else + LogPrint (eLogError, "Timestamp: Couldn't resove address ", address); } void RequestNTPTimeSync () From d7081c5f23bc71a756129900f1c73c649bee1959 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Nov 2018 20:52:54 -0500 Subject: [PATCH 11/33] handle RouterInfo from NTCP2 in netdb's thread --- libi2pd/I2NPProtocol.h | 1 + libi2pd/NTCP2.cpp | 5 ++--- libi2pd/NetDb.cpp | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 15e3a32c..5160acec 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -75,6 +75,7 @@ namespace i2p enum I2NPMessageType { + eI2NPDummyMsg = 0, eI2NPDatabaseStore = 1, eI2NPDatabaseLookup = 2, eI2NPDatabaseSearchReply = 3, diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 8caafd2f..5940e49a 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -695,8 +695,7 @@ namespace transport SendTerminationAndTerminate (eNTCP2IncorrectSParameter); return; } - - i2p::data::netdb.AddRouterInfo (buf.data () + 4, size - 1); // TODO: should insert ri and not parse it twice + i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 4, size - 1)); // TODO: should insert ri and not parse it twice // TODO: process options // ready to communicate @@ -861,7 +860,7 @@ namespace transport case eNTCP2BlkRouterInfo: { LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); - i2p::data::netdb.AddRouterInfo (frame + offset + 1, size - 1); + i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, frame + offset + 1, size - 1)); break; } case eNTCP2BlkI2NPMessage: diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0add6f91..cbe23d59 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -98,6 +98,10 @@ namespace data case eI2NPDatabaseLookup: HandleDatabaseLookupMsg (msg); break; + case eI2NPDummyMsg: + // plain RouterInfo from NTCP2 for now + AddRouterInfo (msg->GetPayload (), msg->GetPayloadLength ()); + break; default: // WTF? LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ()); //i2p::HandleI2NPMessage (msg); From 8a549b83a217eabfe1e068b43ec1061f718444d7 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Nov 2018 12:49:04 -0500 Subject: [PATCH 12/33] NTP sync in separate thread --- daemon/Daemon.cpp | 16 +++++++-- libi2pd/Timestamp.cpp | 76 ++++++++++++++++++++++++++++++++++++++----- libi2pd/Timestamp.h | 29 ++++++++++++++++- 3 files changed, 110 insertions(+), 11 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index b1e694fd..8e0804d1 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -42,6 +42,7 @@ namespace i2p std::unique_ptr httpServer; std::unique_ptr m_I2PControlService; std::unique_ptr UPnP; + std::unique_ptr m_NTPSync; #ifdef WITH_EVENTS std::unique_ptr m_WebsocketServer; #endif @@ -284,7 +285,11 @@ namespace i2p } bool nettime; i2p::config::GetOption("nettime.enabled", nettime); - if (nettime) i2p::util::RequestNTPTimeSync (); + if (nettime) + { + d.m_NTPSync = std::unique_ptr(new i2p::util::NTPTimeSync); + d.m_NTPSync->Start (); + } bool ntcp; i2p::config::GetOption("ntcp", ntcp); bool ssu; i2p::config::GetOption("ssu", ssu); @@ -355,11 +360,18 @@ namespace i2p LogPrint(eLogInfo, "Daemon: stopping Tunnels"); i2p::tunnel::tunnels.Stop(); - if (d.UPnP) { + if (d.UPnP) + { d.UPnP->Stop (); d.UPnP = nullptr; } + if (d.m_NTPSync) + { + d.m_NTPSync->Stop (); + d.m_NTPSync = nullptr; + } + LogPrint(eLogInfo, "Daemon: stopping Transports"); i2p::transport::transports.Stop(); LogPrint(eLogInfo, "Daemon: stopping NetDB"); diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 939e7f91..492e4559 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -1,7 +1,5 @@ #include #include -#include -#include #include #include #include @@ -92,15 +90,77 @@ namespace util LogPrint (eLogError, "Timestamp: Couldn't resove address ", address); } - void RequestNTPTimeSync () + NTPTimeSync::NTPTimeSync (): m_IsRunning (false), m_Timer (m_Service) { + i2p::config::GetOption("nettime.ntpsyncinterval", m_SyncInterval); std::string ntpservers; i2p::config::GetOption("nettime.ntpservers", ntpservers); - if (ntpservers.length () > 0) + boost::split (m_NTPServersList, ntpservers, boost::is_any_of(","), boost::token_compress_on); + } + + NTPTimeSync::~NTPTimeSync () + { + Stop (); + } + + void NTPTimeSync::Start() + { + if (m_NTPServersList.size () > 0) + { + m_IsRunning = true; + LogPrint(eLogInfo, "Timestamp: NTP time sync starting"); + m_Service.post (std::bind (&NTPTimeSync::Sync, this)); + m_Thread.reset (new std::thread (std::bind (&NTPTimeSync::Run, this))); + } + else + LogPrint (eLogWarning, "Timestamp: No NTP server found"); + } + + void NTPTimeSync::Stop () + { + if (m_IsRunning) + { + LogPrint(eLogInfo, "Timestamp: NTP time sync stopping"); + m_IsRunning = false; + m_Timer.cancel (); + m_Service.stop (); + if (m_Thread) + { + m_Thread->join (); + m_Thread.reset (nullptr); + } + } + } + + void NTPTimeSync::Run () + { + while (m_IsRunning) { - std::vector ntpList; - boost::split (ntpList, ntpservers, boost::is_any_of(","), boost::token_compress_on); - if (ntpList.size () > 0) - std::async (std::launch::async, SyncTimeWithNTP, ntpList[rand () % ntpList.size ()]); + try + { + m_Service.run (); + } + catch (std::exception& ex) + { + LogPrint (eLogError, "Timestamp: NTP time sync exception: ", ex.what ()); + } + } + } + + void NTPTimeSync::Sync () + { + if (m_NTPServersList.size () > 0) + SyncTimeWithNTP (m_NTPServersList[rand () % m_NTPServersList.size ()]); + else + m_IsRunning = false; + + if (m_IsRunning) + { + m_Timer.expires_from_now (boost::posix_time::hours (m_SyncInterval)); + m_Timer.async_wait ([this](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + Sync (); + }); } } diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index d7f200b9..e859f7f6 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -2,6 +2,10 @@ #define TIMESTAMP_H__ #include +#include +#include +#include +#include namespace i2p { @@ -11,7 +15,30 @@ namespace util uint32_t GetHoursSinceEpoch (); uint64_t GetSecondsSinceEpoch (); - void RequestNTPTimeSync (); + class NTPTimeSync + { + public: + + NTPTimeSync (); + ~NTPTimeSync (); + + void Start (); + void Stop (); + + private: + + void Run (); + void Sync (); + + private: + + bool m_IsRunning; + std::unique_ptr m_Thread; + boost::asio::io_service m_Service; + boost::asio::deadline_timer m_Timer; + int m_SyncInterval; + std::vector m_NTPServersList; + }; } } From 71e57717c2f4060ef1ebe238e10b6d403dab5c60 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 19 Nov 2018 15:53:16 -0500 Subject: [PATCH 13/33] request memory permisssion for android >= 6 --- .../src/org/purplei2p/i2pd/I2PDActivity.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index bc6f7209..31058765 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -13,13 +13,16 @@ import java.io.StringWriter; import java.util.Timer; import java.util.TimerTask; +import android.Manifest; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.res.AssetManager; +import android.content.pm.PackageManager; import android.os.Bundle; +import android.os.Build; import android.os.Environment; import android.os.IBinder; import android.util.Log; @@ -27,12 +30,15 @@ import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; // For future package update checking import org.purplei2p.i2pd.BuildConfig; public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; + private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1; public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; private TextView textView; @@ -93,6 +99,17 @@ public class I2PDActivity extends Activity { daemon.addStateChangeListener(daemonStateUpdatedListener); daemonStateUpdatedListener.daemonStateUpdate(); + // request permissions + if (Build.VERSION.SDK_INT >= 23) + { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) + { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); + } + } + // set the app be foreground doBindService(); @@ -119,6 +136,28 @@ public class I2PDActivity extends Activity { } } + @Override + public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) + { + switch (requestCode) + { + case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE: + { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) + { + Log.e(TAG, "Memory permission granted"); + } + else + { + Log.e(TAG, "Memory permission declined"); + // TODO: terminate + } + return; + } + default: ; + } + } + private static void cancelGracefulStop() { Timer gracefulQuitTimer = getGracefulQuitTimer(); if(gracefulQuitTimer!=null) { From 7c1961d4efe6f08a1598fbc8f42e7beda7c9132c Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Nov 2018 12:36:10 -0500 Subject: [PATCH 14/33] Cancel Graceful Stop --- android/jni/i2pd_android.cpp | 5 +++ android/jni/org_purplei2p_i2pd_I2PD_JNI.h | 3 ++ android/res/values/strings.xml | 1 + .../org/purplei2p/i2pd/DaemonSingleton.java | 7 ++++ .../src/org/purplei2p/i2pd/I2PDActivity.java | 41 ++++++++++++++++--- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 2 + 6 files changed, 54 insertions(+), 5 deletions(-) diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 8791c90b..ac968fd3 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -58,6 +58,11 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels i2p::context.SetAcceptsTunnels (false); } +JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels + (JNIEnv * env, jclass clazz) { + i2p::context.SetAcceptsTunnels (true); +} + JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged (JNIEnv * env, jclass clazz, jboolean isConnected) { diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h index 04923d22..7beb1284 100644 --- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h +++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h @@ -24,6 +24,9 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels (JNIEnv *, jclass); +JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels + (JNIEnv *, jclass); + JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged (JNIEnv * env, jclass clazz, jboolean isConnected); diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index a0cc264c..18aef3b1 100755 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -3,6 +3,7 @@ i2pd Stop Graceful Stop + Cancel Graceful Stop Graceful stop is already in progress Graceful stop is in progress Already stopped diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 4f3e62f7..4c3d5f44 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -33,6 +33,13 @@ public class DaemonSingleton { } } + public synchronized void startAcceptingTunnels() { + if(isStartedOkay()){ + setState(State.startedOkay); + I2PD_JNI.startAcceptingTunnels(); + } + } + private volatile boolean startedOkay; public enum State { diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 31058765..3c95a832 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -144,14 +144,10 @@ public class I2PDActivity extends Activity { case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) - { Log.e(TAG, "Memory permission granted"); - } else - { Log.e(TAG, "Memory permission declined"); // TODO: terminate - } return; } default: ; @@ -244,7 +240,16 @@ public class I2PDActivity extends Activity { i2pdStop(); return true; case R.id.action_graceful_stop: - i2pdGracefulStop(); + if (getGracefulQuitTimer()!= null) + { + item.setTitle(R.string.action_graceful_stop); + i2pdCancelGracefulStop (); + } + else + { + item.setTitle(R.string.action_cancel_graceful_stop); + i2pdGracefulStop(); + } return true; } @@ -307,6 +312,32 @@ public class I2PDActivity extends Activity { },"gracInit").start(); } + + private void i2pdCancelGracefulStop() + { + cancelGracefulStop(); + Toast.makeText(this, R.string.startedOkay, Toast.LENGTH_SHORT).show(); + new Thread(new Runnable() + { + @Override + public void run() + { + try + { + Log.d(TAG, "grac stopping cancel"); + if(daemon.isStartedOkay()) + daemon.startAcceptingTunnels(); + else + i2pdStop(); + } + catch(Throwable tr) + { + Log.e(TAG,"",tr); + } + } + + },"gracCancel").start(); + } private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) { if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel(); diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index f965d471..63867273 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -12,6 +12,8 @@ public class I2PD_JNI { public static native void stopAcceptingTunnels(); + public static native void startAcceptingTunnels(); + public static native void onNetworkStateChanged(boolean isConnected); public static void loadLibraries() { From 0e9074aabafc21fd86d6e0a3126f02fd98d20b7e Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Nov 2018 13:57:51 -0500 Subject: [PATCH 15/33] reduce start and stop time --- libi2pd/Transports.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 6a833ae0..f989bbef 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -35,8 +35,11 @@ namespace transport void DHKeysPairSupplier::Stop () { - m_IsRunning = false; - m_Acquired.notify_one (); + { + std::unique_lock l(m_AcquiredMutex); + m_IsRunning = false; + m_Acquired.notify_one (); + } if (m_Thread) { m_Thread->join (); @@ -50,19 +53,20 @@ namespace transport while (m_IsRunning) { int num, total = 0; - while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 20) + while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10) { CreateDHKeysPairs (num); total += num; } - if (total >= 20) + if (total >= 10) { LogPrint (eLogWarning, "Transports: ", total, " DH keys generated at the time"); std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break } else { - std::unique_lock l(m_AcquiredMutex); + std::unique_lock l(m_AcquiredMutex); + if (!m_IsRunning) break; m_Acquired.wait (l); // wait for element gets acquired } } From 42ed312384421b428ac136bf0f828a6db7fcb717 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Nov 2018 11:23:48 -0500 Subject: [PATCH 16/33] handle NTCP2 RouterInfo flag --- libi2pd/NTCP2.cpp | 4 ++-- libi2pd/NTCP2.h | 2 ++ libi2pd/NetDb.cpp | 15 +++++++++++++-- libi2pd/NetDb.hpp | 3 ++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 5940e49a..a88d2a3a 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -695,7 +695,7 @@ namespace transport SendTerminationAndTerminate (eNTCP2IncorrectSParameter); return; } - i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 4, size - 1)); // TODO: should insert ri and not parse it twice + i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options // ready to communicate @@ -860,7 +860,7 @@ namespace transport case eNTCP2BlkRouterInfo: { LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); - i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, frame + offset + 1, size - 1)); + i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, frame + offset, size)); break; } case eNTCP2BlkI2NPMessage: diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index ec8ae527..eb46b2f8 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -73,6 +73,8 @@ namespace transport eNTCP2Banned, // 17 }; + // RouterInfo flags + const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01; typedef std::array NTCP2FrameBuffer; struct NTCP2Establisher diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index cbe23d59..d1b3abc5 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -12,6 +12,7 @@ #include "I2NPProtocol.h" #include "Tunnel.h" #include "Transports.h" +#include "NTCP2.h" #include "RouterContext.h" #include "Garlic.h" #include "NetDb.hpp" @@ -99,8 +100,8 @@ namespace data HandleDatabaseLookupMsg (msg); break; case eI2NPDummyMsg: - // plain RouterInfo from NTCP2 for now - AddRouterInfo (msg->GetPayload (), msg->GetPayloadLength ()); + // plain RouterInfo from NTCP2 with flag for now + HandleNTCP2RouterInfoMsg (msg); break; default: // WTF? LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ()); @@ -574,6 +575,16 @@ namespace data transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr)); } + void NetDb::HandleNTCP2RouterInfoMsg (std::shared_ptr m) + { + uint8_t flood = m->GetPayload ()[0] & NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD; + bool updated = AddRouterInfo (m->GetPayload () + 1, m->GetPayloadLength () - 1); // without flag + if (flood && updated && context.IsFloodfill ()) + { + // TODO: flood + LogPrint (eLogInfo, "NetDb: NTCP RouterInfo flood is not implemented"); + } + } void NetDb::HandleDatabaseStoreMsg (std::shared_ptr m) { diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 18377b4f..8d42d760 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -65,7 +65,8 @@ namespace data 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; From ca671551c832ed7ef278a3c110e91c6955635ff1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Nov 2018 13:24:54 -0500 Subject: [PATCH 17/33] flood NTCP2 RouterInfo if requested --- libi2pd/NetDb.cpp | 82 ++++++++++++++++++++++++++++++----------------- libi2pd/NetDb.hpp | 9 ++++-- 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index d1b3abc5..9647be3f 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -100,7 +100,7 @@ namespace data HandleDatabaseLookupMsg (msg); break; case eI2NPDummyMsg: - // plain RouterInfo from NTCP2 with flag for now + // plain RouterInfo from NTCP2 with flags for now HandleNTCP2RouterInfoMsg (msg); break; default: // WTF? @@ -167,22 +167,38 @@ namespace data } } + void NetDb::SetHidden(bool hide) + { + // TODO: remove reachable addresses from router info + m_HiddenMode = hide; + } + bool NetDb::AddRouterInfo (const uint8_t * buf, int len) + { + bool updated; + AddRouterInfo (buf, len, updated); + return updated; + } + + std::shared_ptr NetDb::AddRouterInfo (const uint8_t * buf, int len, bool& updated) { IdentityEx identity; if (identity.FromBuffer (buf, len)) - return AddRouterInfo (identity.GetIdentHash (), buf, len); - return false; + return AddRouterInfo (identity.GetIdentHash (), buf, len, updated); + updated = false; + return nullptr; } - void NetDb::SetHidden(bool hide) { - // TODO: remove reachable addresses from router info - m_HiddenMode = hide; - } - bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) { - bool updated = true; + bool updated; + AddRouterInfo (ident, buf, len, updated); + return updated; + } + + std::shared_ptr NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated) + { + updated = true; auto r = FindRouter (ident); if (r) { @@ -228,7 +244,7 @@ namespace data } // take care about requested destination m_Requests.RequestComplete (ident, r); - return updated; + return r; } bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, @@ -578,11 +594,12 @@ namespace data void NetDb::HandleNTCP2RouterInfoMsg (std::shared_ptr m) { uint8_t flood = m->GetPayload ()[0] & NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD; - bool updated = AddRouterInfo (m->GetPayload () + 1, m->GetPayloadLength () - 1); // without flag - if (flood && updated && context.IsFloodfill ()) + bool updated; + auto ri = AddRouterInfo (m->GetPayload () + 1, m->GetPayloadLength () - 1, updated); // without flags + if (flood && updated && context.IsFloodfill () && ri) { - // TODO: flood - LogPrint (eLogInfo, "NetDb: NTCP RouterInfo flood is not implemented"); + auto floodMsg = CreateDatabaseStoreMsg (ri, 0); // replyToken = 0 + Flood (ri->GetIdentHash (), floodMsg); } } @@ -664,22 +681,7 @@ namespace data { memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen); floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); - std::set excluded; - excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself - excluded.insert (ident); // don't flood back - for (int i = 0; i < 3; i++) - { - auto floodfill = GetClosestFloodfill (ident, excluded); - if (floodfill) - { - auto h = floodfill->GetIdentHash(); - LogPrint(eLogDebug, "NetDb: Flood lease set for ", ident.ToBase32(), " to ", h.ToBase64()); - transports.SendMessage (h, CopyI2NPMessage(floodMsg)); - excluded.insert (h); - } - else - break; - } + Flood (ident, floodMsg); } else LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len); @@ -980,6 +982,26 @@ namespace data } } + void NetDb::Flood (const IdentHash& ident, std::shared_ptr floodMsg) + { + std::set excluded; + excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself + excluded.insert (ident); // don't flood back + for (int i = 0; i < 3; i++) + { + auto floodfill = GetClosestFloodfill (ident, excluded); + if (floodfill) + { + auto h = floodfill->GetIdentHash(); + LogPrint(eLogDebug, "NetDb: Flood lease set for ", ident.ToBase32(), " to ", h.ToBase64()); + transports.SendMessage (h, CopyI2NPMessage(floodMsg)); + excluded.insert (h); + } + else + break; + } + } + std::shared_ptr NetDb::GetRandomRouter () const { return GetRandomRouter ( diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 8d42d760..53d1e685 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -111,13 +111,16 @@ namespace data void Run (); // exploratory thread void Explore (int numDestinations); void Publish (); + void Flood (const IdentHash& ident, std::shared_ptr floodMsg); 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); - template - std::shared_ptr GetRandomRouter (Filter filter) const; + 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; private: From 79c0c11e80ca1f3de7f96d4152272c181c498413 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 22 Nov 2018 00:13:23 +0300 Subject: [PATCH 18/33] configure persist of peer profiles * If persist.profiles = false, peer profiles not stored on disk * remove inet_pton for windows * update configs --- android/assets/i2pd.conf | 12 ++++++++++-- contrib/i2pd.conf | 4 ++++ libi2pd/Config.cpp | 10 ++++++++-- libi2pd/NetDb.cpp | 11 +++++++---- libi2pd/NetDb.hpp | 2 ++ libi2pd/Transports.cpp | 1 - libi2pd/util.cpp | 6 +++--- 7 files changed, 34 insertions(+), 12 deletions(-) diff --git a/android/assets/i2pd.conf b/android/assets/i2pd.conf index a18e13d7..312a24ea 100644 --- a/android/assets/i2pd.conf +++ b/android/assets/i2pd.conf @@ -37,7 +37,12 @@ port = 7070 enabled = true address = 127.0.0.1 port = 4444 -# keys = http-proxy-keys.dat +inbound.length = 1 +inbound.quantity = 5 +outbound.length = 1 +outbound.quantity = 5 +signaturetype=7 +keys = proxy-keys.dat # addresshelper = true # outproxy = http://false.i2p ## httpproxy section also accepts I2CP parameters, like "inbound.length" etc. @@ -46,7 +51,7 @@ port = 4444 enabled = true address = 127.0.0.1 port = 4447 -# keys = socks-proxy-keys.dat +keys = proxy-keys.dat # outproxy.enabled = false # outproxy = 127.0.0.1 # outproxyport = 9050 @@ -80,3 +85,6 @@ verify = true [limits] transittunnels = 50 + +[persist] +profiles = false diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 7bd2c90f..1ef725bb 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -225,3 +225,7 @@ verify = true # inbound.quantity = 3 # outbound.length = 2 # outbound.quantity = 3 + +[persist] +## Save peer profiles on disk (default: true) +# profiles = true diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 3251886b..0403275f 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -237,7 +237,7 @@ namespace config { options_description ntcp2("NTCP2 Options"); ntcp2.add_options() ("ntcp2.enabled", value()->default_value(true), "Enable NTCP2 (default: enabled)") - ("ntcp2.published", value()->default_value(false), "Publish NTCP2 (default: disabled)") + ("ntcp2.published", value()->default_value(false), "Publish NTCP2 (default: disabled)") ("ntcp2.port", value()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)") ; @@ -249,10 +249,15 @@ 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)") ; + options_description persist("Network information persisting options"); + persist.add_options() + ("persist.profiles", value()->default_value(true), "Persist peer profiles (default: true)") + ; + m_OptionsDesc .add(general) .add(limits) @@ -272,6 +277,7 @@ namespace config { .add(exploratory) .add(ntcp2) .add(nettime) + .add(persist) ; } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 9647be3f..ebcc1c5d 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -44,10 +44,12 @@ namespace data m_Families.LoadCertificates (); Load (); - uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); + uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold Reseed (); + i2p::config::GetOption("persist.profiles", m_PersistProfiles); + m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); } @@ -56,8 +58,9 @@ namespace data { if (m_IsRunning) { - for (auto& it: m_RouterInfos) - it.second->SaveProfile (); + if (m_PersistProfiles) + for (auto& it: m_RouterInfos) + it.second->SaveProfile (); DeleteObsoleteProfiles (); m_RouterInfos.clear (); m_Floodfills.clear (); @@ -539,7 +542,7 @@ namespace data { if (it->second->IsUnreachable ()) { - it->second->SaveProfile (); + if (m_PersistProfiles) it->second->SaveProfile (); it = m_RouterInfos.erase (it); continue; } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 53d1e685..b34458fb 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -144,6 +144,8 @@ namespace data friend class NetDbRequests; NetDbRequests m_Requests; + bool m_PersistProfiles; + /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ std::shared_ptr m_FloodfillBootstrap; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index f989bbef..64f41afd 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -817,7 +817,6 @@ namespace transport if (profile) { profile->TunnelNonReplied(); - profile->Save(it->first); } std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 1395c2e6..b558fca4 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -21,9 +21,9 @@ #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) +/* // No more needed. Exists in MinGW. int inet_pton(int af, const char *src, void *dst) -{ /* This function was written by Petar Korponai?. See -http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */ +{ // This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found struct sockaddr_storage ss; int size = sizeof (ss); char src_copy[INET6_ADDRSTRLEN + 1]; @@ -45,7 +45,7 @@ http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */ } } return 0; -} +}*/ #else /* !WIN32 => UNIX */ #include #include From c0e263abd34641e74de69fabf7587795401246e3 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 22 Nov 2018 11:30:44 -0500 Subject: [PATCH 19/33] default value for m_PersistProfiles --- libi2pd/NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index ebcc1c5d..2e5c3a23 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -26,7 +26,7 @@ namespace data { NetDb netdb; - NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false) + NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true), m_HiddenMode(false) { } From cde989b59d6c94ae1ad51ad62d95d4cec711928e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 22 Nov 2018 12:13:16 -0500 Subject: [PATCH 20/33] don't compile compatibility code if openssl 1.1.1 --- libi2pd/ChaCha20.cpp | 6 +++++- libi2pd/ChaCha20.h | 3 +++ libi2pd/Ed25519.cpp | 2 ++ libi2pd/Ed25519.h | 5 +++++ libi2pd/Poly1305.cpp | 4 ++++ libi2pd/Poly1305.h | 3 +++ libi2pd/Siphash.h | 3 +++ 7 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libi2pd/ChaCha20.cpp b/libi2pd/ChaCha20.cpp index e43f1514..0ab98fb2 100644 --- a/libi2pd/ChaCha20.cpp +++ b/libi2pd/ChaCha20.cpp @@ -7,6 +7,8 @@ Kovri go write your own code */ + +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -144,4 +146,6 @@ void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * k } } -} \ No newline at end of file +} +#endif + diff --git a/libi2pd/ChaCha20.h b/libi2pd/ChaCha20.h index c88325d5..5a8ce145 100644 --- a/libi2pd/ChaCha20.h +++ b/libi2pd/ChaCha20.h @@ -9,7 +9,9 @@ #define LIBI2PD_CHACHA20_H #include #include +#include "Crypto.h" +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -22,5 +24,6 @@ namespace crypto } } +#endif #endif diff --git a/libi2pd/Ed25519.cpp b/libi2pd/Ed25519.cpp index 17264926..2c64c475 100644 --- a/libi2pd/Ed25519.cpp +++ b/libi2pd/Ed25519.cpp @@ -411,6 +411,7 @@ namespace crypto } } +#if !OPENSSL_X25519 BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const { BN_CTX_start (ctx); @@ -488,6 +489,7 @@ namespace crypto EncodeBN (q1, buf, 32); BN_free (p1); BN_free (n); BN_free (q1); } +#endif void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey) { diff --git a/libi2pd/Ed25519.h b/libi2pd/Ed25519.h index fc23a457..48b3a665 100644 --- a/libi2pd/Ed25519.h +++ b/libi2pd/Ed25519.h @@ -3,6 +3,7 @@ #include #include +#include "Crypto.h" namespace i2p { @@ -75,8 +76,10 @@ namespace crypto EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const; EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const; void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const; +#if !OPENSSL_X25519 void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519 void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; +#endif 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; @@ -100,8 +103,10 @@ namespace crypto BIGNUM * DecodeBN (const uint8_t * buf) const; void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const; +#if !OPENSSL_X25519 // for x25519 BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const; +#endif private: diff --git a/libi2pd/Poly1305.cpp b/libi2pd/Poly1305.cpp index 9ee46640..a33e9d1b 100644 --- a/libi2pd/Poly1305.cpp +++ b/libi2pd/Poly1305.cpp @@ -6,6 +6,8 @@ Kovri go write your own code */ + +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -249,3 +251,5 @@ namespace crypto } } } +#endif + diff --git a/libi2pd/Poly1305.h b/libi2pd/Poly1305.h index 2c62c5aa..d47e2e66 100644 --- a/libi2pd/Poly1305.h +++ b/libi2pd/Poly1305.h @@ -9,7 +9,9 @@ #define LIBI2PD_POLY1305_H #include #include +#include "Crypto.h" +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -24,5 +26,6 @@ namespace crypto } } +#endif #endif diff --git a/libi2pd/Siphash.h b/libi2pd/Siphash.h index aa8b8631..70822466 100644 --- a/libi2pd/Siphash.h +++ b/libi2pd/Siphash.h @@ -9,7 +9,9 @@ #define SIPHASH_H #include +#include "Crypto.h" +#if !OPENSSL_SIPHASH namespace i2p { namespace crypto @@ -148,5 +150,6 @@ namespace crypto } } } +#endif #endif From f7e997519298d6d767ff4a3fa88f6f9cedd81be3 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 24 Nov 2018 09:43:30 -0500 Subject: [PATCH 21/33] restore BlockCipher XOR using SSE --- libi2pd/Crypto.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 5daf82b0..cbfeb0e9 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -123,8 +123,20 @@ namespace crypto ); } else -#endif +#endif { +#if defined(__SSE__) // SSE + __asm__ + ( + "movups (%[buf]), %%xmm0 \n" + "movups (%[other]), %%xmm1 \n" + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[buf]) \n" + : + : [buf]"r"(buf), [other]"r"(other.buf) + : "%xmm0", "%xmm1", "memory" + ); +#else if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ? { // we are good to cast to uint32_t * @@ -136,6 +148,7 @@ namespace crypto for (int i = 0; i < 16; i++) buf[i] ^= other.buf[i]; } +#endif } } }; From f385c624c7e87c371b6812a46dfb837f43c619cc Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 24 Nov 2018 10:07:17 -0500 Subject: [PATCH 22/33] expose poly1305 digester --- libi2pd/Crypto.cpp | 6 +- libi2pd/Poly1305.cpp | 236 +---------------------------------------- libi2pd/Poly1305.h | 246 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 244 insertions(+), 244 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 4393b2cc..e36b3071 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1126,13 +1126,13 @@ namespace crypto if (encrypt) { // calculate Poly1305 tag and write in after encrypted data - Poly1305HMAC ((uint32_t *)(buf + msgLen), (uint32_t *)polyKey, polyMsg.data (), offset); + Poly1305HMAC ((uint64_t *)(buf + msgLen), (uint64_t *)polyKey, polyMsg.data (), offset); } else { - uint32_t tag[8]; + uint64_t tag[4]; // calculate Poly1305 tag - Poly1305HMAC (tag, (uint32_t *)polyKey, polyMsg.data (), offset); + Poly1305HMAC (tag, (uint64_t *)polyKey, polyMsg.data (), offset); if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided } #else diff --git a/libi2pd/Poly1305.cpp b/libi2pd/Poly1305.cpp index 9ee46640..0f953b8a 100644 --- a/libi2pd/Poly1305.cpp +++ b/libi2pd/Poly1305.cpp @@ -10,242 +10,12 @@ namespace i2p { namespace crypto { - namespace poly1305 - { - - struct LongBlock - { - unsigned long data[17]; - operator unsigned long * () - { - return data; - } - }; - - struct Block - { - unsigned char data[17]; - - operator uint8_t * () - { - return data; - } - - Block & operator += (const Block & other) - { - unsigned short u; - unsigned int i; - for(u = 0, i = 0; i < 17; i++) - { - u += (unsigned short) data[i] + (unsigned short) other.data[i]; - data[i] = (unsigned char) u & 0xff; - u >>= 8; - } - return *this; - } - - Block & operator %=(const LongBlock & other) - { - unsigned long u; - unsigned int i; - u = 0; - for (i = 0; i < 16; i++) { - u += other.data[i]; - data[i] = (unsigned char)u & 0xff; - u >>= 8; - } - u += other.data[16]; - data[16] = (unsigned char)u & 0x03; - u >>= 2; - u += (u << 2); - for (i = 0; i < 16; i++) { - u += data[i]; - data[i] = (unsigned char)u & 0xff; - u >>= 8; - } - data[16] += (unsigned char)u; - return *this; - } - - Block & operator = (const Block & other) - { - memcpy(data, other.data, sizeof(data)); - return *this; - } - - Block & operator ~ () - { - static const Block minusp = { - 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfc - }; - Block orig; - unsigned char neg; - unsigned int i; - orig = *this; - *this += minusp; - neg = -(data[16] >> 7); - for(i = 0; i < 17; i++) - data[i] ^= neg & (orig.data[i] ^ data[i]); - - return *this; - } - - void PutKey(const uint8_t * key) - { - data[0] = key[0] & 0xff; - data[1] = key[1] & 0xff; - data[2] = key[2] & 0xff; - data[3] = key[3] & 0x0f; - data[4] = key[4] & 0xfc; - data[5] = key[5] & 0xff; - data[6] = key[6] & 0xff; - data[7] = key[7] & 0x0f; - data[8] = key[8] & 0xfc; - data[9] = key[9] & 0xff; - data[10] = key[10] & 0xff; - data[11] = key[11] & 0x0f; - data[12] = key[12] & 0xfc; - data[13] = key[13] & 0xff; - data[14] = key[14] & 0xff; - data[15] = key[15] & 0x0f; - data[16] = 0; - } - - void Put(const uint8_t * d, uint8_t last=0) - { - memcpy(data, d, 17); - data[16] = last; - } - }; - - struct Buffer - { - uint8_t data[POLY1305_BLOCK_BYTES]; - operator uint8_t * () - { - return data; - } - }; - } - - struct Poly1305 + void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz) { -#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 8) // older than gcc 4.8 - Poly1305(const uint8_t * key) : m_Leftover(0), m_Final(0) - { - memset (&m_H, 0, sizeof (m_H)); -#else - Poly1305(const uint8_t * key) : m_Leftover(0), m_H{0}, m_Final(0) - { -#endif - m_R.PutKey(key); - m_Pad.Put(key + 16); - } - - void Update(const uint8_t * buf, size_t sz) - { - // process leftover - if(m_Leftover) - { - size_t want = POLY1305_BLOCK_BYTES - m_Leftover; - if(want > sz) want = sz; - memcpy(m_Buffer + m_Leftover, buf, want); - sz -= want; - buf += want; - m_Leftover += want; - if(m_Leftover < POLY1305_BLOCK_BYTES) return; - Blocks(m_Buffer, POLY1305_BLOCK_BYTES); - m_Leftover = 0; - } - // process blocks - if(sz >= POLY1305_BLOCK_BYTES) - { - size_t want = (sz & ~(POLY1305_BLOCK_BYTES - 1)); - Blocks(buf, want); - buf += want; - sz -= want; - } - // leftover - if(sz) - { - memcpy(m_Buffer+m_Leftover, buf, sz); - m_Leftover += sz; - } - } - - void Blocks(const uint8_t * buf, size_t sz) - { - const unsigned char hi = m_Final ^ 1; - while (sz >= POLY1305_BLOCK_BYTES) { - - unsigned long u; - - unsigned int i, j; - m_Msg.Put(buf, hi); - /* h += m */ - m_H += m_Msg; - - /* h *= r */ - for (i = 0; i < 17; i++) { - u = 0; - for (j = 0; j <= i ; j++) { - u += (unsigned short)m_H.data[j] * m_R.data[i - j]; - } - for (j = i + 1; j < 17; j++) { - unsigned long v = (unsigned short)m_H.data[j] * m_R.data[i + 17 - j]; - v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */ - u += v; - } - m_HR[i] = u; - } - /* (partial) h %= p */ - m_H %= m_HR; - buf += POLY1305_BLOCK_BYTES; - sz -= POLY1305_BLOCK_BYTES; - } - } - - void Finish(uint32_t *& out) - { - // process leftovers - if(m_Leftover) - { - size_t idx = m_Leftover; - m_Buffer[idx++] = 1; - for(; idx < POLY1305_BLOCK_BYTES; idx++) - m_Buffer[idx] = 0; - m_Final = 1; - Blocks(m_Buffer, POLY1305_BLOCK_BYTES); - } - - // freeze H - ~m_H; - // add pad - m_H += m_Pad; - // copy digest - memcpy(out, m_H, 16); - } - - size_t m_Leftover; - poly1305::Buffer m_Buffer; - poly1305::Block m_H; - poly1305::Block m_R; - poly1305::Block m_Pad; - poly1305::Block m_Msg; - poly1305::LongBlock m_HR; - uint8_t m_Final; - - }; - - void Poly1305HMAC(uint32_t * out, const uint32_t * key, const uint8_t * buf, std::size_t sz) - { - const uint8_t * k = (const uint8_t *) key; - Poly1305 p(k); + Poly1305 p(key); p.Update(buf, sz); p.Finish(out); - } + } } } diff --git a/libi2pd/Poly1305.h b/libi2pd/Poly1305.h index 2c62c5aa..b2d64bb0 100644 --- a/libi2pd/Poly1305.h +++ b/libi2pd/Poly1305.h @@ -14,14 +14,244 @@ namespace i2p { namespace crypto { - const std::size_t POLY1305_DIGEST_BYTES = 16; - const std::size_t POLY1305_DIGEST_DWORDS = 4; - const std::size_t POLY1305_KEY_BYTES = 32; - const std::size_t POLY1305_KEY_DWORDS = 8; - const std::size_t POLY1305_BLOCK_BYTES = 16; - - void Poly1305HMAC(uint32_t * out, const uint32_t * key, const uint8_t * buf, std::size_t sz); - + const std::size_t POLY1305_DIGEST_BYTES = 16; + const std::size_t POLY1305_DIGEST_DWORDS = 4; + const std::size_t POLY1305_KEY_BYTES = 32; + const std::size_t POLY1305_KEY_DWORDS = 8; + const std::size_t POLY1305_BLOCK_BYTES = 16; + + namespace poly1305 + { + + struct LongBlock + { + unsigned long data[17]; + operator unsigned long * () + { + return data; + } + }; + + struct Block + { + unsigned char data[17]; + + void Zero() + { + memset(data, 0, sizeof(data)); + } + + operator uint8_t * () + { + return data; + } + + Block & operator += (const Block & other) + { + unsigned short u; + unsigned int i; + for(u = 0, i = 0; i < 17; i++) + { + u += (unsigned short) data[i] + (unsigned short) other.data[i]; + data[i] = (unsigned char) u & 0xff; + u >>= 8; + } + return *this; + } + + Block & operator %=(const LongBlock & other) + { + unsigned long u; + unsigned int i; + u = 0; + for (i = 0; i < 16; i++) { + u += other.data[i]; + data[i] = (unsigned char)u & 0xff; + u >>= 8; + } + u += other.data[16]; + data[16] = (unsigned char)u & 0x03; + u >>= 2; + u += (u << 2); + for (i = 0; i < 16; i++) { + u += data[i]; + data[i] = (unsigned char)u & 0xff; + u >>= 8; + } + data[16] += (unsigned char)u; + return *this; + } + + Block & operator = (const Block & other) + { + memcpy(data, other.data, sizeof(data)); + return *this; + } + + Block & operator ~ () + { + static const Block minusp = { + 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfc + }; + Block orig; + unsigned char neg; + unsigned int i; + orig = *this; + *this += minusp; + neg = -(data[16] >> 7); + for(i = 0; i < 17; i++) + data[i] ^= neg & (orig.data[i] ^ data[i]); + + return *this; + } + + void PutKey(const uint64_t * key_l) + { + const uint8_t * key = (const uint8_t*) key_l; + data[0] = key[0] & 0xff; + data[1] = key[1] & 0xff; + data[2] = key[2] & 0xff; + data[3] = key[3] & 0x0f; + data[4] = key[4] & 0xfc; + data[5] = key[5] & 0xff; + data[6] = key[6] & 0xff; + data[7] = key[7] & 0x0f; + data[8] = key[8] & 0xfc; + data[9] = key[9] & 0xff; + data[10] = key[10] & 0xff; + data[11] = key[11] & 0x0f; + data[12] = key[12] & 0xfc; + data[13] = key[13] & 0xff; + data[14] = key[14] & 0xff; + data[15] = key[15] & 0x0f; + data[16] = 0; + } + + template + void Put(const Int_t * d, uint8_t last=0) + { + memcpy(data, d, 16); + data[16] = last; + } + }; + + struct Buffer + { + uint8_t data[POLY1305_BLOCK_BYTES]; + + operator uint8_t * () + { + return data; + } + }; + } + + struct Poly1305 + { + Poly1305(const uint64_t * key) + { + m_Leftover = 0; + m_H.Zero(); + m_Final = 0; + m_R.PutKey(key); + m_Pad.Put(key + 2); + } + + void Update(const uint8_t * buf, size_t sz) + { + // process leftover + if(m_Leftover) + { + size_t want = POLY1305_BLOCK_BYTES - m_Leftover; + if(want > sz) want = sz; + memcpy(m_Buffer + m_Leftover, buf, want); + sz -= want; + buf += want; + m_Leftover += want; + if(m_Leftover < POLY1305_BLOCK_BYTES) return; + Blocks(m_Buffer, POLY1305_BLOCK_BYTES); + m_Leftover = 0; + } + // process blocks + if(sz >= POLY1305_BLOCK_BYTES) + { + size_t want = (sz & ~(POLY1305_BLOCK_BYTES - 1)); + Blocks(buf, want); + buf += want; + sz -= want; + } + // leftover + if(sz) + { + memcpy(m_Buffer+m_Leftover, buf, sz); + m_Leftover += sz; + } + } + + void Blocks(const uint8_t * buf, size_t sz) + { + const unsigned char hi = m_Final ^ 1; + while (sz >= POLY1305_BLOCK_BYTES) { + unsigned long u; + unsigned int i, j; + m_Msg.Put(buf, hi); + /* h += m */ + m_H += m_Msg; + + /* h *= r */ + for (i = 0; i < 17; i++) { + u = 0; + for (j = 0; j <= i ; j++) { + u += (unsigned short)m_H.data[j] * m_R.data[i - j]; + } + for (j = i + 1; j < 17; j++) { + unsigned long v = (unsigned short)m_H.data[j] * m_R.data[i + 17 - j]; + v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */ + u += v; + } + m_HR[i] = u; + } + /* (partial) h %= p */ + m_H %= m_HR; + buf += POLY1305_BLOCK_BYTES; + sz -= POLY1305_BLOCK_BYTES; + } + } + + void Finish(uint64_t * out) + { + // process leftovers + if(m_Leftover) + { + size_t idx = m_Leftover; + m_Buffer[idx++] = 1; + for(; idx < POLY1305_BLOCK_BYTES; idx++) + m_Buffer[idx] = 0; + m_Final = 1; + Blocks(m_Buffer, POLY1305_BLOCK_BYTES); + } + + // freeze H + ~m_H; + // add pad + m_H += m_Pad; + // copy digest + memcpy(out, m_H, 16); + } + + size_t m_Leftover; + poly1305::Buffer m_Buffer; + poly1305::Block m_H; + poly1305::Block m_R; + poly1305::Block m_Pad; + poly1305::Block m_Msg; + 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); + } } From fa620e41a489e7d117304099e7d7163c33c583a2 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 24 Nov 2018 14:41:17 -0500 Subject: [PATCH 23/33] correct alignment for polyKey --- libi2pd/Crypto.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 2448264f..b57ee111 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1088,9 +1088,9 @@ namespace crypto bool ret = true; #if LEGACY_OPENSSL // generate one time poly key - uint8_t polyKey[64]; + uint64_t polyKey[8]; memset(polyKey, 0, sizeof(polyKey)); - chacha20 (polyKey, 64, nonce, key, 0); + chacha20 ((uint8_t *)polyKey, 64, nonce, key, 0); // create Poly1305 message if (!ad) adLen = 0; @@ -1142,7 +1142,7 @@ namespace crypto { uint64_t tag[4]; // calculate Poly1305 tag - Poly1305HMAC (tag, (uint64_t *)polyKey, polyMsg.data (), offset); + Poly1305HMAC (tag, polyKey, polyMsg.data (), offset); if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided } #else From 72c8fd257c7cb68e396f67722e77aab4272d3e4d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 24 Nov 2018 15:39:37 -0500 Subject: [PATCH 24/33] eliminate extra buffer for Poly1305 --- libi2pd/Crypto.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index b57ee111..9b66c8c5 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1091,21 +1091,20 @@ namespace crypto uint64_t polyKey[8]; memset(polyKey, 0, sizeof(polyKey)); chacha20 ((uint8_t *)polyKey, 64, nonce, key, 0); - - // create Poly1305 message + + // create Poly1305 hash + Poly1305 polyHash (polyKey); if (!ad) adLen = 0; - std::vector polyMsg(adLen + msgLen + 3*16); - size_t offset = 0; uint8_t padding[16]; memset (padding, 0, 16); if (ad) { - memcpy (polyMsg.data (), ad, adLen); offset += adLen; // additional authenticated data + polyHash.Update (ad, adLen);// additional authenticated data auto rem = adLen & 0x0F; // %16 if (rem) { // padding1 rem = 16 - rem; - memcpy (polyMsg.data () + offset, padding, rem); offset += rem; + polyHash.Update (padding, rem); } } // encrypt/decrypt data and add to hash @@ -1114,35 +1113,35 @@ namespace crypto if (encrypt) { chacha20 (buf, msgLen, nonce, key, 1); // encrypt - memcpy (polyMsg.data () + offset, buf, msgLen); // after encryption + polyHash.Update (buf, msgLen); // after encryption } else { - memcpy (polyMsg.data () + offset, buf, msgLen); // before decryption + polyHash.Update (buf, msgLen); // before decryption chacha20 (buf, msgLen, nonce, key, 1); // decrypt } - offset += msgLen; // encrypted data auto rem = msgLen & 0x0F; // %16 if (rem) { // padding2 rem = 16 - rem; - memcpy (polyMsg.data () + offset, padding, rem); offset += rem; + polyHash.Update (padding, rem); } - htole64buf (polyMsg.data () + offset, adLen); offset += 8; - htole64buf (polyMsg.data () + offset, msgLen); offset += 8; - + // adLen and msgLen + htole64buf (padding, adLen); + polyHash.Update (padding, 8); + htole64buf (padding, msgLen); + polyHash.Update (padding, 8); + if (encrypt) - { // calculate Poly1305 tag and write in after encrypted data - Poly1305HMAC ((uint64_t *)(buf + msgLen), (uint64_t *)polyKey, polyMsg.data (), offset); - } + polyHash.Finish ((uint64_t *)(buf + msgLen)); else { uint64_t tag[4]; // calculate Poly1305 tag - Poly1305HMAC (tag, polyKey, polyMsg.data (), offset); + polyHash.Finish (tag); if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided } #else From cf0fc3a4a9b37ba097a33c1526f79f3358e41373 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 Nov 2018 10:33:48 -0500 Subject: [PATCH 25/33] some performance improvements --- libi2pd/Crypto.cpp | 5 ++- libi2pd/Crypto.h | 79 +++++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 9b66c8c5..dcd89064 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1130,9 +1130,8 @@ namespace crypto } // adLen and msgLen htole64buf (padding, adLen); - polyHash.Update (padding, 8); - htole64buf (padding, msgLen); - polyHash.Update (padding, 8); + htole64buf (padding + 8, msgLen); + polyHash.Update (padding, 16); if (encrypt) // calculate Poly1305 tag and write in after encrypted data diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index cbfeb0e9..7f44195a 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -108,48 +108,55 @@ namespace crypto void operator^=(const ChipherBlock& other) // XOR { + if (!(((size_t)buf | (size_t)other.buf) & 0x0F)) // multiple of 16 ? + { + // try 128 bits if applicable #ifdef __AVX__ - if (i2p::cpu::avx) - { - __asm__ + if (i2p::cpu::avx) + { + __asm__ + ( + "vmovaps (%[buf]), %%xmm0 \n" + "vmovaps (%[other]), %%xmm1 \n" + "vxorps %%xmm0, %%xmm1, %%xmm0 \n" + "vmovaps %%xmm0, (%[buf]) \n" + : + : [buf]"r"(buf), [other]"r"(other.buf) + : "%xmm0", "%xmm1", "memory" + ); + } + else +#endif + { +#if defined(__SSE__) // SSE + __asm__ ( - "vmovups (%[buf]), %%xmm0 \n" - "vmovups (%[other]), %%xmm1 \n" - "vxorps %%xmm0, %%xmm1, %%xmm0 \n" - "vmovups %%xmm0, (%[buf]) \n" + "movaps (%[buf]), %%xmm0 \n" + "movaps (%[other]), %%xmm1 \n" + "pxor %%xmm1, %%xmm0 \n" + "movaps %%xmm0, (%[buf]) \n" : : [buf]"r"(buf), [other]"r"(other.buf) : "%xmm0", "%xmm1", "memory" - ); - } - else -#endif - { -#if defined(__SSE__) // SSE - __asm__ - ( - "movups (%[buf]), %%xmm0 \n" - "movups (%[other]), %%xmm1 \n" - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[buf]) \n" - : - : [buf]"r"(buf), [other]"r"(other.buf) - : "%xmm0", "%xmm1", "memory" - ); -#else - if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ? - { - // we are good to cast to uint32_t * - for (int i = 0; i < 4; i++) - ((uint32_t *)buf)[i] ^= ((uint32_t *)other.buf)[i]; - } - else - { - for (int i = 0; i < 16; i++) - buf[i] ^= other.buf[i]; + ); +#else + // if not we always can cast to uint64_t * + ((uint64_t *)buf)[0] ^= ((uint64_t *)other.buf)[0]; + ((uint64_t *)buf)[1] ^= ((uint64_t *)other.buf)[1]; +#endif } -#endif - } + } + else if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ? + { + // we are good to cast to uint32_t * + for (int i = 0; i < 4; i++) + ((uint32_t *)buf)[i] ^= ((uint32_t *)other.buf)[i]; + } + else + { + for (int i = 0; i < 16; i++) + buf[i] ^= other.buf[i]; + } } }; From d49f165f0dd3f1d753c3c0f4c777ef9d85594841 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 Nov 2018 15:59:00 -0500 Subject: [PATCH 26/33] fixed build warning --- libi2pd/Crypto.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 7f44195a..6accdaa0 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -140,18 +140,12 @@ namespace crypto : "%xmm0", "%xmm1", "memory" ); #else - // if not we always can cast to uint64_t * - ((uint64_t *)buf)[0] ^= ((uint64_t *)other.buf)[0]; - ((uint64_t *)buf)[1] ^= ((uint64_t *)other.buf)[1]; + // if not we always can cast to uint32_t * + for (int i = 0; i < 4; i++) + reinterpret_cast(buf)[i] ^= reinterpret_cast(buf)[i]; #endif } } - else if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ? - { - // we are good to cast to uint32_t * - for (int i = 0; i < 4; i++) - ((uint32_t *)buf)[i] ^= ((uint32_t *)other.buf)[i]; - } else { for (int i = 0; i < 16; i++) From 08706f5dfb0db821bbb9db022330fb3ee60ccd3b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 Nov 2018 18:49:59 -0500 Subject: [PATCH 27/33] fixed typo --- libi2pd/Crypto.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 6accdaa0..9c4ff505 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -142,7 +142,7 @@ namespace crypto #else // if not we always can cast to uint32_t * for (int i = 0; i < 4; i++) - reinterpret_cast(buf)[i] ^= reinterpret_cast(buf)[i]; + reinterpret_cast(buf)[i] ^= reinterpret_cast(other.buf)[i]; #endif } } From 328c2182c29d12938f9ad757a18bc0dffa8255bb Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 27 Nov 2018 10:35:17 -0500 Subject: [PATCH 28/33] alignment for tunnel message AES decryption --- libi2pd/NTCP2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index a88d2a3a..513aad08 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -872,6 +872,7 @@ namespace transport break; } auto nextMsg = NewI2NPMessage (size); + nextMsg->Align (12); // for possible tunnel msg nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header memcpy (nextMsg->GetNTCP2Header (), frame + offset, size); nextMsg->FromNTCP2 (); From fcd6eb78014777f92f3e4d18cdd7074d587d97a1 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 27 Nov 2018 19:56:35 +0300 Subject: [PATCH 29/33] overwrite user-agent for outproxy requests --- libi2pd_client/HTTPProxy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index f0530ac1..e54ccda5 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -390,6 +390,10 @@ namespace proxy { std::string origURI = m_ClientRequest.uri; // TODO: what do we need to change uri for? m_ClientRequest.uri = m_ClientRequestURL.to_string(); + // update User-Agent to ESR version of Firefox, same as Tor Browser below version 8, for non-HTTPS connections + if(m_ClientRequest.method != "CONNECT") + m_ClientRequest.UpdateHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0"); + m_ClientRequest.write(m_ClientRequestBuffer); m_ClientRequestBuffer << m_recv_buf.substr(m_req_len); From 0c9ebc36d40a9e38fa640680ea48c1703a3db63a Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 27 Nov 2018 14:33:31 -0500 Subject: [PATCH 30/33] remove AVX and SSE for CipherBlock XOR --- libi2pd/Crypto.h | 39 +++------------------------------------ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 9c4ff505..475f7fa3 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -108,43 +108,10 @@ namespace crypto void operator^=(const ChipherBlock& other) // XOR { - if (!(((size_t)buf | (size_t)other.buf) & 0x0F)) // multiple of 16 ? + if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ? { - // try 128 bits if applicable -#ifdef __AVX__ - if (i2p::cpu::avx) - { - __asm__ - ( - "vmovaps (%[buf]), %%xmm0 \n" - "vmovaps (%[other]), %%xmm1 \n" - "vxorps %%xmm0, %%xmm1, %%xmm0 \n" - "vmovaps %%xmm0, (%[buf]) \n" - : - : [buf]"r"(buf), [other]"r"(other.buf) - : "%xmm0", "%xmm1", "memory" - ); - } - else -#endif - { -#if defined(__SSE__) // SSE - __asm__ - ( - "movaps (%[buf]), %%xmm0 \n" - "movaps (%[other]), %%xmm1 \n" - "pxor %%xmm1, %%xmm0 \n" - "movaps %%xmm0, (%[buf]) \n" - : - : [buf]"r"(buf), [other]"r"(other.buf) - : "%xmm0", "%xmm1", "memory" - ); -#else - // if not we always can cast to uint32_t * - for (int i = 0; i < 4; i++) - reinterpret_cast(buf)[i] ^= reinterpret_cast(other.buf)[i]; -#endif - } + for (int i = 0; i < 4; i++) + reinterpret_cast(buf)[i] ^= reinterpret_cast(other.buf)[i]; } else { From e68f1dbc99f694d2887b84afcbe2d52795e6aa2f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Nov 2018 14:41:14 -0500 Subject: [PATCH 31/33] AEAD/Chacha20/Poly1305 encrypt multiple buffers --- libi2pd/ChaCha20.cpp | 121 ++++++++++++---------------- libi2pd/ChaCha20.h | 26 +++++- libi2pd/Crypto.cpp | 49 +++++++++++ libi2pd/Crypto.h | 3 + tests/test-aeadchacha20poly1305.cpp | 6 ++ 5 files changed, 133 insertions(+), 72 deletions(-) diff --git a/libi2pd/ChaCha20.cpp b/libi2pd/ChaCha20.cpp index 0ab98fb2..dc6eb18f 100644 --- a/libi2pd/ChaCha20.cpp +++ b/libi2pd/ChaCha20.cpp @@ -50,44 +50,26 @@ void quarterround(uint32_t *x, int a, int b, int c, int d) x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); } - struct State_t - { - State_t() {}; - State_t(State_t &&) = delete; - - State_t & operator += (const State_t & other) - { - for(int i = 0; i < 16; i++) - data[i] += other.data[i]; - return *this; - } - - void Copy(const State_t & other) - { - memcpy(data, other.data, sizeof(uint32_t) * 16); - } - uint32_t data[16]; - }; - - struct Block_t - { - Block_t() {}; - Block_t(Block_t &&) = delete; - uint8_t data[blocksize]; +struct Block_t +{ + Block_t() {}; + Block_t(Block_t &&) = delete; - void operator << (const State_t & st) - { - int i; - for (i = 0; i < 16; i++) - u32t8le(st.data[i], data + (i << 2)); - } - }; + uint8_t data[blocksize]; + + void operator << (const Chacha20State & st) + { + int i; + for (i = 0; i < 16; i++) + u32t8le(st.data[i], data + (i << 2)); + } +}; -void block(const State_t &input, Block_t & block, int rounds) +void block(const Chacha20State &input, Block_t & block, int rounds) { int i; - State_t x; + Chacha20State x; x.Copy(input); for (i = rounds; i > 0; i -= 2) @@ -107,44 +89,41 @@ void block(const State_t &input, Block_t & block, int rounds) } } // namespace chacha - - - - -void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter) -{ - chacha::State_t state; - chacha::Block_t block; - size_t i, j; - - state.data[0] = 0x61707865; - state.data[1] = 0x3320646e; - state.data[2] = 0x79622d32; - state.data[3] = 0x6b206574; - - for (i = 0; i < 8; i++) - state.data[4 + i] = chacha::u8t32le(key + i * 4); - - - state.data[12] = counter; - - for (i = 0; i < 3; i++) - state.data[13 + i] = chacha::u8t32le(nonce + i * 4); - - - for (i = 0; i < sz; i += chacha::blocksize) - { - chacha::block(state, block, chacha::rounds); - state.data[12]++; - for (j = i; j < i + chacha::blocksize; j++) - { - if (j >= sz) break; - buf[j] ^= block.data[j - i]; - } - } - -} - + void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter) + { + state.data[0] = 0x61707865; + 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); + + state.data[12] = counter; + for (size_t i = 0; i < 3; i++) + state.data[13 + i] = chacha::u8t32le(nonce + i * 4); + } + + void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz) + { + chacha::Block_t block; + for (size_t i = 0; i < sz; i += chacha::blocksize) + { + chacha::block(state, block, chacha::rounds); + state.data[12]++; + for (size_t j = i; j < i + chacha::blocksize; j++) + { + if (j >= sz) break; + buf[j] ^= block.data[j - i]; + } + } + } + + void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter) + { + Chacha20State state; + Chacha20Init (state, nonce, key, counter); + Chacha20Encrypt (state, buf, sz); + } } } #endif diff --git a/libi2pd/ChaCha20.h b/libi2pd/ChaCha20.h index 5a8ce145..da817847 100644 --- a/libi2pd/ChaCha20.h +++ b/libi2pd/ChaCha20.h @@ -9,6 +9,8 @@ #define LIBI2PD_CHACHA20_H #include #include +#include +#include #include "Crypto.h" #if LEGACY_OPENSSL @@ -19,10 +21,32 @@ namespace crypto const std::size_t CHACHA20_KEY_BYTES = 32; const std::size_t CHACHA20_NOUNCE_BYTES = 12; + struct Chacha20State + { + Chacha20State () {}; + Chacha20State (Chacha20State &&) = delete; + + Chacha20State & operator += (const Chacha20State & other) + { + for(int i = 0; i < 16; i++) + data[i] += other.data[i]; + return *this; + } + + void Copy(const Chacha20State & other) + { + memcpy(data, other.data, sizeof(uint32_t) * 16); + } + uint32_t data[16]; + }; + + void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter); + void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); + /** encrypt buf in place with chacha20 */ void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1); -} +} } #endif diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index dcd89064..85145804 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1172,6 +1172,55 @@ namespace crypto return ret; } + void AEADChaCha20Poly1305Encrypt (std::vector >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac) + { + if (bufs.empty ()) return; +#if LEGACY_OPENSSL + // generate one time poly key + uint64_t polyKey[8]; + memset(polyKey, 0, sizeof(polyKey)); + chacha20 ((uint8_t *)polyKey, 64, nonce, key, 0); + Poly1305 polyHash (polyKey); + // encrypt buffers + Chacha20State state; + Chacha20Init (state, nonce, key, 1); + size_t size = 0; + for (auto& it: bufs) + { + Chacha20Encrypt (state, (uint8_t *)it.first, it.second); + polyHash.Update ((uint8_t *)it.first, it.second); // after encryption + size += it.second; + } + // padding + uint8_t padding[16]; + memset (padding, 0, 16); + auto rem = size & 0x0F; // %16 + if (rem) + { + // padding2 + rem = 16 - rem; + polyHash.Update (padding, rem); + } + // adLen and msgLen + // adLen is always zero + htole64buf (padding + 8, size); + polyHash.Update (padding, 16); + // MAC + polyHash.Finish ((uint64_t *)mac); +#else + int outlen = 0; + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new (); + 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 (auto& it: bufs) + EVP_EncryptUpdate(ctx, (uint8_t *)it.first, &outlen, (uint8_t *)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); +#endif + } + // init and terminate /* std::vector > m_OpenSSLMutexes; diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 475f7fa3..79d16e50 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -282,6 +283,8 @@ namespace crypto // AEAD/ChaCha20/Poly1305 bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag + void AEADChaCha20Poly1305Encrypt (std::vector >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad + // init and terminate void InitCrypto (bool precomputation); void TerminateCrypto (); diff --git a/tests/test-aeadchacha20poly1305.cpp b/tests/test-aeadchacha20poly1305.cpp index dcd4b4d6..38717a62 100644 --- a/tests/test-aeadchacha20poly1305.cpp +++ b/tests/test-aeadchacha20poly1305.cpp @@ -51,4 +51,10 @@ int main () uint8_t buf1[114]; assert (i2p::crypto::AEADChaCha20Poly1305 (buf, 114, ad, 12, key, nonce, buf1, 114, false)); assert (memcmp (buf1, text, 114) == 0); + // test encryption of multiple buffers + memcpy (buf, text, 114); + std::vector > bufs{ std::make_pair (buf, 114) }; + i2p::crypto::AEADChaCha20Poly1305Encrypt (bufs, key, nonce, buf + 114); + i2p::crypto::AEADChaCha20Poly1305 (buf, 114, nullptr, 0, key, nonce, buf1, 114, false); + assert (memcmp (buf1, text, 114) == 0); } From ef6db64e9fa342c8627458ce020ed935c96922de Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Nov 2018 16:21:11 -0500 Subject: [PATCH 32/33] correct chacha20 for multiple messages --- libi2pd/ChaCha20.cpp | 96 +++++++++++++++-------------- libi2pd/ChaCha20.h | 29 +++++++-- libi2pd/Crypto.cpp | 6 +- tests/test-aeadchacha20poly1305.cpp | 2 +- 4 files changed, 78 insertions(+), 55 deletions(-) diff --git a/libi2pd/ChaCha20.cpp b/libi2pd/ChaCha20.cpp index dc6eb18f..0ee7cf75 100644 --- a/libi2pd/ChaCha20.cpp +++ b/libi2pd/ChaCha20.cpp @@ -15,9 +15,6 @@ namespace crypto { namespace chacha { -constexpr int rounds = 20; -constexpr std::size_t blocksize = 64; - void u32t8le(uint32_t v, uint8_t * p) { p[0] = v & 0xff; @@ -51,22 +48,14 @@ void quarterround(uint32_t *x, int a, int b, int c, int d) } -struct Block_t +void Chacha20Block::operator << (const Chacha20State & st) { - Block_t() {}; - Block_t(Block_t &&) = delete; - - uint8_t data[blocksize]; - - void operator << (const Chacha20State & st) - { - int i; - for (i = 0; i < 16; i++) - u32t8le(st.data[i], data + (i << 2)); - } -}; + int i; + for (i = 0; i < 16; i++) + u32t8le(st.data[i], data + (i << 2)); +} -void block(const Chacha20State &input, Block_t & block, int rounds) +void block (Chacha20State &input, int rounds) { int i; Chacha20State x; @@ -84,45 +73,60 @@ void block(const Chacha20State &input, Block_t & block, int rounds) quarterround(x.data, 3, 4, 9, 14); } x += input; - block << x; + input.block << x; } -} // namespace chacha - void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter) +void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter) +{ + state.data[0] = 0x61707865; + 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); + + state.data[12] = counter; + for (size_t i = 0; i < 3; i++) + state.data[13 + i] = chacha::u8t32le(nonce + i * 4); +} + +void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz) +{ + if (state.offset > 0) { - state.data[0] = 0x61707865; - 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); - - state.data[12] = counter; - for (size_t i = 0; i < 3; i++) - state.data[13 + i] = chacha::u8t32le(nonce + i * 4); + // 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 = 0; } - - void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz) + for (size_t i = 0; i < sz; i += chacha::blocksize) { - chacha::Block_t block; - for (size_t i = 0; i < sz; i += chacha::blocksize) - { - chacha::block(state, block, chacha::rounds); - state.data[12]++; - for (size_t j = i; j < i + chacha::blocksize; j++) - { - if (j >= sz) break; - buf[j] ^= block.data[j - i]; - } - } + 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]; + } } +} +} // namespace chacha + void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter) { - Chacha20State state; - Chacha20Init (state, nonce, key, counter); - Chacha20Encrypt (state, buf, sz); + chacha::Chacha20State state; + chacha::Chacha20Init (state, nonce, key, counter); + chacha::Chacha20Encrypt (state, buf, sz); } } } diff --git a/libi2pd/ChaCha20.h b/libi2pd/ChaCha20.h index da817847..0a2f3be0 100644 --- a/libi2pd/ChaCha20.h +++ b/libi2pd/ChaCha20.h @@ -18,12 +18,28 @@ 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 int rounds = 20; + + struct Chacha20State; + struct Chacha20Block + { + Chacha20Block () {}; + Chacha20Block (Chacha20Block &&) = delete; + + uint8_t data[blocksize]; + + void operator << (const Chacha20State & st); + }; struct Chacha20State { - Chacha20State () {}; + Chacha20State (): offset (0) {}; Chacha20State (Chacha20State &&) = delete; Chacha20State & operator += (const Chacha20State & other) @@ -38,10 +54,13 @@ namespace crypto memcpy(data, other.data, sizeof(uint32_t) * 16); } uint32_t data[16]; - }; + Chacha20Block block; + size_t offset; + }; void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter); - void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); + void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); +} /** encrypt buf in place with chacha20 */ void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1); diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 85145804..659fddcc 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1182,12 +1182,12 @@ namespace crypto chacha20 ((uint8_t *)polyKey, 64, nonce, key, 0); Poly1305 polyHash (polyKey); // encrypt buffers - Chacha20State state; - Chacha20Init (state, nonce, key, 1); + chacha::Chacha20State state; + chacha::Chacha20Init (state, nonce, key, 1); size_t size = 0; for (auto& it: bufs) { - Chacha20Encrypt (state, (uint8_t *)it.first, it.second); + chacha::Chacha20Encrypt (state, (uint8_t *)it.first, it.second); polyHash.Update ((uint8_t *)it.first, it.second); // after encryption size += it.second; } diff --git a/tests/test-aeadchacha20poly1305.cpp b/tests/test-aeadchacha20poly1305.cpp index 38717a62..d10ab2fc 100644 --- a/tests/test-aeadchacha20poly1305.cpp +++ b/tests/test-aeadchacha20poly1305.cpp @@ -53,7 +53,7 @@ int main () assert (memcmp (buf1, text, 114) == 0); // test encryption of multiple buffers memcpy (buf, text, 114); - std::vector > bufs{ std::make_pair (buf, 114) }; + std::vector > bufs{ std::make_pair (buf, 50), std::make_pair (buf + 50, 50), std::make_pair (buf + 100, 14) }; i2p::crypto::AEADChaCha20Poly1305Encrypt (bufs, key, nonce, buf + 114); i2p::crypto::AEADChaCha20Poly1305 (buf, 114, nullptr, 0, key, nonce, buf1, 114, false); assert (memcmp (buf1, text, 114) == 0); From 7692332f0e9df279e7e87822327aefbbea3f47a2 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Nov 2018 21:31:06 -0500 Subject: [PATCH 33/33] don't inialize Chacha20 state twice --- libi2pd/ChaCha20.cpp | 32 +++++++++++++++++--------------- libi2pd/ChaCha20.h | 24 ++++++++++++------------ libi2pd/Crypto.cpp | 17 ++++++++++------- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/libi2pd/ChaCha20.cpp b/libi2pd/ChaCha20.cpp index 0ee7cf75..30e02f42 100644 --- a/libi2pd/ChaCha20.cpp +++ b/libi2pd/ChaCha20.cpp @@ -1,12 +1,15 @@ -#include "ChaCha20.h" - -/** - This code is licensed under the MCGSI Public License - Copyright 2018 Jeff Becker - - Kovri go write your own code +/* +* Copyright (c) 2013-2018, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +* Kovri go write your own code +* +*/ - */ +#include "ChaCha20.h" #if LEGACY_OPENSSL namespace i2p @@ -91,6 +94,12 @@ void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * state.data[13 + i] = chacha::u8t32le(nonce + i * 4); } +void Chacha20SetCounter (Chacha20State& state, uint32_t counter) +{ + state.data[12] = counter; + state.offset = 0; +} + void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz) { if (state.offset > 0) @@ -121,13 +130,6 @@ void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz) } } // namespace chacha - - void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter) - { - chacha::Chacha20State state; - chacha::Chacha20Init (state, nonce, key, counter); - chacha::Chacha20Encrypt (state, buf, sz); - } } } #endif diff --git a/libi2pd/ChaCha20.h b/libi2pd/ChaCha20.h index 0a2f3be0..a5a8aafc 100644 --- a/libi2pd/ChaCha20.h +++ b/libi2pd/ChaCha20.h @@ -1,10 +1,13 @@ -/** - This code is licensed under the MCGSI Public License - Copyright 2018 Jeff Becker - - Kovri go write your own code - - */ +/* +* Copyright (c) 2013-2018, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +* Kovri go write your own code +* +*/ #ifndef LIBI2PD_CHACHA20_H #define LIBI2PD_CHACHA20_H #include @@ -59,12 +62,9 @@ namespace chacha }; void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter); - void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); + void Chacha20SetCounter (Chacha20State& state, uint32_t counter); + void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place } - - /** encrypt buf in place with chacha20 */ - void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1); - } } #endif diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 659fddcc..28df1399 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1087,11 +1087,12 @@ namespace crypto if (encrypt && len < msgLen + 16) return false; bool ret = true; #if LEGACY_OPENSSL + chacha::Chacha20State state; // generate one time poly key + chacha::Chacha20Init (state, nonce, key, 0); uint64_t polyKey[8]; memset(polyKey, 0, sizeof(polyKey)); - chacha20 ((uint8_t *)polyKey, 64, nonce, key, 0); - + chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64); // create Poly1305 hash Poly1305 polyHash (polyKey); if (!ad) adLen = 0; @@ -1108,17 +1109,18 @@ namespace crypto } } // encrypt/decrypt data and add to hash + Chacha20SetCounter (state, 1); if (buf != msg) memcpy (buf, msg, msgLen); if (encrypt) { - chacha20 (buf, msgLen, nonce, key, 1); // encrypt + chacha::Chacha20Encrypt (state, buf, msgLen); // encrypt polyHash.Update (buf, msgLen); // after encryption } else { polyHash.Update (buf, msgLen); // before decryption - chacha20 (buf, msgLen, nonce, key, 1); // decrypt + chacha::Chacha20Encrypt (state, buf, msgLen); // decrypt } auto rem = msgLen & 0x0F; // %16 @@ -1176,14 +1178,15 @@ namespace crypto { if (bufs.empty ()) return; #if LEGACY_OPENSSL + chacha::Chacha20State state; // generate one time poly key + chacha::Chacha20Init (state, nonce, key, 0); uint64_t polyKey[8]; memset(polyKey, 0, sizeof(polyKey)); - chacha20 ((uint8_t *)polyKey, 64, nonce, key, 0); + chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64); Poly1305 polyHash (polyKey); // encrypt buffers - chacha::Chacha20State state; - chacha::Chacha20Init (state, nonce, key, 1); + Chacha20SetCounter (state, 1); size_t size = 0; for (auto& it: bufs) {