Browse Source

Merge pull request #1249 from PurpleI2P/openssl

2.21.0
pull/1268/head
orignal 6 years ago committed by GitHub
parent
commit
5e31e533e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      ChangeLog
  2. 2
      Win32/installer.iss
  3. 3
      android/AndroidManifest.xml
  4. 6
      android/build.gradle
  5. 24
      android/jni/Android.mk
  6. 42
      android/src/org/purplei2p/i2pd/ForegroundService.java
  7. 24
      android_binary_only/jni/Android.mk
  8. 6
      appveyor.yml
  9. 3
      contrib/rpm/i2pd.spec
  10. 10
      daemon/HTTPServer.cpp
  11. 6
      debian/changelog
  12. 67
      libi2pd/Crypto.cpp
  13. 51
      libi2pd/Crypto.h
  14. 57
      libi2pd/Identity.cpp
  15. 124
      libi2pd/NTCP2.cpp
  16. 23
      libi2pd/NTCP2.h
  17. 11
      libi2pd/NetDb.cpp
  18. 2
      libi2pd/Reseed.cpp
  19. 20
      libi2pd/RouterContext.cpp
  20. 5
      libi2pd/RouterContext.h
  21. 8
      libi2pd/RouterInfo.cpp
  22. 69
      libi2pd/Signature.cpp
  23. 123
      libi2pd/Signature.h
  24. 4
      libi2pd/version.h
  25. 4
      qt/i2pd_qt/TunnelConfig.cpp
  26. 2
      qt/i2pd_qt/android/AndroidManifest.xml
  27. 3
      qt/i2pd_qt/i2pd_qt.pro
  28. 2
      qt/i2pd_qt/mainwindow.h

14
ChangeLog

@ -1,6 +1,20 @@ @@ -1,6 +1,20 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.21.0] - 2018-10-04
### Added
- EdDSA, x25519 and SipHash from openssl 1.1.1
- NTCP2 ipv6 incoming connections
- Show total number of destination's outgoing tags in the web console
### Changed
- Android build with openssl 1.1.1/boost 1.64
- Bandwidth classes 'P' and 'X' don't add 'O' anymore
### Fixed
- Update own RouterInfo if no SSU
- Recognize 'P' and 'X' routers as high bandwidth without 'O'
- NTCP address doesn't disappear if NTCP2 enabled
- Android with api 26+
## [2.20.0] - 2018-08-23
### Added
- Full implementation of NTCP2

2
Win32/installer.iss

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
#define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.20.0"
#define I2Pd_ver "2.21.0"
#define I2Pd_Publisher "PurpleI2P"
[Setup]

3
android/AndroidManifest.xml

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
package="org.purplei2p.i2pd"
android:installLocation="auto"
android:versionCode="1"
android:versionName="2.20.0">
android:versionName="2.21.0">
<uses-sdk
android:minSdkVersion="14"
@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- normal perm -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- required in API 26+ -->
<application
android:allowBackup="true"
android:icon="@drawable/icon"

6
android/build.gradle

@ -17,6 +17,10 @@ repositories { @@ -17,6 +17,10 @@ repositories {
}
}
dependencies {
compile 'com.android.support:support-compat:28.0.0'
}
android {
compileSdkVersion 28
buildToolsVersion "28.0.1"
@ -25,7 +29,7 @@ android { @@ -25,7 +29,7 @@ android {
targetSdkVersion 28
minSdkVersion 14
versionCode 1
versionName "2.20.0"
versionName "2.21.0"
ndk {
abiFilters 'armeabi-v7a'
abiFilters 'x86'

24
android/jni/Android.mk

@ -25,43 +25,43 @@ include $(BUILD_SHARED_LIBRARY) @@ -25,43 +25,43 @@ include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_system
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_date_time
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_filesystem
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_program_options
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
LOCAL_STATIC_LIBRARIES := crypto
include $(PREBUILT_STATIC_LIBRARY)

42
android/src/org/purplei2p/i2pd/ForegroundService.java

@ -1,12 +1,17 @@ @@ -1,12 +1,17 @@
package org.purplei2p.i2pd;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
@ -104,22 +109,41 @@ public class ForegroundService extends Service { @@ -104,22 +109,41 @@ public class ForegroundService extends Service {
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, I2PDActivity.class), 0);
// If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : "";
// Set the info for the views that show in the notification panel.
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.app_name)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
Notification notification = new NotificationCompat.Builder(this, channelId)
.setOngoing(true)
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
.setPriority(Notification.PRIORITY_DEFAULT)
.setCategory(Notification.CATEGORY_SERVICE)
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.app_name)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
.build();
// Send the notification.
//mNM.notify(NOTIFICATION, notification);
startForeground(NOTIFICATION, notification);
shown=true;
shown = true;
}
@RequiresApi(Build.VERSION_CODES.O)
private synchronized String createNotificationChannel() {
String channelId = getString(R.string.app_name);
CharSequence channelName = "I2Pd service";
NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
//chan.setLightColor(Color.PURPLE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
service.createNotificationChannel(chan);
return channelId;
}
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
}

24
android_binary_only/jni/Android.mk

