Browse Source

Merge pull request #1274 from PurpleI2P/openssl

recent changes
pull/1348/head
orignal 6 years ago committed by GitHub
parent
commit
c212a30d33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      android/assets/i2pd.conf
  2. 5
      android/jni/i2pd_android.cpp
  3. 3
      android/jni/org_purplei2p_i2pd_I2PD_JNI.h
  4. 1
      android/res/values/strings.xml
  5. 7
      android/src/org/purplei2p/i2pd/DaemonSingleton.java
  6. 72
      android/src/org/purplei2p/i2pd/I2PDActivity.java
  7. 2
      android/src/org/purplei2p/i2pd/I2PD_JNI.java
  8. 6
      contrib/i2pd.conf
  9. 35
      contrib/rpm/i2pd-git.spec
  10. 3
      contrib/rpm/i2pd.spec
  11. 2
      contrib/tunnels.d/IRC-Irc2P.conf
  12. 5
      contrib/tunnels.d/README
  13. 18
      daemon/Daemon.cpp
  14. 77
      daemon/HTTPServer.cpp
  15. 1
      debian/docs
  16. 1
      debian/i2pd.dirs
  17. 2
      debian/i2pd.install
  18. 2
      debian/i2pd.links
  19. 151
      libi2pd/ChaCha20.cpp
  20. 68
      libi2pd/ChaCha20.h
  21. 22
      libi2pd/Config.cpp
  22. 94
      libi2pd/Crypto.cpp
  23. 40
      libi2pd/Crypto.h
  24. 2
      libi2pd/Ed25519.cpp
  25. 5
      libi2pd/Ed25519.h
  26. 1
      libi2pd/I2NPProtocol.h
  27. 6
      libi2pd/NTCP2.cpp
  28. 2
      libi2pd/NTCP2.h
  29. 100
      libi2pd/NetDb.cpp
  30. 14
      libi2pd/NetDb.hpp
  31. 240
      libi2pd/Poly1305.cpp
  32. 249
      libi2pd/Poly1305.h
  33. 3
      libi2pd/Siphash.h
  34. 125
      libi2pd/Timestamp.cpp
  35. 44
      libi2pd/Timestamp.h
  36. 15
      libi2pd/Transports.cpp
  37. 6
      libi2pd/util.cpp
  38. 4
      libi2pd_client/HTTPProxy.cpp
  39. 1
      qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml
  40. 6
      tests/test-aeadchacha20poly1305.cpp

12
android/assets/i2pd.conf

@ -37,7 +37,12 @@ port = 7070 @@ -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 @@ -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 @@ -80,3 +85,6 @@ verify = true
[limits]
transittunnels = 50
[persist]
profiles = false

5
android/jni/i2pd_android.cpp

@ -58,6 +58,11 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels @@ -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)
{

3
android/jni/org_purplei2p_i2pd_I2PD_JNI.h

@ -24,6 +24,9 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon @@ -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);

1
android/res/values/strings.xml

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
<string name="app_name">i2pd</string>
<string name="action_stop">Stop</string>
<string name="action_graceful_stop">Graceful Stop</string>
<string name="action_cancel_graceful_stop">Cancel Graceful Stop</string>
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
<string name="already_stopped">Already stopped</string>

7
android/src/org/purplei2p/i2pd/DaemonSingleton.java

