Compare commits

..

4 Commits

Author SHA1 Message Date
orignal
d610e6c4c1 Merge pull request #2132 from PurpleI2P/openssl
recent changes
2024-12-06 20:14:40 -05:00
orignal
35352f1497 Merge pull request #2125 from PurpleI2P/openssl
Recent changes
2024-11-19 18:27:05 -05:00
orignal
e695f1e060 Merge pull request #2118 from PurpleI2P/openssl
recent changes
2024-10-28 20:33:07 -04:00
orignal
ecc635e9bc Merge pull request #2105 from PurpleI2P/openssl
2.54.0
2024-10-08 10:01:35 -04:00
24 changed files with 661 additions and 144 deletions

View File

@@ -29,6 +29,7 @@ DAEMON_SRC_DIR := daemon
# import source files lists # import source files lists
include filelist.mk include filelist.mk
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),no) USE_STATIC := $(or $(USE_STATIC),no)
USE_UPNP := $(or $(USE_UPNP),no) USE_UPNP := $(or $(USE_UPNP),no)
DEBUG := $(or $(DEBUG),yes) DEBUG := $(or $(DEBUG),yes)

View File

@@ -30,6 +30,13 @@ ifeq ($(USE_UPNP),yes)
INCFLAGS += -I${UPNPROOT}/include INCFLAGS += -I${UPNPROOT}/include
endif endif
ifeq ($(USE_AESNI),yes)
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
NEEDED_CXXFLAGS += -maes
DEFINES += -D__AES__
endif
endif
install: all install: all
install -d ${PREFIX}/bin install -d ${PREFIX}/bin
install -m 755 ${I2PD} ${PREFIX}/bin install -m 755 ${I2PD} ${PREFIX}/bin

View File

@@ -51,6 +51,13 @@ ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP DEFINES += -DUSE_UPNP
endif endif
ifeq ($(USE_AESNI),yes)
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
NEEDED_CXXFLAGS += -maes
DEFINES += -D__AES__
endif
endif
install: all install: all
install -d ${PREFIX}/bin install -d ${PREFIX}/bin
install -m 755 ${I2PD} ${PREFIX}/bin install -m 755 ${I2PD} ${PREFIX}/bin

View File

@@ -42,6 +42,12 @@ ifeq ($(USE_WIN32_APP), yes)
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif endif
ifeq ($(USE_AESNI),yes)
NEEDED_CXXFLAGS += -maes
LDFLAGS += -maes
DEFINES += -D__AES__
endif
ifeq ($(USE_ASLR),yes) ifeq ($(USE_ASLR),yes)
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
endif endif

View File

@@ -25,5 +25,9 @@ endif
OSARCH = $(shell uname -p) OSARCH = $(shell uname -p)
ifneq ($(OSARCH),powerpc) ifneq ($(OSARCH),powerpc)
ifeq ($(USE_AESNI),yes)
CXXFLAGS += -D__AES__ -maes
else
CXXFLAGS += -msse CXXFLAGS += -msse
endif
endif endif

View File