@ -26,43 +26,43 @@ include $(BUILD_EXECUTABLE) @@ -26,43 +26,43 @@ include $(BUILD_EXECUTABLE)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_system
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_date_time
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_filesystem
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_program_options
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
LOCAL_STATIC_LIBRARIES := crypto
include $(PREBUILT_STATIC_LIBRARY)

6
appveyor.yml

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
version: 2.20.{build}
version: 2.21.{build}
pull_requests:
do_not_increment_build_number: true
branches:
@ -18,9 +18,9 @@ environment: @@ -18,9 +18,9 @@ environment:
install:
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu "
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
- if "%MSYSTEM%" == "MINGW64" (
c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc"

3
contrib/rpm/i2pd.spec

@ -96,6 +96,9 @@ getent passwd i2pd >/dev/null || \ @@ -96,6 +96,9 @@ getent passwd i2pd >/dev/null || \
%changelog
* Thu Oct 4 2018 orignal <i2porignal@yandex.ru> - 2.21.0
- update to 2.21.0
* Thu Aug 23 2018 orignal <i2porignal@yandex.ru> - 2.20.0
- update to 2.20.0

10
daemon/HTTPServer.cpp

@ -381,10 +381,12 @@ namespace http { @@ -381,10 +381,12 @@ namespace http {
s << "<br>\r\n";
s << "<b>Tags</b><br>Incoming: <i>" << dest->GetNumIncomingTags () << "</i><br>";
if (!dest->GetSessions ().empty ()) {
s << "<div class='slide'><label for='slide-tags'>Outgoing:</label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n";
for (const auto& it: dest->GetSessions ())
s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
s << "</p>\r\n</div>\r\n";
std::stringstream tmp_s; uint32_t out_tags = 0;
for (const auto& it: dest->GetSessions ()) {
tmp_s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
out_tags = out_tags + it.second->GetNumOutgoingTags ();
}
s << "<div class='slide'><label for='slide-tags'>Outgoing: <i>" << out_tags << "</i></label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n" << tmp_s.str () << "</p>\r\n</div>\r\n";
} else
s << "Outgoing: <i>0</i><br>\r\n";
s << "<br>\r\n";

6
debian/changelog vendored

@ -1,3 +1,9 @@ @@ -1,3 +1,9 @@
i2pd (2.21.0-1) unstable; urgency=medium
* updated to version 2.21.0/0.9.37
-- orignal <orignal@i2pmail.org> Thu, 4 Oct 2018 16:00:00 +0000
i2pd (2.20.0-1) unstable; urgency=medium
* updated to version 2.20.0/0.9.36

67
libi2pd/Crypto.cpp

@ -12,9 +12,8 @@ @@ -12,9 +12,8 @@
#if LEGACY_OPENSSL
#include "ChaCha20.h"
#include "Poly1305.h"
#else
#include <openssl/evp.h>
#endif
#include "Ed25519.h"
#include "I2PEndian.h"
#include "Log.h"
@ -278,6 +277,70 @@ namespace crypto @@ -278,6 +277,70 @@ namespace crypto
BN_free (pk);
}
// x25519
X25519Keys::X25519Keys ()
{
#if OPENSSL_X25519
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
#else
m_Ctx = BN_CTX_new ();
#endif
}
X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
{
#if OPENSSL_X25519
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey
#else
memcpy (m_PrivateKey, priv, 32);
memcpy (m_PublicKey, pub, 32);
m_Ctx = BN_CTX_new ();
#endif
}
X25519Keys::~X25519Keys ()
{
#if OPENSSL_X25519
EVP_PKEY_CTX_free (m_Ctx);
if (m_Pkey)
EVP_PKEY_free (m_Pkey);
#else
BN_CTX_free (m_Ctx);
#endif
}
void X25519Keys::GenerateKeys ()
{
#if OPENSSL_X25519
m_Pkey = nullptr;
EVP_PKEY_keygen_init (m_Ctx);
EVP_PKEY_keygen (m_Ctx, &m_Pkey);
EVP_PKEY_CTX_free (m_Ctx);
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
size_t len = 32;
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
#else
RAND_bytes (m_PrivateKey, 32);
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
#endif
}
void X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
{
#if OPENSSL_X25519
EVP_PKEY_derive_init (m_Ctx);
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
EVP_PKEY_derive_set_peer (m_Ctx, pkey);
size_t len = 32;
EVP_PKEY_derive (m_Ctx, shared, &len);
EVP_PKEY_free (pkey);
#else
GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
#endif
}
// ElGamal
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
{

51
libi2pd/Crypto.h

@ -13,11 +13,24 @@ @@ -13,11 +13,24 @@
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/engine.h>
#include <openssl/opensslv.h>
#include "Base.h"
#include "Tag.h"
#include "CPU.h"
// recognize openssl version and features
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# define LEGACY_OPENSSL 1
#else
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# define OPENSSL_SIPHASH 1
# endif
#endif
namespace i2p
{
namespace crypto
@ -48,6 +61,31 @@ namespace crypto @@ -48,6 +61,31 @@ namespace crypto
uint8_t m_PublicKey[256];
};
// x25519
class X25519Keys
{
public:
X25519Keys ();
X25519Keys (const uint8_t * priv, const uint8_t * pub); // for RouterContext
~X25519Keys ();
void GenerateKeys ();
const uint8_t * GetPublicKey () const { return m_PublicKey; };
void Agree (const uint8_t * pub, uint8_t * shared);
private:
uint8_t m_PublicKey[32];
#if OPENSSL_X25519
EVP_PKEY_CTX * m_Ctx;
EVP_PKEY * m_Pkey;
#else
BN_CTX * m_Ctx;
uint8_t m_PrivateKey[32];
#endif
};
// ElGamal
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false);
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
@ -260,18 +298,7 @@ namespace crypto @@ -260,18 +298,7 @@ namespace crypto
}
}
// take care about openssl version
#include <openssl/opensslv.h>
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# define LEGACY_OPENSSL 1
#else
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# endif
#endif
// take care about openssl below 1.1.0
#if LEGACY_OPENSSL
// define getters and setters introduced in 1.1.0
inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)