@ -33,6 +33,13 @@ public class DaemonSingleton { @@ -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 {

72
android/src/org/purplei2p/i2pd/I2PDActivity.java

@ -13,13 +13,16 @@ import java.io.StringWriter; @@ -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; @@ -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 { @@ -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,24 @@ public class I2PDActivity extends Activity { @@ -119,6 +136,24 @@ 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) {
@ -205,7 +240,16 @@ public class I2PDActivity extends Activity { @@ -205,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;
}
@ -268,6 +312,32 @@ public class I2PDActivity extends Activity { @@ -268,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();

2
android/src/org/purplei2p/i2pd/I2PD_JNI.java

@ -12,6 +12,8 @@ public class I2PD_JNI { @@ -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() {

6
contrib/i2pd.conf

@ -93,6 +93,8 @@ ipv6 = false @@ -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
@ -223,3 +225,7 @@ verify = true @@ -223,3 +225,7 @@ verify = true
# inbound.quantity = 3
# outbound.length = 2
# outbound.quantity = 3
[persist]
## Save peer profiles on disk (default: true)
# profiles = true

35
contrib/rpm/i2pd-git.spec

@ -55,19 +55,22 @@ make %{?_smp_mflags} @@ -55,19 +55,22 @@ 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
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 +93,14 @@ getent passwd i2pd >/dev/null || \ @@ -90,14 +93,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

3
contrib/rpm/i2pd.spec

@ -53,6 +53,9 @@ make %{?_smp_mflags} @@ -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

2
contrib/tunnels.d/IRC-Irc2P.conf

@ -4,4 +4,4 @@ @@ -4,4 +4,4 @@
#port = 6668
#destination = irc.postman.i2p
#destinationport = 6667
#keys = irc-keys.dat
#keys = irc-keys.dat

5
contrib/tunnels.d/README

@ -1 +1,4 @@ @@ -1 +1,4 @@
In that directory you can store separated config files for every tunnel.
# 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

18
daemon/Daemon.cpp

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
#include "ClientContext.h"
#include "Crypto.h"
#include "UPnP.h"
#include "Timestamp.h"
#include "util.h"
#include "Event.h"
@ -41,6 +42,7 @@ namespace i2p @@ -41,6 +42,7 @@ namespace i2p
std::unique_ptr<i2p::http::HTTPServer> httpServer;
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
std::unique_ptr<i2p::transport::UPnP> UPnP;
std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
#ifdef WITH_EVENTS
std::unique_ptr<i2p::event::WebsocketServer> m_WebsocketServer;
#endif
@ -282,6 +284,13 @@ namespace i2p @@ -282,6 +284,13 @@ namespace i2p
d.UPnP->Start ();
}
bool nettime; i2p::config::GetOption("nettime.enabled", nettime);
if (nettime)
{
d.m_NTPSync = std::unique_ptr<i2p::util::NTPTimeSync>(new i2p::util::NTPTimeSync);
d.m_NTPSync->Start ();
}
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
bool ssu; i2p::config::GetOption("ssu", ssu);
LogPrint(eLogInfo, "Daemon: starting Transports");
@ -351,11 +360,18 @@ namespace i2p @@ -351,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");

77
daemon/HTTPServer.cpp

@ -155,6 +155,8 @@ namespace http { @@ -155,6 +155,8 @@ namespace http {
static void ShowPageHead (std::stringstream& s)
{
std::string webroot;
i2p::config::GetOption("http.webroot", webroot);
s <<
"<!DOCTYPE html>\r\n"
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
@ -173,16 +175,16 @@ namespace http { @@ -173,16 +175,16 @@ namespace http {
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
"<div class=wrapper>\r\n"
"<div class=left>\r\n"
" <a href=\"/\">Main page</a><br>\r\n<br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_LEASESETS << "\">LeaseSets</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
" <a href=\"/?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n";
" <a href=\"" << webroot << "\">Main page</a><br>\r\n<br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_LEASESETS << "\">LeaseSets</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n";
if (i2p::client::context.GetSAMBridge ())
s << " <a href=\"/?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n";
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n";
s <<
"</div>\r\n"
"<div class=right>";
@ -321,11 +323,12 @@ namespace http { @@ -321,11 +323,12 @@ namespace http {
void ShowLocalDestinations (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
s << "<b>Local Destinations:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetDestinations ())
{
auto ident = it.second->GetIdentHash ();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
}
@ -340,7 +343,7 @@ namespace http { @@ -340,7 +343,7 @@ namespace http {
{
auto ident = dest->GetIdentHash ();
auto& name = dest->GetNickname ();
s << "<a href=\"/?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">[ ";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">[ ";
s << name << " ]</a> &#8660; " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"<br>\r\n" << std::endl;
}
}
@ -510,33 +513,34 @@ namespace http { @@ -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 << "<b>Router Commands</b><br>\r\n<br>\r\n";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "&token=" << token << "\">Run peer test</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "&token=" << token << "\">Run peer test</a><br>\r\n";
//s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
if (i2p::context.AcceptsTunnels ())
s << " <a href=\"/?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
if (Daemon.gracefulShutdownInterval)
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n";
#elif defined(WIN32_APP)
if (i2p::util::DaemonWin32::Instance().isGraceful)
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
#endif
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n";
s << "<br>\r\n<b>Logging level</b><br>\r\n";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\">[none]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\">[error]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\">[none]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\">[error]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><br>\r\n";
}
void ShowTransitTunnels (std::stringstream& s)
@ -653,6 +657,7 @@ namespace http { @@ -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 { @@ -662,13 +667,14 @@ namespace http {
for (auto& it: sam->GetSessions ())
{
auto& name = it.second->localDestination->GetNickname ();
s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
s << name << " (" << it.first << ")</a><br>\r\n" << std::endl;
}
}
static void ShowSAMSession (std::stringstream& s, const std::string& id)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
s << "<b>SAM Session:</b><br>\r\n<br>\r\n";
auto sam = i2p::client::context.GetSAMBridge ();
if (!sam) {
@ -681,7 +687,7 @@ namespace http { @@ -681,7 +687,7 @@ namespace http {
return;
}
auto& ident = session->localDestination->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
s << "<br>\r\n";
s << "<b>Streams:</b><br>\r\n";
@ -701,11 +707,12 @@ namespace http { @@ -701,11 +707,12 @@ namespace http {
void ShowI2PTunnels (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetClientTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@ -714,7 +721,7 @@ namespace http { @@ -714,7 +721,7 @@ namespace http {
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "HTTP Proxy" << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@ -723,7 +730,7 @@ namespace http { @@ -723,7 +730,7 @@ namespace http {
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "SOCKS Proxy" << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@ -734,7 +741,7 @@ namespace http { @@ -734,7 +741,7 @@ namespace http {
for (auto& it: serverTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8658; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << ":" << it.second->GetLocalPort ();
@ -748,7 +755,7 @@ namespace http { @@ -748,7 +755,7 @@ namespace http {
for (auto& it: clientForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@ -761,7 +768,7 @@ namespace http { @@ -761,7 +768,7 @@ namespace http {
for (auto& it: serverForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@ -1025,10 +1032,12 @@ namespace http { @@ -1025,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 << "<b>SUCCESS</b>:&nbsp;Command accepted<br><br>\r\n";
s << "<a href=\"/?page=commands\">Back to commands list</a><br>\r\n";
s << "<a href=\"" << webroot << "?page=commands\">Back to commands list</a><br>\r\n";
s << "<p>You will be redirected in 5 seconds</b>";
res.add_header("Refresh", "5; url=/?page=commands");
res.add_header("Refresh", redirect.c_str());
}
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)

1
debian/docs vendored

@ -2,3 +2,4 @@ README.md @@ -2,3 +2,4 @@ README.md
contrib/i2pd.conf
contrib/subscriptions.txt
contrib/tunnels.conf
contrib/tunnels.d

1
debian/i2pd.dirs vendored

@ -1,3 +1,2 @@ @@ -1,3 +1,2 @@
etc/i2pd
etc/i2pd/tunnels.conf.d
var/lib/i2pd

2
debian/i2pd.install vendored

@ -3,5 +3,5 @@ contrib/i2pd.conf etc/i2pd/ @@ -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

2
debian/i2pd.links vendored

@ -1,5 +1,5 @@ @@ -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

151
libi2pd/ChaCha20.cpp

@ -1,21 +1,23 @@ @@ -1,21 +1,23 @@
#include "ChaCha20.h"
/**
This code is licensed under the MCGSI Public License
Copyright 2018 Jeff Becker
/*
* 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
*
*/
Kovri go write your own code
#include "ChaCha20.h"
*/
#if LEGACY_OPENSSL
namespace i2p
{
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;
@ -48,44 +50,18 @@ void quarterround(uint32_t *x, int a, int b, int c, int d) @@ -48,44 +50,18 @@ 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];
void operator << (const State_t & st)
{
int i;
for (i = 0; i < 16; i++)
u32t8le(st.data[i], data + (i << 2));
}
};
void Chacha20Block::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 (Chacha20State &input, int rounds)
{
int i;
State_t x;
Chacha20State x;
x.Copy(input);
for (i = rounds; i > 0; i -= 2)
@ -100,48 +76,61 @@ void block(const State_t &input, Block_t & block, int rounds) @@ -100,48 +76,61 @@ void block(const State_t &input, Block_t & block, int rounds)
quarterround(x.data, 3, 4, 9, 14);
}
x += input;
block << x;
input.block << x;
}
} // namespace chacha
void chacha20(uint8_t * buf, size_t sz, 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)
{
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];
}
}
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 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)
{
// 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;
}
for (size_t i = 0; i < sz; i += chacha::blocksize)
{
chacha::block(state, chacha::rounds);
state.data[12]++;
for (size_t j = i; j < i + chacha::blocksize; j++)
{
if (j >= sz)
{
state.offset = j & 0x3F; // % 64
break;
}
buf[j] ^= state.block.data[j - i];
}
}
}
} // namespace chacha
}
}
}
#endif

68
libi2pd/ChaCha20.h

@ -1,26 +1,72 @@ @@ -1,26 +1,72 @@
/**
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 <cstdint>
#include <cstring>
#include <inttypes.h>
#include <string.h>
#include "Crypto.h"
#if LEGACY_OPENSSL
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];
/** 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);
void operator << (const Chacha20State & st);
};
struct Chacha20State
{
Chacha20State (): offset (0) {};
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];
Chacha20Block block;
size_t offset;
};
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
}
}
}
#endif
#endif

22
libi2pd/Config.cpp

@ -88,6 +88,7 @@ namespace config { @@ -88,6 +88,7 @@ namespace config {
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )")
;
options_description httpproxy("HTTP Proxy options");
@ -236,10 +237,27 @@ namespace config { @@ -236,10 +237,27 @@ namespace config {
options_description ntcp2("NTCP2 Options");
ntcp2.add_options()
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
("ntcp2.published", value<bool>()->default_value(false), "Publish NTCP2 (default: disabled)")
("ntcp2.published", value<bool>()->default_value(false), "Publish NTCP2 (default: disabled)")
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
;
options_description nettime("Time sync options");
nettime.add_options()
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
("nettime.ntpservers", value<std::string>()->default_value(
"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<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
;
options_description persist("Network information persisting options");
persist.add_options()
("persist.profiles", value<bool>()->default_value(true), "Persist peer profiles (default: true)")
;
m_OptionsDesc
.add(general)
.add(limits)
@ -258,6 +276,8 @@ namespace config { @@ -258,6 +276,8 @@ namespace config {
.add(websocket)
.add(exploratory)
.add(ntcp2)
.add(nettime)
.add(persist)
;
}

94
libi2pd/Crypto.cpp

@ -1087,62 +1087,62 @@ namespace crypto @@ -1087,62 +1087,62 @@ namespace crypto
if (encrypt && len < msgLen + 16) return false;
bool ret = true;
#if LEGACY_OPENSSL
chacha::Chacha20State state;
// generate one time poly key
uint8_t polyKey[64];
chacha::Chacha20Init (state, nonce, key, 0);
uint64_t polyKey[8];
memset(polyKey, 0, sizeof(polyKey));
chacha20 (polyKey, 64, nonce, key, 0);
// create Poly1305 message
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
// create Poly1305 hash
Poly1305 polyHash (polyKey);
if (!ad) adLen = 0;
std::vector<uint8_t> 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
Chacha20SetCounter (state, 1);
if (buf != msg)
memcpy (buf, msg, msgLen);
if (encrypt)
{
chacha20 (buf, msgLen, nonce, key, 1); // encrypt
memcpy (polyMsg.data () + offset, buf, msgLen); // after encryption
chacha::Chacha20Encrypt (state, buf, msgLen); // encrypt
polyHash.Update (buf, msgLen); // after encryption
}
else
{
memcpy (polyMsg.data () + offset, buf, msgLen); // before decryption
chacha20 (buf, msgLen, nonce, key, 1); // decrypt
polyHash.Update (buf, msgLen); // before decryption
chacha::Chacha20Encrypt (state, buf, msgLen); // 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);
htole64buf (padding + 8, msgLen);
polyHash.Update (padding, 16);
if (encrypt)
{
// calculate Poly1305 tag and write in after encrypted data
Poly1305HMAC ((uint32_t *)(buf + msgLen), (uint32_t *)polyKey, polyMsg.data (), offset);
}
polyHash.Finish ((uint64_t *)(buf + msgLen));
else
{
uint32_t tag[8];
uint64_t tag[4];
// calculate Poly1305 tag
Poly1305HMAC (tag, (uint32_t *)polyKey, polyMsg.data (), offset);
polyHash.Finish (tag);
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
}
#else
@ -1174,6 +1174,56 @@ namespace crypto @@ -1174,6 +1174,56 @@ namespace crypto
return ret;
}
void AEADChaCha20Poly1305Encrypt (std::vector<std::pair<void*, std::size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
{
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));
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
Poly1305 polyHash (polyKey);
// encrypt buffers
Chacha20SetCounter (state, 1);
size_t size = 0;
for (auto& it: bufs)
{
chacha::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 <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;

40
libi2pd/Crypto.h

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
#include <inttypes.h>
#include <string>
#include <vector>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/aes.h>
@ -108,35 +109,16 @@ namespace crypto @@ -108,35 +109,16 @@ namespace crypto
void operator^=(const ChipherBlock& other) // XOR
{
#ifdef __AVX__
if (i2p::cpu::avx)
{
__asm__
(
"vmovups (%[buf]), %%xmm0 \n"
"vmovups (%[other]), %%xmm1 \n"
"vxorps %%xmm0, %%xmm1, %%xmm0 \n"
"vmovups %%xmm0, (%[buf]) \n"
:
: [buf]"r"(buf), [other]"r"(other.buf)
: "%xmm0", "%xmm1", "memory"
);
}
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
{
for (int i = 0; i < 4; i++)
reinterpret_cast<uint32_t *>(buf)[i] ^= reinterpret_cast<const uint32_t *>(other.buf)[i];
}
else
#endif
{
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];
}
}
{
for (int i = 0; i < 16; i++)
buf[i] ^= other.buf[i];
}
}
};
@ -301,6 +283,8 @@ namespace crypto @@ -301,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<std::pair<void*, std::size_t> >& 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 ();

2
libi2pd/Ed25519.cpp

@ -411,6 +411,7 @@ namespace crypto @@ -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 @@ -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)
{

5
libi2pd/Ed25519.h

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
#include <memory>
#include <openssl/bn.h>
#include "Crypto.h"
namespace i2p
{
@ -75,8 +76,10 @@ namespace crypto @@ -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 @@ -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:

1
libi2pd/I2NPProtocol.h

@ -75,6 +75,7 @@ namespace i2p @@ -75,6 +75,7 @@ namespace i2p
enum I2NPMessageType
{
eI2NPDummyMsg = 0,
eI2NPDatabaseStore = 1,
eI2NPDatabaseLookup = 2,
eI2NPDatabaseSearchReply = 3,

6
libi2pd/NTCP2.cpp

@ -695,8 +695,7 @@ namespace transport @@ -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 () + 3, size)); // TODO: should insert ri and not parse it twice
// TODO: process options
// ready to communicate
@ -861,7 +860,7 @@ namespace transport @@ -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, size));
break;
}
case eNTCP2BlkI2NPMessage:
@ -873,6 +872,7 @@ namespace transport @@ -873,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 ();

2
libi2pd/NTCP2.h

@ -73,6 +73,8 @@ namespace transport @@ -73,6 +73,8 @@ namespace transport
eNTCP2Banned, // 17
};
// RouterInfo flags
const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
typedef std::array<uint8_t, NTCP2_UNENCRYPTED_FRAME_MAX_SIZE> NTCP2FrameBuffer;
struct NTCP2Establisher

100
libi2pd/NetDb.cpp

@ -12,6 +12,7 @@ @@ -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"
@ -25,7 +26,7 @@ namespace data @@ -25,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)
{
}
@ -43,10 +44,12 @@ namespace data @@ -43,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));
}
@ -55,8 +58,9 @@ namespace data @@ -55,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 ();
@ -98,6 +102,10 @@ namespace data @@ -98,6 +102,10 @@ namespace data
case eI2NPDatabaseLookup:
HandleDatabaseLookupMsg (msg);
break;
case eI2NPDummyMsg:
// plain RouterInfo from NTCP2 with flags for now
HandleNTCP2RouterInfoMsg (msg);
break;
default: // WTF?
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
//i2p::HandleI2NPMessage (msg);
@ -162,22 +170,38 @@ namespace data @@ -162,22 +170,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<const RouterInfo> 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<const RouterInfo> NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated)
{
updated = true;
auto r = FindRouter (ident);
if (r)
{
@ -223,7 +247,7 @@ namespace data @@ -223,7 +247,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,
@ -518,7 +542,7 @@ namespace data @@ -518,7 +542,7 @@ namespace data
{
if (it->second->IsUnreachable ())
{
it->second->SaveProfile ();
if (m_PersistProfiles) it->second->SaveProfile ();
it = m_RouterInfos.erase (it);
continue;
}
@ -570,6 +594,17 @@ namespace data @@ -570,6 +594,17 @@ namespace data
transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr));
}
void NetDb::HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m)
{
uint8_t flood = m->GetPayload ()[0] & NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD;
bool updated;
auto ri = AddRouterInfo (m->GetPayload () + 1, m->GetPayloadLength () - 1, updated); // without flags
if (flood && updated && context.IsFloodfill () && ri)
{
auto floodMsg = CreateDatabaseStoreMsg (ri, 0); // replyToken = 0
Flood (ri->GetIdentHash (), floodMsg);
}
}
void NetDb::HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> m)
{
@ -649,22 +684,7 @@ namespace data @@ -649,22 +684,7 @@ namespace data
{
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen);
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
std::set<IdentHash> 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);
@ -965,6 +985,26 @@ namespace data @@ -965,6 +985,26 @@ namespace data
}
}
void NetDb::Flood (const IdentHash& ident, std::shared_ptr<I2NPMessage> floodMsg)
{
std::set<IdentHash> 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<const RouterInfo> NetDb::GetRandomRouter () const
{
return GetRandomRouter (

14
libi2pd/NetDb.hpp

@ -65,7 +65,8 @@ namespace data @@ -65,7 +65,8 @@ namespace data
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
void HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg);
void HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m);
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
@ -110,13 +111,16 @@ namespace data @@ -110,13 +111,16 @@ namespace data
void Run (); // exploratory thread
void Explore (int numDestinations);
void Publish ();
void Flood (const IdentHash& ident, std::shared_ptr<I2NPMessage> 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<typename Filter>
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len, bool& updated);
std::shared_ptr<const RouterInfo> AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated);
template<typename Filter>
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
private:
@ -140,6 +144,8 @@ namespace data @@ -140,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<RouterInfo> m_FloodfillBootstrap;

240
libi2pd/Poly1305.cpp

@ -6,246 +6,20 @@ @@ -6,246 +6,20 @@
Kovri go write your own code
*/
#if LEGACY_OPENSSL
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);
}
}
}
}
#endif

249
libi2pd/Poly1305.h

@ -9,20 +9,253 @@ @@ -9,20 +9,253 @@
#define LIBI2PD_POLY1305_H
#include <cstdint>
#include <cstring>
#include "Crypto.h"
#if LEGACY_OPENSSL
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<typename Int_t>
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);
}
}
#endif
#endif

3
libi2pd/Siphash.h

@ -9,7 +9,9 @@ @@ -9,7 +9,9 @@
#define SIPHASH_H
#include <cstdint>
#include "Crypto.h"
#if !OPENSSL_SIPHASH
namespace i2p
{
namespace crypto
@ -148,5 +150,6 @@ namespace crypto @@ -148,5 +150,6 @@ namespace crypto
}
}
}
#endif
#endif

125
libi2pd/Timestamp.cpp

@ -1,6 +1,10 @@ @@ -1,6 +1,10 @@
#include <inttypes.h>
#include <string.h>
#include <chrono>
#include <future>
#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include "Config.h"
#include "Log.h"
#include "I2PEndian.h"
#include "Timestamp.h"
@ -15,10 +19,30 @@ namespace i2p @@ -15,10 +19,30 @@ namespace i2p
{
namespace util
{
static uint64_t GetLocalMillisecondsSinceEpoch ()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count ();
}
static uint32_t GetLocalHoursSinceEpoch ()
{
return std::chrono::duration_cast<std::chrono::hours>(
std::chrono::system_clock::now().time_since_epoch()).count ();
}
static uint64_t GetLocalSecondsSinceEpoch ()
{
return std::chrono::duration_cast<std::chrono::seconds>(
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 +72,112 @@ namespace util @@ -48,19 +72,112 @@ 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, "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);
}
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);
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)
{
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 ();
});
}
}
uint64_t GetMillisecondsSinceEpoch ()
{
return GetLocalMillisecondsSinceEpoch () + g_TimeOffset*1000;
}
uint32_t GetHoursSinceEpoch ()
{
return GetLocalHoursSinceEpoch () + g_TimeOffset/3600;
}
uint64_t GetSecondsSinceEpoch ()
{
return GetLocalSecondsSinceEpoch () + g_TimeOffset;
}
}
}

44
libi2pd/Timestamp.h

@ -2,29 +2,43 @@ @@ -2,29 +2,43 @@
#define TIMESTAMP_H__
#include <inttypes.h>
#include <chrono>
#include <thread>
#include <vector>
#include <string>
#include <boost/asio.hpp>
namespace i2p
{
namespace util
{
inline uint64_t GetMillisecondsSinceEpoch ()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count ();
}
uint64_t GetMillisecondsSinceEpoch ();
uint32_t GetHoursSinceEpoch ();
uint64_t GetSecondsSinceEpoch ();
inline uint32_t GetHoursSinceEpoch ()
class NTPTimeSync
{
return std::chrono::duration_cast<std::chrono::hours>(
std::chrono::system_clock::now().time_since_epoch()).count ();
}
public:
inline uint64_t GetSecondsSinceEpoch ()
{
return std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()).count ();
}
NTPTimeSync ();
~NTPTimeSync ();
void Start ();
void Stop ();
private:
void Run ();
void Sync ();
private:
bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread;
boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer;
int m_SyncInterval;
std::vector<std::string> m_NTPServersList;
};
}
}

15
libi2pd/Transports.cpp

@ -35,8 +35,11 @@ namespace transport @@ -35,8 +35,11 @@ namespace transport
void DHKeysPairSupplier::Stop ()
{
m_IsRunning = false;
m_Acquired.notify_one ();
{
std::unique_lock<std::mutex> l(m_AcquiredMutex);
m_IsRunning = false;
m_Acquired.notify_one ();
}
if (m_Thread)
{
m_Thread->join ();
@ -50,19 +53,20 @@ namespace transport @@ -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<std::mutex> l(m_AcquiredMutex);
std::unique_lock<std::mutex> l(m_AcquiredMutex);
if (!m_IsRunning) break;
m_Acquired.wait (l); // wait for element gets acquired
}
}
@ -813,7 +817,6 @@ namespace transport @@ -813,7 +817,6 @@ namespace transport
if (profile)
{
profile->TunnelNonReplied();
profile->Save(it->first);
}
std::unique_lock<std::mutex> l(m_PeersMutex);
it = m_Peers.erase (it);

6
libi2pd/util.cpp

@ -21,9 +21,9 @@ @@ -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 */ @@ -45,7 +45,7 @@ http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */
}
}
return 0;
}
}*/
#else /* !WIN32 => UNIX */
#include <sys/types.h>
#include <ifaddrs.h>

4
libi2pd_client/HTTPProxy.cpp

@ -390,6 +390,10 @@ namespace proxy { @@ -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);

1
qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml

@ -35,6 +35,7 @@ @@ -35,6 +35,7 @@
<translation type="qt" />
<releases>
<release version="2.22.0" date="2018-11-09" />
<release version="2.21.1" date="2018-10-22" />
<release version="2.21.0" date="2018-10-04" />
</releases>

6
tests/test-aeadchacha20poly1305.cpp

@ -51,4 +51,10 @@ int main () @@ -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<std::pair<void*, std::size_t> > 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);
}

Loading…
Cancel
Save