@@ -29,6 +29,7 @@ project(
) )
# configurable options # configurable options
option(WITH_AESNI "Use AES-NI instructions set" ON)
option(WITH_HARDENING "Use hardening compiler flags" OFF) option(WITH_HARDENING "Use hardening compiler flags" OFF)
option(WITH_LIBRARY "Build library" ON) option(WITH_LIBRARY "Build library" ON)
option(WITH_BINARY "Build binary" ON) option(WITH_BINARY "Build binary" ON)
@@ -184,6 +185,16 @@ if(UNIX)
endif() endif()
endif() endif()
# Note: AES-NI and AVX is available on x86-based CPU's.
# Here also ARM64 implementation, but currently we don't support it.
# MSVC is not supported due to different ASM processing, so we hope OpenSSL has its own checks to run optimized code.
if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386"))
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
endif()
add_definitions(-D__AES__)
endif()
if(WITH_ADDRSANITIZER) if(WITH_ADDRSANITIZER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
@@ -324,6 +335,7 @@ message(STATUS "Architecture : ${ARCHITECTURE}")
message(STATUS "Compiler flags : ${CMAKE_CXX_FLAGS}") message(STATUS "Compiler flags : ${CMAKE_CXX_FLAGS}")
message(STATUS "Install prefix: : ${CMAKE_INSTALL_PREFIX}") message(STATUS "Install prefix: : ${CMAKE_INSTALL_PREFIX}")
message(STATUS "Options:") message(STATUS "Options:")
message(STATUS " AESNI : ${WITH_AESNI}")
message(STATUS " HARDENING : ${WITH_HARDENING}") message(STATUS " HARDENING : ${WITH_HARDENING}")
message(STATUS " LIBRARY : ${WITH_LIBRARY}") message(STATUS " LIBRARY : ${WITH_LIBRARY}")
message(STATUS " BINARY : ${WITH_BINARY}") message(STATUS " BINARY : ${WITH_BINARY}")

View File

@@ -149,10 +149,12 @@ namespace util
LogPrint(eLogDebug, "FS: Certificates directory: ", certsdir); LogPrint(eLogDebug, "FS: Certificates directory: ", certsdir);
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
if (!ssu && i2p::config::IsDefault ("precomputation.elgamal")) if (!ssu && i2p::config::IsDefault ("precomputation.elgamal"))
precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly
i2p::crypto::InitCrypto (precomputation); i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces

68
libi2pd/CPU.cpp Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2013-2023, 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
*/
#include "CPU.h"
#include "Log.h"
#ifndef bit_AES
#define bit_AES (1 << 25)
#endif
#if defined(__GNUC__) && __GNUC__ < 6 && IS_X86
#include <cpuid.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace i2p
{
namespace cpu
{
bool aesni = false;
inline bool cpu_support_aes()
{
#if IS_X86
#if defined(__clang__)
# if (__clang_major__ >= 6)
__builtin_cpu_init();
# endif
return __builtin_cpu_supports("aes");
#elif (defined(__GNUC__) && __GNUC__ >= 6)
__builtin_cpu_init();
return __builtin_cpu_supports("aes");
#elif (defined(__GNUC__) && __GNUC__ < 6)
int cpu_info[4];
bool flag = false;
__cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
if (cpu_info[0] >= 0x00000001) {
__cpuid(0x00000001, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
flag = ((cpu_info[2] & bit_AES) != 0);
}
return flag;
#elif defined(_MSC_VER)
int cpu_info[4];
__cpuid(cpu_info, 1);
return ((cpu_info[2] & bit_AES) != 0);
#endif
#endif
return false;
}
void Detect(bool AesSwitch, bool force)
{
if ((cpu_support_aes() && AesSwitch) || (AesSwitch && force)) {
aesni = true;
}
LogPrint(eLogInfo, "AESNI ", (aesni ? "enabled" : "disabled"));
}
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2023, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -21,4 +21,20 @@
# define IS_X86_64 0 # define IS_X86_64 0
#endif #endif
#if defined(__AES__) && !defined(_MSC_VER) && IS_X86
# define SUPPORTS_AES 1
#else
# define SUPPORTS_AES 0
#endif
namespace i2p
{
namespace cpu
{
extern bool aesni;
void Detect(bool AesSwitch, bool force);
}
}
#endif #endif

View File

@@ -117,7 +117,7 @@ namespace config {
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels") ("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url") ("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper") ("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper")
("httpproxy.senduseragent", value<bool>()->default_value(false), "Pass through user's User-Agent if enabled. Disabled by default") ("httpproxy.senduseragent", value<bool>()->default_value(false), "Pass through user's User-Agent if enabled. Disabled by deafult")
("httpproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type") ("httpproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type")
("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("0,4"), "Local destination's LeaseSet encryption type") ("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("0,4"), "Local destination's LeaseSet encryption type")
("httpproxy.i2cp.leaseSetPrivKey", value<std::string>()->default_value(""), "LeaseSet private key") ("httpproxy.i2cp.leaseSetPrivKey", value<std::string>()->default_value(""), "LeaseSet private key")
@@ -315,11 +315,11 @@ namespace config {
("persist.addressbook", value<bool>()->default_value(true), "Persist full addresses (default: true)") ("persist.addressbook", value<bool>()->default_value(true), "Persist full addresses (default: true)")
; ;
options_description cpuext("CPU encryption extensions options. Deprecated"); options_description cpuext("CPU encryption extensions options");
cpuext.add_options() cpuext.add_options()
("cpuext.aesni", bool_switch()->default_value(true), "Deprecated option") ("cpuext.aesni", bool_switch()->default_value(true), "Use auto detection for AESNI CPU extensions. If false, AESNI will be not used")
("cpuext.avx", bool_switch()->default_value(false), "Deprecated option") ("cpuext.avx", bool_switch()->default_value(false), "Deprecated option")
("cpuext.force", bool_switch()->default_value(false), "Deprecated option") ("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines")
; ;
options_description meshnets("Meshnet transports options"); options_description meshnets("Meshnet transports options");

View File

@@ -19,7 +19,6 @@
#if OPENSSL_HKDF #if OPENSSL_HKDF
#include <openssl/kdf.h> #include <openssl/kdf.h>
#endif #endif
#include "CPU.h"
#include "Crypto.h" #include "Crypto.h"
#include "Ed25519.h" #include "Ed25519.h"
#include "I2PEndian.h" #include "I2PEndian.h"
@@ -516,105 +515,429 @@ namespace crypto
} }
// AES // AES
ECBEncryption::ECBEncryption () #if SUPPORTS_AES
#define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
"movaps %%xmm1, %%xmm4 \n" \
"pslldq $4, %%xmm4 \n" \
"pxor %%xmm4, %%xmm1 \n" \
"pslldq $4, %%xmm4 \n" \
"pxor %%xmm4, %%xmm1 \n" \
"pslldq $4, %%xmm4 \n" \
"pxor %%xmm4, %%xmm1 \n" \
"pxor %%xmm2, %%xmm1 \n" \
"movaps %%xmm1, "#round0"(%[sched]) \n" \
"aeskeygenassist $0, %%xmm1, %%xmm4 \n" \
"pshufd $0xaa, %%xmm4, %%xmm2 \n" \
"movaps %%xmm3, %%xmm4 \n" \
"pslldq $4, %%xmm4 \n" \
"pxor %%xmm4, %%xmm3 \n" \
"pslldq $4, %%xmm4 \n" \
"pxor %%xmm4, %%xmm3 \n" \
"pslldq $4, %%xmm4 \n" \
"pxor %%xmm4, %%xmm3 \n" \
"pxor %%xmm2, %%xmm3 \n" \
"movaps %%xmm3, "#round1"(%[sched]) \n"
#endif
#if SUPPORTS_AES
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{ {
m_Ctx = EVP_CIPHER_CTX_new (); __asm__
(
"movups (%[key]), %%xmm1 \n"
"movups 16(%[key]), %%xmm3 \n"
"movaps %%xmm1, (%[sched]) \n"
"movaps %%xmm3, 16(%[sched]) \n"
"aeskeygenassist $1, %%xmm3, %%xmm2 \n"
KeyExpansion256(32,48)
"aeskeygenassist $2, %%xmm3, %%xmm2 \n"
KeyExpansion256(64,80)
"aeskeygenassist $4, %%xmm3, %%xmm2 \n"
KeyExpansion256(96,112)
"aeskeygenassist $8, %%xmm3, %%xmm2 \n"
KeyExpansion256(128,144)
"aeskeygenassist $16, %%xmm3, %%xmm2 \n"
KeyExpansion256(160,176)
"aeskeygenassist $32, %%xmm3, %%xmm2 \n"
KeyExpansion256(192,208)
"aeskeygenassist $64, %%xmm3, %%xmm2 \n"
// key expansion final
"pshufd $0xff, %%xmm2, %%xmm2 \n"
"movaps %%xmm1, %%xmm4 \n"
"pslldq $4, %%xmm4 \n"
"pxor %%xmm4, %%xmm1 \n"
"pslldq $4, %%xmm4 \n"
"pxor %%xmm4, %%xmm1 \n"
"pslldq $4, %%xmm4 \n"
"pxor %%xmm4, %%xmm1 \n"
"pxor %%xmm2, %%xmm1 \n"
"movups %%xmm1, 224(%[sched]) \n"
: // output
: [key]"r"((const uint8_t *)key), [sched]"r"(GetKeySchedule ()) // input
: "%xmm1", "%xmm2", "%xmm3", "%xmm4", "memory" // clogged
);
}
#endif
#if SUPPORTS_AES
#define EncryptAES256(sched) \
"pxor (%["#sched"]), %%xmm0 \n" \
"aesenc 16(%["#sched"]), %%xmm0 \n" \
"aesenc 32(%["#sched"]), %%xmm0 \n" \
"aesenc 48(%["#sched"]), %%xmm0 \n" \
"aesenc 64(%["#sched"]), %%xmm0 \n" \
"aesenc 80(%["#sched"]), %%xmm0 \n" \
"aesenc 96(%["#sched"]), %%xmm0 \n" \
"aesenc 112(%["#sched"]), %%xmm0 \n" \
"aesenc 128(%["#sched"]), %%xmm0 \n" \
"aesenc 144(%["#sched"]), %%xmm0 \n" \
"aesenc 160(%["#sched"]), %%xmm0 \n" \
"aesenc 176(%["#sched"]), %%xmm0 \n" \
"aesenc 192(%["#sched"]), %%xmm0 \n" \
"aesenc 208(%["#sched"]), %%xmm0 \n" \
"aesenclast 224(%["#sched"]), %%xmm0 \n"
#endif
void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
{
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
:
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
}
else
#endif
{
AES_encrypt (in->buf, out->buf, &m_Key);
}
} }
ECBEncryption::~ECBEncryption () #if SUPPORTS_AES
#define DecryptAES256(sched) \
"pxor 224(%["#sched"]), %%xmm0 \n" \
"aesdec 208(%["#sched"]), %%xmm0 \n" \
"aesdec 192(%["#sched"]), %%xmm0 \n" \
"aesdec 176(%["#sched"]), %%xmm0 \n" \
"aesdec 160(%["#sched"]), %%xmm0 \n" \
"aesdec 144(%["#sched"]), %%xmm0 \n" \
"aesdec 128(%["#sched"]), %%xmm0 \n" \
"aesdec 112(%["#sched"]), %%xmm0 \n" \
"aesdec 96(%["#sched"]), %%xmm0 \n" \
"aesdec 80(%["#sched"]), %%xmm0 \n" \
"aesdec 64(%["#sched"]), %%xmm0 \n" \
"aesdec 48(%["#sched"]), %%xmm0 \n" \
"aesdec 32(%["#sched"]), %%xmm0 \n" \
"aesdec 16(%["#sched"]), %%xmm0 \n" \
"aesdeclast (%["#sched"]), %%xmm0 \n"
#endif
void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
{ {
if (m_Ctx) #if SUPPORTS_AES
EVP_CIPHER_CTX_free (m_Ctx); if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
:
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
}
else
#endif
{
AES_decrypt (in->buf, out->buf, &m_Key);
}
} }
void ECBEncryption::Encrypt (const uint8_t * in, uint8_t * out) #if SUPPORTS_AES
#define CallAESIMC(offset) \
"movaps "#offset"(%[shed]), %%xmm0 \n" \
"aesimc %%xmm0, %%xmm0 \n" \
"movaps %%xmm0, "#offset"(%[shed]) \n"
#endif
void ECBEncryption::SetKey (const AESKey& key)
{ {
EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_ecb(), NULL, m_Key, NULL); #if SUPPORTS_AES
EVP_CIPHER_CTX_set_padding (m_Ctx, 0); if(i2p::cpu::aesni)
int len; {
EVP_EncryptUpdate (m_Ctx, out, &len, in, 16); ExpandKey (key);
EVP_EncryptFinal_ex (m_Ctx, out + len, &len); }
else
#endif
{
AES_set_encrypt_key (key, 256, &m_Key);
}
} }
ECBDecryption::ECBDecryption () void ECBDecryption::SetKey (const AESKey& key)
{ {
m_Ctx = EVP_CIPHER_CTX_new (); #if SUPPORTS_AES
if(i2p::cpu::aesni)
{
ExpandKey (key); // expand encryption key first
// then invert it using aesimc
__asm__
(
CallAESIMC(16)
CallAESIMC(32)
CallAESIMC(48)
CallAESIMC(64)
CallAESIMC(80)
CallAESIMC(96)
CallAESIMC(112)
CallAESIMC(128)
CallAESIMC(144)
CallAESIMC(160)
CallAESIMC(176)
CallAESIMC(192)
CallAESIMC(208)
:
: [shed]"r"(GetKeySchedule ())
: "%xmm0", "memory"
);
}
else
#endif
{
AES_set_decrypt_key (key, 256, &m_Key);
}
} }
ECBDecryption::~ECBDecryption () void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{ {
if (m_Ctx) #if SUPPORTS_AES
EVP_CIPHER_CTX_free (m_Ctx); if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "cc", "memory"
);
} }
else
void ECBDecryption::Decrypt (const uint8_t * in, uint8_t * out) #endif
{ {
EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_ecb(), NULL, m_Key, NULL); for (int i = 0; i < numBlocks; i++)
EVP_CIPHER_CTX_set_padding (m_Ctx, 0); {
int len; *m_LastBlock.GetChipherBlock () ^= in[i];
EVP_DecryptUpdate (m_Ctx, out, &len, in, 16); m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ());
EVP_DecryptFinal_ex (m_Ctx, out + len, &len); out[i] = *m_LastBlock.GetChipherBlock ();
} }
CBCEncryption::CBCEncryption ()
{
m_Ctx = EVP_CIPHER_CTX_new ();
//memset ((uint8_t *)m_LastBlock, 0, 16);
} }
CBCEncryption::~CBCEncryption ()
{
if (m_Ctx)
EVP_CIPHER_CTX_free (m_Ctx);
} }
void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out) void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
{ {
// len/16 // len/16
EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, m_IV); int numBlocks = len >> 4;
EVP_CIPHER_CTX_set_padding (m_Ctx, 0); if (numBlocks > 0)
int l; Encrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
EVP_EncryptUpdate (m_Ctx, out, &l, in, len);
EVP_EncryptFinal_ex (m_Ctx, out + l, &l);
} }
CBCDecryption::CBCDecryption () void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{ {
m_Ctx = EVP_CIPHER_CTX_new (); #if SUPPORTS_AES
//memset ((uint8_t *)m_IV, 0, 16); if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
}
else
#endif
Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
} }
CBCDecryption::~CBCDecryption () void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{ {
if (m_Ctx) #if SUPPORTS_AES
EVP_CIPHER_CTX_free (m_Ctx); if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
}
else
#endif
{
for (int i = 0; i < numBlocks; i++)
{
ChipherBlock tmp = in[i];
m_ECBDecryption.Decrypt (in + i, out + i);
out[i] ^= *m_IV.GetChipherBlock ();
*m_IV.GetChipherBlock () = tmp;
}
}
} }
void CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out) void CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out)
{ {
// len/16 int numBlocks = len >> 4;
EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, m_IV); if (numBlocks > 0)
EVP_CIPHER_CTX_set_padding (m_Ctx, 0); Decrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
int l; }
EVP_DecryptUpdate (m_Ctx, out, &l, in, len);
EVP_DecryptFinal_ex (m_Ctx, out + l, &l); void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"movups %%xmm0, (%[iv]) \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
}
else
#endif
Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
} }
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{ {
m_IVEncryption.Encrypt (in, out); // iv #if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
// encrypt IV
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
EncryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// encrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "cc", "memory"
);
}
else
#endif
{
m_IVEncryption.Encrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
m_LayerEncryption.SetIV (out); m_LayerEncryption.SetIV (out);
m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
m_IVEncryption.Encrypt (out, out); // double iv m_IVEncryption.Encrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
}
} }
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{ {
m_IVDecryption.Decrypt (in, out); // iv #if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
// decrypt IV
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
DecryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// decrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched_l)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
}
else
#endif
{
m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
m_LayerDecryption.SetIV (out); m_LayerDecryption.SetIV (out);
m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
m_IVDecryption.Decrypt (out, out); // double iv m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
}
} }
// AEAD/ChaCha20/Poly1305 // AEAD/ChaCha20/Poly1305
@@ -834,8 +1157,9 @@ namespace crypto
} }
}*/ }*/
void InitCrypto (bool precomputation) void InitCrypto (bool precomputation, bool aesni, bool force)
{ {
i2p::cpu::Detect (aesni, force);
/* auto numLocks = CRYPTO_num_locks(); /* auto numLocks = CRYPTO_num_locks();
for (int i = 0; i < numLocks; i++) for (int i = 0; i < numLocks; i++)
m_OpenSSLMutexes.emplace_back (new std::mutex); m_OpenSSLMutexes.emplace_back (new std::mutex);

View File

@@ -25,6 +25,7 @@
#include "Base.h" #include "Base.h"
#include "Tag.h" #include "Tag.h"
#include "CPU.h"
// recognize openssl version and features // recognize openssl version and features
#if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 #if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
@@ -84,76 +85,142 @@ namespace crypto
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub); void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
// AES // AES
typedef i2p::data::Tag<32> AESKey; struct ChipherBlock
class ECBEncryption
{ {
public: uint8_t buf[16];
ECBEncryption (); void operator^=(const ChipherBlock& other) // XOR
~ECBEncryption (); {
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
void SetKey (const AESKey& key) { m_Key = key; }; {
void Encrypt(const uint8_t * in, uint8_t * out); for (int i = 0; i < 4; i++)
reinterpret_cast<uint32_t *>(buf)[i] ^= reinterpret_cast<const uint32_t *>(other.buf)[i];
private: }
else
AESKey m_Key; {
EVP_CIPHER_CTX * m_Ctx; for (int i = 0; i < 16; i++)
buf[i] ^= other.buf[i];
}
}
}; };
class ECBDecryption typedef i2p::data::Tag<32> AESKey;
template<size_t sz>
class AESAlignedBuffer // 16 bytes alignment
{ {
public: public:
ECBDecryption (); AESAlignedBuffer ()
~ECBDecryption (); {
m_Buf = m_UnalignedBuffer;
uint8_t rem = ((size_t)m_Buf) & 0x0f;
if (rem)
m_Buf += (16 - rem);
}
void SetKey (const AESKey& key) { m_Key = key; }; operator uint8_t * () { return m_Buf; };
void Decrypt (const uint8_t * in, uint8_t * out); operator const uint8_t * () const { return m_Buf; };
ChipherBlock * GetChipherBlock () { return (ChipherBlock *)m_Buf; };
const ChipherBlock * GetChipherBlock () const { return (const ChipherBlock *)m_Buf; };
private: private:
AESKey m_Key; uint8_t m_UnalignedBuffer[sz + 15]; // up to 15 bytes alignment
EVP_CIPHER_CTX * m_Ctx; uint8_t * m_Buf;
};
#if SUPPORTS_AES
class ECBCryptoAESNI
{
public:
uint8_t * GetKeySchedule () { return m_KeySchedule; };
protected:
void ExpandKey (const AESKey& key);
private:
AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes
};
#endif
#if SUPPORTS_AES
class ECBEncryption: public ECBCryptoAESNI
#else
class ECBEncryption
#endif
{
public:
void SetKey (const AESKey& key);
void Encrypt(const ChipherBlock * in, ChipherBlock * out);
private:
AES_KEY m_Key;
};
#if SUPPORTS_AES
class ECBDecryption: public ECBCryptoAESNI
#else
class ECBDecryption
#endif
{
public:
void SetKey (const AESKey& key);
void Decrypt (const ChipherBlock * in, ChipherBlock * out);
private:
AES_KEY m_Key;
}; };
class CBCEncryption class CBCEncryption
{ {
public: public:
CBCEncryption (); CBCEncryption () { memset ((uint8_t *)m_LastBlock, 0, 16); };
~CBCEncryption ();
void SetKey (const AESKey& key) { m_Key = key; }; // 32 bytes void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 bytes
void SetIV (const uint8_t * iv) { m_IV = iv; }; // 16 bytes void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_LastBlock, iv, 16); }; // 16 bytes
void GetIV (uint8_t * iv) const { memcpy (iv, (const uint8_t *)m_LastBlock, 16); };
void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
void Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); void Encrypt (const uint8_t * in, std::size_t len, uint8_t * out);
void Encrypt (const uint8_t * in, uint8_t * out); // one block
ECBEncryption & ECB() { return m_ECBEncryption; }
private: private:
AESKey m_Key; AESAlignedBuffer<16> m_LastBlock;
i2p::data::Tag<16> m_IV;
EVP_CIPHER_CTX * m_Ctx; ECBEncryption m_ECBEncryption;
}; };
class CBCDecryption class CBCDecryption
{ {
public: public:
CBCDecryption (); CBCDecryption () { memset ((uint8_t *)m_IV, 0, 16); };
~CBCDecryption ();
void SetKey (const AESKey& key) { m_Key = key; }; // 32 bytes void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 bytes
void SetIV (const uint8_t * iv) { m_IV = iv; }; // 16 bytes void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_IV, iv, 16); }; // 16 bytes
void GetIV (uint8_t * iv) const { memcpy (iv, (const uint8_t *)m_IV, 16); };
void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
void Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); void Decrypt (const uint8_t * in, std::size_t len, uint8_t * out);
void Decrypt (const uint8_t * in, uint8_t * out); // one block
ECBDecryption & ECB() { return m_ECBDecryption; }
private: private:
AESKey m_Key; AESAlignedBuffer<16> m_IV;
i2p::data::Tag<16> m_IV; ECBDecryption m_ECBDecryption;
EVP_CIPHER_CTX * m_Ctx;
}; };
class TunnelEncryption // with double IV encryption class TunnelEncryption // with double IV encryption
@@ -221,7 +288,7 @@ namespace crypto
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
// init and terminate // init and terminate
void InitCrypto (bool precomputation); void InitCrypto (bool precomputation, bool aesni, bool force);
void TerminateCrypto (); void TerminateCrypto ();
} }
} }

View File

@@ -550,7 +550,7 @@ namespace garlic
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
} }
else else
LogPrint (eLogWarning, "Garlic: Incoming sessions come too often"); LogPrint (eLogWarning, "Garlic: Incoming sessions come too ofter");
} }
else else
LogPrint (eLogError, "Garlic: Failed to decrypt message"); LogPrint (eLogError, "Garlic: Failed to decrypt message");

View File

@@ -286,7 +286,7 @@ namespace garlic
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions; std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
uint8_t * m_PayloadBuffer; // for ECIESX25519AEADRatchet uint8_t * m_PayloadBuffer; // for ECIESX25519AEADRatchet
uint64_t m_LastIncomingSessionTimestamp; // in milliseconds uint64_t m_LastIncomingSessionTimestamp; // in millseconds
// incoming // incoming
int m_NumRatchetInboundTags; int m_NumRatchetInboundTags;
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags; std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;

View File

@@ -122,7 +122,7 @@ namespace transport
encryption.SetKey (m_RemoteIdentHash); encryption.SetKey (m_RemoteIdentHash);
encryption.SetIV (m_IV); encryption.SetIV (m_IV);
encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X
memcpy (m_IV, m_SessionRequestBuffer + 16, 16); // save last block as IV for SessionCreated encryption.GetIV (m_IV); // save IV for SessionCreated
// encryption key for next block // encryption key for next block
if (!KDF1Alice ()) return false; if (!KDF1Alice ()) return false;
// fill options // fill options
@@ -210,7 +210,7 @@ namespace transport
decryption.SetKey (i2p::context.GetIdentHash ()); decryption.SetKey (i2p::context.GetIdentHash ());
decryption.SetIV (i2p::context.GetNTCP2IV ()); decryption.SetIV (i2p::context.GetNTCP2IV ());
decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ()); decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ());
memcpy (m_IV, m_SessionRequestBuffer + 16, 16); // save last block as IV for SessionCreated decryption.GetIV (m_IV); // save IV for SessionCreated
// decryption key for next block // decryption key for next block
if (!KDF1Bob ()) if (!KDF1Bob ())
{ {

View File

@@ -637,7 +637,7 @@ namespace data
if (checkForExpiration && uptime > i2p::transport::SSU2_TO_INTRODUCER_SESSION_DURATION) // 1 hour if (checkForExpiration && uptime > i2p::transport::SSU2_TO_INTRODUCER_SESSION_DURATION) // 1 hour
expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
bool isOffline = checkForExpiration && i2p::transport::transports.GetNumPeers () < NETDB_MIN_TRANSPORTS; // enough routers and uptime, but no transports bool isOffline = checkForExpiration && i2p::transport::transports.GetNumPeers () < NETDB_MIN_TRANSPORTS; // enough routers and uptime, but no tranports
std::list<std::pair<std::string, std::shared_ptr<RouterInfo::Buffer> > > saveToDisk; std::list<std::pair<std::string, std::shared_ptr<RouterInfo::Buffer> > > saveToDisk;
std::list<std::string> removeFromDisk; std::list<std::string> removeFromDisk;

View File

@@ -1389,7 +1389,7 @@ namespace transport
excluded.insert (ident); excluded.insert (ident);
} }
// session about to expire are not counted // sesssion about to expire are not counted
for (auto i = introducers.size (); i < SSU2_MAX_NUM_INTRODUCERS + numOldSessions; i++) for (auto i = introducers.size (); i < SSU2_MAX_NUM_INTRODUCERS + numOldSessions; i++)
{ {
auto introducer = i2p::data::netdb.GetRandomSSU2Introducer (v4, excluded); auto introducer = i2p::data::netdb.GetRandomSSU2Introducer (v4, excluded);

View File

@@ -68,7 +68,7 @@ namespace transport
void SSU2PeerTestSession::HandleAddress (const uint8_t * buf, size_t len) void SSU2PeerTestSession::HandleAddress (const uint8_t * buf, size_t len)
{ {
if (!ExtractEndpoint (buf, len, m_OurEndpoint)) if (!ExtractEndpoint (buf, len, m_OurEndpoint))
LogPrint (eLogWarning, "SSU2: Can't handle address block from peer test message"); LogPrint (eLogWarning, "SSU2: Can't hanlde address block from peer test message");
} }
void SSU2PeerTestSession::HandlePeerTest (const uint8_t * buf, size_t len) void SSU2PeerTestSession::HandlePeerTest (const uint8_t * buf, size_t len)
@@ -89,7 +89,7 @@ namespace transport
{ {
if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ()) if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ())
{ {
m_PeerTestResendTimer.cancel (); // cancel delayed msg 6 if any m_PeerTestResendTimer.cancel (); // calcel delayed msg 6 if any
m_IsConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ()); m_IsConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ());
if (GetAddress ()) if (GetAddress ())
{ {

View File

@@ -958,7 +958,7 @@ namespace stream
if (choking || requestImmediateAck) if (choking || requestImmediateAck)
{ {
htobe16buf (packet + size, 2); // 2 bytes delay interval htobe16buf (packet + size, 2); // 2 bytes delay interval
htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediate ack interval htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediated ack interval
size += 2; size += 2;
if (requestImmediateAck) // ack request sent if (requestImmediateAck) // ack request sent
{ {
@@ -1147,6 +1147,7 @@ namespace stream
m_CurrentOutboundTunnel = routingPath->outboundTunnel; m_CurrentOutboundTunnel = routingPath->outboundTunnel;
m_CurrentRemoteLease = routingPath->remoteLease; m_CurrentRemoteLease = routingPath->remoteLease;
m_RTT = routingPath->rtt; m_RTT = routingPath->rtt;
m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.3 + m_Jitter)); // TODO: implement it better
} }
} }

View File

@@ -298,7 +298,7 @@ namespace stream
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample;
double m_Jitter; double m_Jitter;
uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds
m_LastSendTime, m_RemoteLeaseChangeTime; // milliseconds m_LastSendTime, m_RemoteLeaseChangeTime; // miliseconds
uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed
int m_NumResendAttempts, m_NumPacketsToSend; int m_NumResendAttempts, m_NumPacketsToSend;
size_t m_MTU; size_t m_MTU;

View File

@@ -240,13 +240,13 @@ namespace tunnel
auto currentTransport = m_CurrentTransport.lock (); auto currentTransport = m_CurrentTransport.lock ();
if (!currentTransport) if (!currentTransport)
{ {
// try to obtain transport from pending request or send thought transport is not complete // try to obtain transport from peding reequest or send thought transport is not complete
if (m_PendingTransport.valid ()) // pending request? if (m_PendingTransport.valid ()) // pending request?
{ {
if (m_PendingTransport.wait_for(std::chrono::seconds(0)) == std::future_status::ready) if (m_PendingTransport.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{ {
// pending request complete // pending request complete
currentTransport = m_PendingTransport.get (); // take transports used in pending request currentTransport = m_PendingTransport.get (); // take tarnsports used in pending request
if (currentTransport) if (currentTransport)
{ {
if (currentTransport->IsEstablished ()) if (currentTransport->IsEstablished ())
@@ -257,7 +257,7 @@ namespace tunnel
} }
else // still pending else // still pending
{ {
// send through transports, but don't update pending transport // send through transports, but don't update pedning transport
i2p::transport::transports.SendMessages (m_Tunnel.GetNextIdentHash (), std::move (newTunnelMsgs)); i2p::transport::transports.SendMessages (m_Tunnel.GetNextIdentHash (), std::move (newTunnelMsgs));
return; return;
} }

View File

@@ -37,7 +37,9 @@ namespace api
i2p::fs::Init(); i2p::fs::Init();
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
i2p::crypto::InitCrypto (precomputation); bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
int netID; i2p::config::GetOption("netid", netID); int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID); i2p::context.SetNetID (netID);

View File

@@ -879,7 +879,7 @@ namespace client
if (!remoteSession || !m_Destination->SendMsg (buf + offset, payloadLen, remoteSession, nonce)) if (!remoteSession || !m_Destination->SendMsg (buf + offset, payloadLen, remoteSession, nonce))
{ {
i2p::data::IdentHash identHash; i2p::data::IdentHash identHash;
SHA256(ident, identSize, identHash); // calculate ident hash, because we don't need full identity SHA256(ident, identSize, identHash); // caclulate ident hash, because we don't need full identity
m_Destination->SendMsgTo (buf + offset, payloadLen, identHash, nonce); m_Destination->SendMsgTo (buf + offset, payloadLen, identHash, nonce);
} }
} }

View File

@@ -86,7 +86,7 @@ namespace client
} }
else else
{ {
LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from different address. Removed"); LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from differend address. Removed");
m_Sessions.erase (it); m_Sessions.erase (it);
} }
} }