57
libi2pd/Identity.cpp

@ -72,29 +72,10 @@ namespace data @@ -72,29 +72,10 @@ namespace data
break;
}
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
{
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256 - 128
excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 128, excessLen);
break;
}
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
{
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384 - 128
excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 128, excessLen);
break;
}
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
{
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512 - 128
excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 128, excessLen);
break;
}
LogPrint (eLogError, "Identity: RSA signing key type ", (int)type, " is not supported");
break;
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
{
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
@ -368,32 +349,10 @@ namespace data @@ -368,32 +349,10 @@ namespace data
break;
}
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
{
uint8_t signingKey[i2p::crypto::RSASHA2562048_KEY_LENGTH];
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
size_t excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256- 128
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
UpdateVerifier (new i2p::crypto:: RSASHA2562048Verifier (signingKey));
break;
}
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
{
uint8_t signingKey[i2p::crypto::RSASHA3843072_KEY_LENGTH];
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
size_t excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384- 128
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
UpdateVerifier (new i2p::crypto:: RSASHA3843072Verifier (signingKey));
break;
}
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
{
uint8_t signingKey[i2p::crypto::RSASHA5124096_KEY_LENGTH];
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
size_t excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512- 128
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
UpdateVerifier (new i2p::crypto:: RSASHA5124096Verifier (signingKey));
break;
}
LogPrint (eLogError, "Identity: RSA signing key type ", (int)keyType, " is not supported");
break;
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
{
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
@ -564,13 +523,9 @@ namespace data @@ -564,13 +523,9 @@ namespace data
m_Signer.reset (new i2p::crypto::ECDSAP521Signer (m_SigningPrivateKey));
break;
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
m_Signer.reset (new i2p::crypto::RSASHA2562048Signer (m_SigningPrivateKey));
break;
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
m_Signer.reset (new i2p::crypto::RSASHA3843072Signer (m_SigningPrivateKey));
break;
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
m_Signer.reset (new i2p::crypto::RSASHA5124096Signer (m_SigningPrivateKey));
LogPrint (eLogError, "Identity: RSA signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
break;
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH));
@ -642,7 +597,7 @@ namespace data @@ -642,7 +597,7 @@ namespace data
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Create EdDSA");
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
// no break here
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);

124
libi2pd/NTCP2.cpp

@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
#include "Log.h"
#include "I2PEndian.h"
#include "Crypto.h"
#include "Ed25519.h"
#include "Siphash.h"
#include "RouterContext.h"
#include "Transports.h"
@ -31,19 +30,14 @@ namespace transport @@ -31,19 +30,14 @@ namespace transport
NTCP2Establisher::NTCP2Establisher ():
m_SessionRequestBuffer (nullptr), m_SessionCreatedBuffer (nullptr), m_SessionConfirmedBuffer (nullptr)
{
m_Ctx = BN_CTX_new ();
CreateEphemeralKey ();
}
NTCP2Establisher::~NTCP2Establisher ()
{
BN_CTX_free (m_Ctx);
delete[] m_SessionRequestBuffer;
delete[] m_SessionCreatedBuffer;
delete[] m_SessionConfirmedBuffer;
#if OPENSSL_X25519
EVP_PKEY_free (m_EphemeralPkey);
#endif
}
void NTCP2Establisher::MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived)
@ -59,7 +53,7 @@ namespace transport @@ -59,7 +53,7 @@ namespace transport
HMAC(EVP_sha256(), tempKey, 32, m_CK, 33, derived, &len);
}
void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, const uint8_t * priv, const uint8_t * rs, const uint8_t * epub)
void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub)
{
static const uint8_t protocolNameHash[] =
{
@ -83,20 +77,20 @@ namespace transport @@ -83,20 +77,20 @@ namespace transport
SHA256_Update (&ctx, m_H, 32);
SHA256_Update (&ctx, epub, 32);
SHA256_Final (m_H, &ctx);
// x25519 between rs and priv
// x25519 between pub and priv
uint8_t inputKeyMaterial[32];
i2p::crypto::GetEd25519 ()->ScalarMul (pub, priv, inputKeyMaterial, m_Ctx); // rs*priv
priv.Agree (pub, inputKeyMaterial);
MixKey (inputKeyMaterial, m_K);
}
void NTCP2Establisher::KDF1Alice ()
{
KeyDerivationFunction1 (m_RemoteStaticKey, GetPriv (), m_RemoteStaticKey, GetPub ());
KeyDerivationFunction1 (m_RemoteStaticKey, m_EphemeralKeys, m_RemoteStaticKey, GetPub ());
}
void NTCP2Establisher::KDF1Bob ()
{
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetNTCP2StaticPrivateKey (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetStaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
}
void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub)
@ -120,20 +114,10 @@ namespace transport @@ -120,20 +114,10 @@ namespace transport
SHA256_Update (&ctx, epub, 32);
SHA256_Final (m_H, &ctx);
// x25519 between remote pub and priv
// x25519 between remote pub and ephemaral priv
uint8_t inputKeyMaterial[32];
#if OPENSSL_X25519
auto pctx = EVP_PKEY_CTX_new (m_EphemeralPkey, NULL);
EVP_PKEY_derive_init (pctx);
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, GetRemotePub (), 32);
EVP_PKEY_derive_set_peer (pctx, pkey);
size_t len = 32;
EVP_PKEY_derive (pctx, inputKeyMaterial, &len);
EVP_PKEY_free (pkey);
EVP_PKEY_CTX_free (pctx);
#else
i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), GetPriv (), inputKeyMaterial, m_Ctx);
#endif
m_EphemeralKeys.Agree (GetRemotePub (), inputKeyMaterial);
MixKey (inputKeyMaterial, m_K);
}
@ -150,34 +134,20 @@ namespace transport @@ -150,34 +134,20 @@ namespace transport
void NTCP2Establisher::KDF3Alice ()
{
uint8_t inputKeyMaterial[32];
i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), i2p::context.GetNTCP2StaticPrivateKey (), inputKeyMaterial, m_Ctx);
i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
MixKey (inputKeyMaterial, m_K);
}
void NTCP2Establisher::KDF3Bob ()
{
uint8_t inputKeyMaterial[32];
i2p::crypto::GetEd25519 ()->ScalarMul (m_RemoteStaticKey, m_EphemeralPrivateKey, inputKeyMaterial, m_Ctx);
m_EphemeralKeys.Agree (m_RemoteStaticKey, inputKeyMaterial);
MixKey (inputKeyMaterial, m_K);
}
void NTCP2Establisher::CreateEphemeralKey ()
{
#if OPENSSL_X25519
m_EphemeralPkey = nullptr;
EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
EVP_PKEY_keygen_init (pctx);
EVP_PKEY_keygen (pctx, &m_EphemeralPkey);
EVP_PKEY_CTX_free (pctx);
// TODO: remove, after switch to m_EphemeralPkey
size_t len = 32;
EVP_PKEY_get_raw_public_key (m_EphemeralPkey, m_EphemeralPublicKey, &len);
len = 32;
EVP_PKEY_get_raw_private_key (m_EphemeralPkey, m_EphemeralPrivateKey, &len);
#else
RAND_bytes (m_EphemeralPrivateKey, 32);
i2p::crypto::GetEd25519 ()->ScalarMulB (m_EphemeralPrivateKey, m_EphemeralPublicKey, m_Ctx);
#endif
m_EphemeralKeys.GenerateKeys ();
}
void NTCP2Establisher::CreateSessionRequestMessage ()
@ -420,6 +390,10 @@ namespace transport @@ -420,6 +390,10 @@ namespace transport
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
m_Server (server), m_Socket (m_Server.GetService ()),
m_IsEstablished (false), m_IsTerminated (false),
m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr),
#if OPENSSL_SIPHASH
m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr),
#endif
m_NextReceivedLen (0), m_NextReceivedBuffer (nullptr), m_NextSendBuffer (nullptr),
m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0), m_IsSending (false)
{
@ -442,6 +416,12 @@ namespace transport @@ -442,6 +416,12 @@ namespace transport
{
delete[] m_NextReceivedBuffer;
delete[] m_NextSendBuffer;
#if OPENSSL_SIPHASH
if (m_SendSipKey) EVP_PKEY_free (m_SendSipKey);
if (m_ReceiveSipKey) EVP_PKEY_free (m_ReceiveSipKey);
if (m_SendMDCtx) EVP_MD_CTX_destroy (m_SendMDCtx);
if (m_ReceiveMDCtx) EVP_MD_CTX_destroy (m_ReceiveMDCtx);
#endif
}
void NTCP2Session::Terminate ()
@ -651,8 +631,7 @@ namespace transport @@ -651,8 +631,7 @@ namespace transport
// Alice data phase keys
m_SendKey = m_Kab;
m_ReceiveKey = m_Kba;
m_SendSipKey = m_Sipkeysab;
m_ReceiveSipKey = m_Sipkeysba;
SetSipKeys (m_Sipkeysab, m_Sipkeysba);
memcpy (m_ReceiveIV.buf, m_Sipkeysba + 16, 8);
memcpy (m_SendIV.buf, m_Sipkeysab + 16, 8);
Established ();
@ -704,8 +683,7 @@ namespace transport @@ -704,8 +683,7 @@ namespace transport
// Bob data phase keys
m_SendKey = m_Kba;
m_ReceiveKey = m_Kab;
m_SendSipKey = m_Sipkeysba;
m_ReceiveSipKey = m_Sipkeysab;
SetSipKeys (m_Sipkeysba, m_Sipkeysab);
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
// payload
@ -731,6 +709,12 @@ namespace transport @@ -731,6 +709,12 @@ namespace transport
SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail);
return;
}
if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes
{
LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed");
SendTerminationAndTerminate (eNTCP2Message3Error);
return;
}
auto addr = ri.GetNTCP2Address (false); // any NTCP2 address
if (!addr)
{
@ -763,6 +747,26 @@ namespace transport @@ -763,6 +747,26 @@ namespace transport
}
}
void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey)
{
#if OPENSSL_SIPHASH
m_SendSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, sendSipKey, 16);
m_SendMDCtx = EVP_MD_CTX_create ();
EVP_PKEY_CTX *ctx = nullptr;
EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, m_SendSipKey);
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
m_ReceiveSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16);
m_ReceiveMDCtx = EVP_MD_CTX_create ();
ctx = nullptr;
EVP_DigestSignInit (m_ReceiveMDCtx, &ctx, NULL, NULL, m_ReceiveSipKey);
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
#else
m_SendSipKey = sendSipKey;
m_ReceiveSipKey = receiveSipKey;
#endif
}
void NTCP2Session::ClientLogin ()
{
SendSessionRequest ();
@ -793,7 +797,14 @@ namespace transport @@ -793,7 +797,14 @@ namespace transport
}
else
{
#if OPENSSL_SIPHASH
EVP_DigestSignInit (m_ReceiveMDCtx, nullptr, nullptr, nullptr, nullptr);
EVP_DigestSignUpdate (m_ReceiveMDCtx, m_ReceiveIV.buf, 8);
size_t l = 8;
EVP_DigestSignFinal (m_ReceiveMDCtx, m_ReceiveIV.buf, &l);
#else
i2p::crypto::Siphash<8> (m_ReceiveIV.buf, m_ReceiveIV.buf, 8, m_ReceiveSipKey);
#endif
// m_NextReceivedLen comes from the network in BigEndian
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
@ -801,7 +812,16 @@ namespace transport @@ -801,7 +812,16 @@ namespace transport
{
if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer;
m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen];
Receive ();
boost::system::error_code ec;
size_t moreBytes = m_Socket.available(ec);
if (!ec && moreBytes >= m_NextReceivedLen)
{
// read and process messsage immediately if avaliable
moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec);
HandleReceived (ec, moreBytes);
}
else
Receive ();
}
else
{
@ -914,7 +934,14 @@ namespace transport @@ -914,7 +934,14 @@ namespace transport
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
m_NextSendBuffer = new uint8_t[len + 16 + 2];
i2p::crypto::AEADChaCha20Poly1305 (payload, len, nullptr, 0, m_SendKey, nonce, m_NextSendBuffer + 2, len + 16, true);
#if OPENSSL_SIPHASH
EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr);
EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8);
size_t l = 8;
EVP_DigestSignFinal (m_SendMDCtx, m_SendIV.buf, &l);
#else
i2p::crypto::Siphash<8> (m_SendIV.buf, m_SendIV.buf, 8, m_SendSipKey);
#endif
// length must be in BigEndian
htobe16buf (m_NextSendBuffer, (len + 16) ^ le16toh (m_SendIV.key));
LogPrint (eLogDebug, "NTCP2: sent length ", len + 16);
@ -1029,6 +1056,11 @@ namespace transport @@ -1029,6 +1056,11 @@ namespace transport
m_SendQueue.push_back (it);
if (!m_IsSending)
SendQueue ();
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
{
LogPrint (eLogWarning, "NTCP2: outgoing messages queue size exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
Terminate ();
}
}
void NTCP2Session::SendLocalRouterInfo ()

23
libi2pd/NTCP2.h

@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <boost/asio.hpp>
#include "Crypto.h"
#include "util.h"
#include "RouterInfo.h"
#include "TransportSession.h"
@ -38,6 +39,7 @@ namespace transport @@ -38,6 +39,7 @@ namespace transport
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
const int NTCP2_CLOCK_SKEW = 60; // in seconds
const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up
enum NTCP2BlockType
{
@ -78,8 +80,7 @@ namespace transport @@ -78,8 +80,7 @@ namespace transport
NTCP2Establisher ();
~NTCP2Establisher ();
const uint8_t * GetPub () const { return m_EphemeralPublicKey; };
const uint8_t * GetPriv () const { return m_EphemeralPrivateKey; };
const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); };
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
@ -95,7 +96,7 @@ namespace transport @@ -95,7 +96,7 @@ namespace transport
void KDF3Bob ();
void MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived);
void KeyDerivationFunction1 (const uint8_t * pub, const uint8_t * priv, const uint8_t * rs, const uint8_t * epub); // for SessionRequest, (pub, priv) for DH
void KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub); // for SessionRequest, (pub, priv) for DH
void KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub); // for SessionCreate
void CreateEphemeralKey ();
@ -109,11 +110,8 @@ namespace transport @@ -109,11 +110,8 @@ namespace transport
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
BN_CTX * m_Ctx;
uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], m_RemoteEphemeralPublicKey[32]; // x25519
#if OPENSSL_X25519
EVP_PKEY * m_EphemeralPkey;
#endif
i2p::crypto::X25519Keys m_EphemeralKeys;
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/;
i2p::data::IdentHash m_RemoteIdentHash;
uint16_t m3p2Len;
@ -151,6 +149,7 @@ namespace transport @@ -151,6 +149,7 @@ namespace transport
void CreateNonce (uint64_t seqn, uint8_t * nonce);
void KeyDerivationFunctionDataPhase ();
void SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey);
// establish
void SendSessionRequest ();
@ -190,7 +189,13 @@ namespace transport @@ -190,7 +189,13 @@ namespace transport
std::unique_ptr<NTCP2Establisher> m_Establisher;
// data phase
uint8_t m_Kab[33], m_Kba[32], m_Sipkeysab[33], m_Sipkeysba[32];
const uint8_t * m_SendKey, * m_ReceiveKey, * m_SendSipKey, * m_ReceiveSipKey;
const uint8_t * m_SendKey, * m_ReceiveKey;
#if OPENSSL_SIPHASH
EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey;
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
#else
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
#endif
uint16_t m_NextReceivedLen;
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
union

11
libi2pd/NetDb.cpp

@ -130,18 +130,17 @@ namespace data @@ -130,18 +130,17 @@ namespace data
lastDestinationCleanup = ts;
}
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL) // update timestamp and publish
{
Publish ();
i2p::context.UpdateTimestamp (ts);
if (!m_HiddenMode) Publish ();
lastPublish = ts;
}
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
{
auto numRouters = m_RouterInfos.size ();
if (numRouters == 0)
{
throw std::runtime_error("No known routers, reseed seems to be totally failed");
}
if (!numRouters)
throw std::runtime_error("No known routers, reseed seems to be totally failed");
else // we have peers now
m_FloodfillBootstrap = nullptr;
if (numRouters < 2500 || ts - lastExploratory >= 90)

2
libi2pd/Reseed.cpp

@ -219,7 +219,7 @@ namespace data @@ -219,7 +219,7 @@ namespace data
BN_CTX * bnctx = BN_CTX_new ();
BIGNUM * s = BN_new (), * n = BN_new ();
BN_bin2bn (signature, signatureLength, s);
BN_bin2bn (it->second, i2p::crypto::RSASHA5124096_KEY_LENGTH, n);
BN_bin2bn (it->second, 512, n); // RSA 4096 assumed
BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n
uint8_t * enSigBuf = new uint8_t[signatureLength];
i2p::crypto::bn2buf (s, enSigBuf, signatureLength);

20
libi2pd/RouterContext.cpp

@ -497,6 +497,12 @@ namespace i2p @@ -497,6 +497,12 @@ namespace i2p
}
}
void RouterContext::UpdateTimestamp (uint64_t ts)
{
if (ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL)
UpdateRouterInfo ();
}
bool RouterContext::Load ()
{
std::ifstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ifstream::in | std::ifstream::binary);
@ -620,4 +626,18 @@ namespace i2p @@ -620,4 +626,18 @@ namespace i2p
{
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, false) : false;
}
i2p::crypto::X25519Keys& RouterContext::GetStaticKeys ()
{
if (!m_StaticKeys)
{
if (!m_NTCP2Keys) NewNTCP2Keys ();
auto x = new i2p::crypto::X25519Keys (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey);
if (!m_StaticKeys)
m_StaticKeys.reset (x);
else
delete x;
}
return *m_StaticKeys;
}
}

5
libi2pd/RouterContext.h

@ -62,6 +62,7 @@ namespace i2p @@ -62,6 +62,7 @@ namespace i2p
const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; };
const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; };
const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; };
i2p::crypto::X25519Keys& GetStaticKeys ();
uint32_t GetUptime () const;
uint32_t GetStartupTime () const { return m_StartupTime; };
@ -102,6 +103,7 @@ namespace i2p @@ -102,6 +103,7 @@ namespace i2p
void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session
void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from NTCP2 session
void UpdateStats ();
void UpdateTimestamp (uint64_t ts); // in seconds, called from NetDb before publishing
void CleanupDestination (); // garlic destination
// implements LocalDestination
@ -133,7 +135,7 @@ namespace i2p @@ -133,7 +135,7 @@ namespace i2p
i2p::data::RouterInfo m_RouterInfo;
i2p::data::PrivateKeys m_Keys;
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
uint64_t m_LastUpdateTime;
uint64_t m_LastUpdateTime; // in seconds
bool m_AcceptsTunnels, m_IsFloodfill;
uint64_t m_StartupTime; // in seconds since epoch
uint64_t m_BandwidthLimit; // allowed bandwidth
@ -143,6 +145,7 @@ namespace i2p @@ -143,6 +145,7 @@ namespace i2p
int m_NetID;
std::mutex m_GarlicMutex;
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
std::unique_ptr<i2p::crypto::X25519Keys> m_StaticKeys;
};
extern RouterContext context;

8
libi2pd/RouterInfo.cpp

@ -375,7 +375,7 @@ namespace data @@ -375,7 +375,7 @@ namespace data
break;
case CAPS_FLAG_EXTRA_BANDWIDTH1:
case CAPS_FLAG_EXTRA_BANDWIDTH2:
m_Caps |= Caps::eExtraBandwidth;
m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth;
break;
case CAPS_FLAG_HIDDEN:
m_Caps |= Caps::eHidden;
@ -406,16 +406,14 @@ namespace data @@ -406,16 +406,14 @@ namespace data
if (m_Caps & eExtraBandwidth) caps += (m_Caps & eHighBandwidth) ?
CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X'
CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P'
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
else
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
caps += CAPS_FLAG_FLOODFILL; // floodfill
}
else
{
if (m_Caps & eExtraBandwidth)
{
caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
}
else
caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth
}

69
libi2pd/Signature.cpp

@ -52,29 +52,7 @@ namespace crypto @@ -52,29 +52,7 @@ namespace crypto
}
#endif
#if OPENSSL_EDDSA
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey)
{
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
// TODO: check public key
m_MDCtx = EVP_MD_CTX_create ();
EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
}
EDDSA25519Signer::~EDDSA25519Signer ()
{
EVP_MD_CTX_destroy (m_MDCtx);
EVP_PKEY_free (m_Pkey);
}
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
size_t l = 64;
EVP_DigestSign (m_MDCtx, signature, &l, buf, len);
}
#else
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey)
EDDSA25519SignerCompat::EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey)
{
// expand key
Ed25519::ExpandPrivateKey (signingPrivateKey, m_ExpandedPrivateKey);
@ -94,13 +72,56 @@ namespace crypto @@ -94,13 +72,56 @@ namespace crypto
BN_CTX_free (ctx);
}
EDDSA25519SignerCompat::~EDDSA25519SignerCompat ()
{
}
void EDDSA25519SignerCompat::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature);
}
#if OPENSSL_EDDSA
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey):
m_Fallback (nullptr)
{
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH];
size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len);
if (memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
{
LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback");
EVP_PKEY_free (m_Pkey);
m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey);
}
else
{
m_MDCtx = EVP_MD_CTX_create ();
EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
}
}
EDDSA25519Signer::~EDDSA25519Signer ()
{
if (m_Fallback) delete m_Fallback;
else
{
EVP_MD_CTX_destroy (m_MDCtx);
EVP_PKEY_free (m_Pkey);
}
}
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature);
if (m_Fallback) return m_Fallback->Sign (buf, len, signature);
else
{
size_t l = 64;
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
memcpy (signature, sig, 64);
}
}
#endif
}

123
libi2pd/Signature.h

@ -6,7 +6,6 @@ @@ -6,7 +6,6 @@
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include "Crypto.h"
#include "Ed25519.h"
@ -149,6 +148,7 @@ namespace crypto @@ -149,6 +148,7 @@ namespace crypto
enum { hashLen = 64 };
};
// EcDSA
template<typename Hash, int curve, size_t keyLen>
class ECDSAVerifier: public Verifier
{
@ -269,97 +269,6 @@ namespace crypto @@ -269,97 +269,6 @@ namespace crypto
CreateECDSARandomKeys (NID_secp521r1, ECDSAP521_KEY_LENGTH, signingPrivateKey, signingPublicKey);
}
// RSA
template<typename Hash, int type, size_t keyLen>
class RSAVerifier: public Verifier
{
public:
RSAVerifier (const uint8_t * signingKey)
{
m_PublicKey = RSA_new ();
RSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, keyLen, NULL) /* n */ , BN_dup (GetRSAE ()) /* d */, NULL);
}
~RSAVerifier ()
{
RSA_free (m_PublicKey);
}
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
uint8_t digest[Hash::hashLen];
Hash::CalculateHash (buf, len, digest);
return RSA_verify (type, digest, Hash::hashLen, signature, GetSignatureLen (), m_PublicKey);
}
size_t GetPublicKeyLen () const { return keyLen; }
size_t GetSignatureLen () const { return keyLen; }
size_t GetPrivateKeyLen () const { return GetSignatureLen ()*2; };
private:
RSA * m_PublicKey;
};
template<typename Hash, int type, size_t keyLen>
class RSASigner: public Signer
{
public:
RSASigner (const uint8_t * signingPrivateKey)
{
m_PrivateKey = RSA_new ();
RSA_set0_key (m_PrivateKey, BN_bin2bn (signingPrivateKey, keyLen, NULL), /* n */
BN_dup (GetRSAE ()) /* e */, BN_bin2bn (signingPrivateKey + keyLen, keyLen, NULL) /* d */);
}
~RSASigner ()
{
RSA_free (m_PrivateKey);
}
void Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
uint8_t digest[Hash::hashLen];
Hash::CalculateHash (buf, len, digest);
unsigned int signatureLen = keyLen;
RSA_sign (type, digest, Hash::hashLen, signature, &signatureLen, m_PrivateKey);
}
private:
RSA * m_PrivateKey;
};
inline void CreateRSARandomKeys (size_t publicKeyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
{
RSA * rsa = RSA_new ();
BIGNUM * e = BN_dup (GetRSAE ()); // make it non-const
RSA_generate_key_ex (rsa, publicKeyLen*8, e, NULL);
const BIGNUM * n, * d, * e1;
RSA_get0_key (rsa, &n, &e1, &d);
bn2buf (n, signingPrivateKey, publicKeyLen);
bn2buf (d, signingPrivateKey + publicKeyLen, publicKeyLen);
bn2buf (n, signingPublicKey, publicKeyLen);
BN_free (e); // this e is not assigned to rsa->e
RSA_free (rsa);
}
// RSA_SHA256_2048
const size_t RSASHA2562048_KEY_LENGTH = 256;
typedef RSAVerifier<SHA256Hash, NID_sha256, RSASHA2562048_KEY_LENGTH> RSASHA2562048Verifier;
typedef RSASigner<SHA256Hash, NID_sha256, RSASHA2562048_KEY_LENGTH> RSASHA2562048Signer;
// RSA_SHA384_3072
const size_t RSASHA3843072_KEY_LENGTH = 384;
typedef RSAVerifier<SHA384Hash, NID_sha384, RSASHA3843072_KEY_LENGTH> RSASHA3843072Verifier;
typedef RSASigner<SHA384Hash, NID_sha384, RSASHA3843072_KEY_LENGTH> RSASHA3843072Signer;
// RSA_SHA512_4096
const size_t RSASHA5124096_KEY_LENGTH = 512;
typedef RSAVerifier<SHA512Hash, NID_sha512, RSASHA5124096_KEY_LENGTH> RSASHA5124096Verifier;
typedef RSASigner<SHA512Hash, NID_sha512, RSASHA5124096_KEY_LENGTH> RSASHA5124096Signer;
// EdDSA
class EDDSA25519Verifier: public Verifier
@ -385,6 +294,24 @@ namespace crypto @@ -385,6 +294,24 @@ namespace crypto
#endif
};
class EDDSA25519SignerCompat: public Signer
{
public:
EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
// we pass signingPublicKey to check if it matches private key
~EDDSA25519SignerCompat ();
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
private:
uint8_t m_ExpandedPrivateKey[64];
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
};
#if OPENSSL_EDDSA
class EDDSA25519Signer: public Signer
{
public:
@ -394,19 +321,17 @@ namespace crypto @@ -394,19 +321,17 @@ namespace crypto
~EDDSA25519Signer ();
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
#if !OPENSSL_EDDSA
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
#endif
private:
#if OPENSSL_EDDSA
EVP_PKEY * m_Pkey;
EVP_MD_CTX * m_MDCtx;
EDDSA25519SignerCompat * m_Fallback;
};
#else
uint8_t m_ExpandedPrivateKey[64];
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
typedef EDDSA25519SignerCompat EDDSA25519Signer;
#endif
};
inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
{

4
libi2pd/version.h

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
#define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 20
#define I2PD_VERSION_MINOR 21
#define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
#define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9
#define I2P_VERSION_MICRO 36
#define I2P_VERSION_MICRO 37
#define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)

4
qt/i2pd_qt/TunnelConfig.cpp

@ -31,16 +31,15 @@ void ClientTunnelConfig::saveToStringStream(std::stringstream& out) { @@ -31,16 +31,15 @@ void ClientTunnelConfig::saveToStringStream(std::stringstream& out) {
out << "address=" << address << "\n"
<< "port=" << port << "\n"
<< "destination=" << dest << "\n"
<< "keys=" << keys << "\n"
<< "destinationport=" << destinationPort << "\n"
<< "signaturetype=" << sigType << "\n";
if(!keys.empty()) out << "keys=" << keys << "\n";
}
void ServerTunnelConfig::saveToStringStream(std::stringstream& out) {
out << "host=" << host << "\n"
<< "port=" << port << "\n"
<< "keys=" << keys << "\n"
<< "signaturetype=" << sigType << "\n"
<< "inport=" << inPort << "\n"
<< "accesslist=" << accessList << "\n"
@ -49,5 +48,6 @@ void ServerTunnelConfig::saveToStringStream(std::stringstream& out) { @@ -49,5 +48,6 @@ void ServerTunnelConfig::saveToStringStream(std::stringstream& out) {
<< "address=" << address << "\n"
<< "hostoverride=" << hostOverride << "\n"
<< "webircpassword=" << webircpass << "\n";
if(!keys.empty()) out << "keys=" << keys << "\n";
}

2
qt/i2pd_qt/android/AndroidManifest.xml

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.20.0" android:versionCode="1" android:installLocation="auto">
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.21.0" android:versionCode="1" android:installLocation="auto">
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- <application android:hardwareAccelerated="true" -->

3
qt/i2pd_qt/i2pd_qt.pro

@ -97,7 +97,8 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ @@ -97,7 +97,8 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
pagewithbackbutton.cpp \
widgetlock.cpp \
widgetlockregistry.cpp \
logviewermanager.cpp
logviewermanager.cpp \
../../libi2pd/NTCP2.cpp
#qt creator does not handle this well
#SOURCES += $$files(../../libi2pd/*.cpp)

2
qt/i2pd_qt/mainwindow.h

@ -726,8 +726,8 @@ private: @@ -726,8 +726,8 @@ private:
// mandatory params
std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST);
int port = section.second.get<int> (I2P_SERVER_TUNNEL_PORT);
std::string keys = section.second.get<std::string> (I2P_SERVER_TUNNEL_KEYS);
// optional params
std::string keys = section.second.get<std::string> (I2P_SERVER_TUNNEL_KEYS, "");
int inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0);
std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, "");
std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, "");

Loading…
Cancel
Save