mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
14 Commits
master
...
cec68a2447
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cec68a2447 | ||
|
|
73ba1afc20 | ||
|
|
dcbe6cfaf2 | ||
|
|
3534b9c499 | ||
|
|
a7021a8283 | ||
|
|
946e523554 | ||
|
|
cdd528c51f | ||
|
|
1a748aebf1 | ||
|
|
f23a7f569b | ||
|
|
48b62340cc | ||
|
|
65da550d19 | ||
|
|
786da057f2 | ||
|
|
097813a6ca | ||
|
|
226257aa71 |
4
.github/workflows/build-windows.yml
vendored
4
.github/workflows/build-windows.yml
vendored
@@ -230,8 +230,10 @@ jobs:
|
||||
run: |
|
||||
cd MINGW-packages/mingw-w64-boost
|
||||
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
|
||||
- name: Remove boost packages
|
||||
run: pacman --noconfirm -R mingw-w64-i686-boost mingw-w64-i686-boost-libs
|
||||
- name: Install boost package
|
||||
run: pacman --noconfirm -U --overwrite MINGW-packages/mingw-w64-boost/mingw-w64-i686-*-any.pkg.tar.zst
|
||||
run: pacman --noconfirm -U MINGW-packages/mingw-w64-boost/mingw-w64-i686-*-any.pkg.tar.zst
|
||||
|
||||
# Building i2pd
|
||||
- name: Build application
|
||||
|
||||
1
Makefile
1
Makefile
@@ -29,7 +29,6 @@ DAEMON_SRC_DIR := daemon
|
||||
# import source files lists
|
||||
include filelist.mk
|
||||
|
||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||
USE_STATIC := $(or $(USE_STATIC),no)
|
||||
USE_UPNP := $(or $(USE_UPNP),no)
|
||||
DEBUG := $(or $(DEBUG),yes)
|
||||
|
||||
@@ -30,13 +30,6 @@ ifeq ($(USE_UPNP),yes)
|
||||
INCFLAGS += -I${UPNPROOT}/include
|
||||
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 -d ${PREFIX}/bin
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin
|
||||
|
||||
@@ -51,13 +51,6 @@ ifeq ($(USE_UPNP),yes)
|
||||
DEFINES += -DUSE_UPNP
|
||||
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 -d ${PREFIX}/bin
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin
|
||||
|
||||
@@ -42,12 +42,6 @@ ifeq ($(USE_WIN32_APP), yes)
|
||||
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
|
||||
endif
|
||||
|
||||
ifeq ($(USE_AESNI),yes)
|
||||
NEEDED_CXXFLAGS += -maes
|
||||
LDFLAGS += -maes
|
||||
DEFINES += -D__AES__
|
||||
endif
|
||||
|
||||
ifeq ($(USE_ASLR),yes)
|
||||
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
|
||||
endif
|
||||
|
||||
@@ -25,9 +25,5 @@ endif
|
||||
OSARCH = $(shell uname -p)
|
||||
|
||||
ifneq ($(OSARCH),powerpc)
|
||||
ifeq ($(USE_AESNI),yes)
|
||||
CXXFLAGS += -D__AES__ -maes
|
||||
else
|
||||
CXXFLAGS += -msse
|
||||
endif
|
||||
CXXFLAGS += -msse
|
||||
endif
|
||||
|
||||
@@ -29,7 +29,6 @@ project(
|
||||
)
|
||||
|
||||
# configurable options
|
||||
option(WITH_AESNI "Use AES-NI instructions set" ON)
|
||||
option(WITH_HARDENING "Use hardening compiler flags" OFF)
|
||||
option(WITH_LIBRARY "Build library" ON)
|
||||
option(WITH_BINARY "Build binary" ON)
|
||||
@@ -185,16 +184,6 @@ if(UNIX)
|
||||
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)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
@@ -335,7 +324,6 @@ message(STATUS "Architecture : ${ARCHITECTURE}")
|
||||
message(STATUS "Compiler flags : ${CMAKE_CXX_FLAGS}")
|
||||
message(STATUS "Install prefix: : ${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS "Options:")
|
||||
message(STATUS " AESNI : ${WITH_AESNI}")
|
||||
message(STATUS " HARDENING : ${WITH_HARDENING}")
|
||||
message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
||||
message(STATUS " BINARY : ${WITH_BINARY}")
|
||||
|
||||
@@ -277,9 +277,3 @@ verify = true
|
||||
## Save full addresses on disk (default: true)
|
||||
# addressbook = true
|
||||
|
||||
[cpuext]
|
||||
## Use CPU AES-NI instructions set when work with cryptography when available (default: true)
|
||||
# aesni = true
|
||||
## Force usage of CPU instructions set, even if they not found (default: false)
|
||||
## DO NOT TOUCH that option if you really don't know what are you doing!
|
||||
# force = false
|
||||
|
||||
@@ -149,12 +149,10 @@ namespace util
|
||||
LogPrint(eLogDebug, "FS: Certificates directory: ", certsdir);
|
||||
|
||||
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);
|
||||
if (!ssu && i2p::config::IsDefault ("precomputation.elgamal"))
|
||||
precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly
|
||||
i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
|
||||
i2p::crypto::InitCrypto (precomputation);
|
||||
|
||||
i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -21,20 +21,4 @@
|
||||
# define IS_X86_64 0
|
||||
#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
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace config {
|
||||
("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.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 deafult")
|
||||
("httpproxy.senduseragent", value<bool>()->default_value(false), "Pass through user's User-Agent if enabled. Disabled by default")
|
||||
("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.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)")
|
||||
;
|
||||
|
||||
options_description cpuext("CPU encryption extensions options");
|
||||
options_description cpuext("CPU encryption extensions options. Deprecated");
|
||||
cpuext.add_options()
|
||||
("cpuext.aesni", bool_switch()->default_value(true), "Use auto detection for AESNI CPU extensions. If false, AESNI will be not used")
|
||||
("cpuext.aesni", bool_switch()->default_value(true), "Deprecated option")
|
||||
("cpuext.avx", 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")
|
||||
("cpuext.force", bool_switch()->default_value(false), "Deprecated option")
|
||||
;
|
||||
|
||||
options_description meshnets("Meshnet transports options");
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#if OPENSSL_HKDF
|
||||
#include <openssl/kdf.h>
|
||||
#endif
|
||||
#include "CPU.h"
|
||||
#include "Crypto.h"
|
||||
#include "Ed25519.h"
|
||||
#include "I2PEndian.h"
|
||||
@@ -441,9 +442,8 @@ namespace crypto
|
||||
// encrypt
|
||||
CBCEncryption encryption;
|
||||
encryption.SetKey (shared);
|
||||
encryption.SetIV (iv);
|
||||
encrypted[257] = 0;
|
||||
encryption.Encrypt (m, 256, encrypted + 258);
|
||||
encryption.Encrypt (m, 256, iv, encrypted + 258);
|
||||
EC_POINT_free (p);
|
||||
BN_CTX_end (ctx);
|
||||
BN_CTX_free (ctx);
|
||||
@@ -476,8 +476,7 @@ namespace crypto
|
||||
uint8_t m[256];
|
||||
CBCDecryption decryption;
|
||||
decryption.SetKey (shared);
|
||||
decryption.SetIV (iv);
|
||||
decryption.Decrypt (encrypted + 258, 256, m);
|
||||
decryption.Decrypt (encrypted + 258, 256, iv, m);
|
||||
// verify and copy
|
||||
uint8_t hash[32];
|
||||
SHA256 (m + 33, 222, hash);
|
||||
@@ -515,440 +514,114 @@ namespace crypto
|
||||
}
|
||||
|
||||
// AES
|
||||
#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)
|
||||
ECBEncryption::ECBEncryption ()
|
||||
{
|
||||
__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
|
||||
);
|
||||
m_Ctx = EVP_CIPHER_CTX_new ();
|
||||
}
|
||||
#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)
|
||||
|
||||
ECBEncryption::~ECBEncryption ()
|
||||
{
|
||||
#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);
|
||||
}
|
||||
if (m_Ctx)
|
||||
EVP_CIPHER_CTX_free (m_Ctx);
|
||||
}
|
||||
|
||||
void ECBEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_ecb(), NULL, m_Key, NULL);
|
||||
EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
|
||||
int len;
|
||||
EVP_EncryptUpdate (m_Ctx, out, &len, in, 16);
|
||||
EVP_EncryptFinal_ex (m_Ctx, out + len, &len);
|
||||
}
|
||||
|
||||
#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)
|
||||
ECBDecryption::ECBDecryption ()
|
||||
{
|
||||
#if SUPPORTS_AES
|
||||
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);
|
||||
}
|
||||
m_Ctx = EVP_CIPHER_CTX_new ();
|
||||
}
|
||||
|
||||
ECBDecryption::~ECBDecryption ()
|
||||
{
|
||||
if (m_Ctx)
|
||||
EVP_CIPHER_CTX_free (m_Ctx);
|
||||
}
|
||||
|
||||
void ECBDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_ecb(), NULL, m_Key, NULL);
|
||||
EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
|
||||
int len;
|
||||
EVP_DecryptUpdate (m_Ctx, out, &len, in, 16);
|
||||
EVP_DecryptFinal_ex (m_Ctx, out + len, &len);
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
#if SUPPORTS_AES
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
ExpandKey (key);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
AES_set_encrypt_key (key, 256, &m_Key);
|
||||
}
|
||||
CBCEncryption::CBCEncryption ()
|
||||
{
|
||||
m_Ctx = EVP_CIPHER_CTX_new ();
|
||||
}
|
||||
|
||||
void ECBDecryption::SetKey (const AESKey& key)
|
||||
|
||||
CBCEncryption::~CBCEncryption ()
|
||||
{
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#if SUPPORTS_AES
|
||||
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
|
||||
#endif
|
||||
{
|
||||
for (int i = 0; i < numBlocks; i++)
|
||||
{
|
||||
*m_LastBlock.GetChipherBlock () ^= in[i];
|
||||
m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ());
|
||||
out[i] = *m_LastBlock.GetChipherBlock ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
|
||||
if (m_Ctx)
|
||||
EVP_CIPHER_CTX_free (m_Ctx);
|
||||
}
|
||||
|
||||
void CBCEncryption::Encrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out)
|
||||
{
|
||||
// len/16
|
||||
int numBlocks = len >> 4;
|
||||
if (numBlocks > 0)
|
||||
Encrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||
EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, iv);
|
||||
EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
|
||||
int l;
|
||||
EVP_EncryptUpdate (m_Ctx, out, &l, in, len);
|
||||
EVP_EncryptFinal_ex (m_Ctx, out + l, &l);
|
||||
}
|
||||
|
||||
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#if SUPPORTS_AES
|
||||
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 ()
|
||||
{
|
||||
m_Ctx = EVP_CIPHER_CTX_new ();
|
||||
}
|
||||
|
||||
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||
|
||||
CBCDecryption::~CBCDecryption ()
|
||||
{
|
||||
#if SUPPORTS_AES
|
||||
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)
|
||||
if (m_Ctx)
|
||||
EVP_CIPHER_CTX_free (m_Ctx);
|
||||
}
|
||||
|
||||
void CBCDecryption::Decrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out)
|
||||
{
|
||||
int numBlocks = len >> 4;
|
||||
if (numBlocks > 0)
|
||||
Decrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||
}
|
||||
|
||||
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);
|
||||
// len/16
|
||||
EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, iv);
|
||||
EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
|
||||
int l;
|
||||
EVP_DecryptUpdate (m_Ctx, out, &l, in, len);
|
||||
EVP_DecryptFinal_ex (m_Ctx, out + l, &l);
|
||||
}
|
||||
|
||||
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#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.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||
m_IVEncryption.Encrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||
}
|
||||
uint8_t iv[16];
|
||||
m_IVEncryption.Encrypt (in, iv); // iv
|
||||
m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, iv, out + 16); // data
|
||||
m_IVEncryption.Encrypt (iv, out); // double iv
|
||||
}
|
||||
|
||||
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#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.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||
m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||
}
|
||||
uint8_t iv[16];
|
||||
m_IVDecryption.Decrypt (in, iv); // iv
|
||||
m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, iv, out + 16); // data
|
||||
m_IVDecryption.Decrypt (iv, out); // double iv
|
||||
}
|
||||
|
||||
// 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)
|
||||
static bool AEADChaCha20Poly1305 (EVP_CIPHER_CTX * ctx, 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)
|
||||
{
|
||||
if (len < msgLen) return false;
|
||||
if (!ctx || len < msgLen) return false;
|
||||
if (encrypt && len < msgLen + 16) return false;
|
||||
bool ret = true;
|
||||
int outlen = 0;
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
||||
if (encrypt)
|
||||
{
|
||||
EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
||||
@@ -978,26 +651,66 @@ namespace crypto
|
||||
EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen);
|
||||
ret = EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen) > 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
EVP_CIPHER_CTX * ctx = EVP_CIPHER_CTX_new ();
|
||||
auto ret = AEADChaCha20Poly1305 (ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, encrypt);
|
||||
EVP_CIPHER_CTX_free (ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
|
||||
AEADChaCha20Poly1305Encryptor::AEADChaCha20Poly1305Encryptor ()
|
||||
{
|
||||
m_Ctx = EVP_CIPHER_CTX_new ();
|
||||
}
|
||||
|
||||
AEADChaCha20Poly1305Encryptor::~AEADChaCha20Poly1305Encryptor ()
|
||||
{
|
||||
if (m_Ctx)
|
||||
EVP_CIPHER_CTX_free (m_Ctx);
|
||||
}
|
||||
|
||||
bool AEADChaCha20Poly1305Encryptor::Encrypt (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)
|
||||
{
|
||||
return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, true);
|
||||
}
|
||||
|
||||
void AEADChaCha20Poly1305Encryptor::Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs,
|
||||
const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
|
||||
{
|
||||
if (bufs.empty ()) return;
|
||||
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);
|
||||
EVP_EncryptInit_ex(m_Ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
||||
EVP_CIPHER_CTX_ctrl(m_Ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
|
||||
EVP_EncryptInit_ex(m_Ctx, NULL, NULL, key, nonce);
|
||||
for (const auto& it: bufs)
|
||||
EVP_EncryptUpdate(ctx, it.first, &outlen, it.first, it.second);
|
||||
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
|
||||
EVP_CIPHER_CTX_free (ctx);
|
||||
EVP_EncryptUpdate(m_Ctx, it.first, &outlen, it.first, it.second);
|
||||
EVP_EncryptFinal_ex(m_Ctx, NULL, &outlen);
|
||||
EVP_CIPHER_CTX_ctrl(m_Ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
|
||||
}
|
||||
|
||||
AEADChaCha20Poly1305Decryptor::AEADChaCha20Poly1305Decryptor ()
|
||||
{
|
||||
m_Ctx = EVP_CIPHER_CTX_new ();
|
||||
}
|
||||
|
||||
AEADChaCha20Poly1305Decryptor::~AEADChaCha20Poly1305Decryptor ()
|
||||
{
|
||||
if (m_Ctx)
|
||||
EVP_CIPHER_CTX_free (m_Ctx);
|
||||
}
|
||||
|
||||
bool AEADChaCha20Poly1305Decryptor::Decrypt (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)
|
||||
{
|
||||
return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, false);
|
||||
}
|
||||
|
||||
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
||||
@@ -1157,9 +870,8 @@ namespace crypto
|
||||
}
|
||||
}*/
|
||||
|
||||
void InitCrypto (bool precomputation, bool aesni, bool force)
|
||||
void InitCrypto (bool precomputation)
|
||||
{
|
||||
i2p::cpu::Detect (aesni, force);
|
||||
/* auto numLocks = CRYPTO_num_locks();
|
||||
for (int i = 0; i < numLocks; i++)
|
||||
m_OpenSSLMutexes.emplace_back (new std::mutex);
|
||||
|
||||
175
libi2pd/Crypto.h
175
libi2pd/Crypto.h
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "Base.h"
|
||||
#include "Tag.h"
|
||||
#include "CPU.h"
|
||||
|
||||
// recognize openssl version and features
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||
@@ -85,142 +84,70 @@ namespace crypto
|
||||
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
|
||||
|
||||
// AES
|
||||
struct ChipherBlock
|
||||
{
|
||||
uint8_t buf[16];
|
||||
|
||||
void operator^=(const ChipherBlock& other) // XOR
|
||||
{
|
||||
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
reinterpret_cast<uint32_t *>(buf)[i] ^= reinterpret_cast<const uint32_t *>(other.buf)[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
buf[i] ^= other.buf[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef i2p::data::Tag<32> AESKey;
|
||||
|
||||
template<size_t sz>
|
||||
class AESAlignedBuffer // 16 bytes alignment
|
||||
{
|
||||
public:
|
||||
|
||||
AESAlignedBuffer ()
|
||||
{
|
||||
m_Buf = m_UnalignedBuffer;
|
||||
uint8_t rem = ((size_t)m_Buf) & 0x0f;
|
||||
if (rem)
|
||||
m_Buf += (16 - rem);
|
||||
}
|
||||
|
||||
operator uint8_t * () { return m_Buf; };
|
||||
operator const uint8_t * () const { return m_Buf; };
|
||||
ChipherBlock * GetChipherBlock () { return (ChipherBlock *)m_Buf; };
|
||||
const ChipherBlock * GetChipherBlock () const { return (const ChipherBlock *)m_Buf; };
|
||||
|
||||
private:
|
||||
|
||||
uint8_t m_UnalignedBuffer[sz + 15]; // up to 15 bytes alignment
|
||||
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);
|
||||
ECBEncryption ();
|
||||
~ECBEncryption ();
|
||||
|
||||
void SetKey (const uint8_t * key) { m_Key = key; };
|
||||
void Encrypt(const uint8_t * in, uint8_t * out);
|
||||
|
||||
void Encrypt(const ChipherBlock * in, ChipherBlock * out);
|
||||
private:
|
||||
|
||||
private:
|
||||
AES_KEY m_Key;
|
||||
AESKey m_Key;
|
||||
EVP_CIPHER_CTX * m_Ctx;
|
||||
};
|
||||
|
||||
#if SUPPORTS_AES
|
||||
class ECBDecryption: public ECBCryptoAESNI
|
||||
#else
|
||||
class ECBDecryption
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
void SetKey (const AESKey& key);
|
||||
void Decrypt (const ChipherBlock * in, ChipherBlock * out);
|
||||
ECBDecryption ();
|
||||
~ECBDecryption ();
|
||||
|
||||
void SetKey (const uint8_t * key) { m_Key = key; };
|
||||
void Decrypt (const uint8_t * in, uint8_t * out);
|
||||
|
||||
private:
|
||||
AES_KEY m_Key;
|
||||
|
||||
AESKey m_Key;
|
||||
EVP_CIPHER_CTX * m_Ctx;
|
||||
};
|
||||
|
||||
class CBCEncryption
|
||||
{
|
||||
public:
|
||||
|
||||
CBCEncryption () { memset ((uint8_t *)m_LastBlock, 0, 16); };
|
||||
|
||||
void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 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, uint8_t * out); // one block
|
||||
|
||||
ECBEncryption & ECB() { return m_ECBEncryption; }
|
||||
CBCEncryption ();
|
||||
~CBCEncryption ();
|
||||
|
||||
void SetKey (const uint8_t * key) { m_Key = key; }; // 32 bytes
|
||||
void Encrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out);
|
||||
|
||||
private:
|
||||
|
||||
AESAlignedBuffer<16> m_LastBlock;
|
||||
|
||||
ECBEncryption m_ECBEncryption;
|
||||
AESKey m_Key;
|
||||
EVP_CIPHER_CTX * m_Ctx;
|
||||
};
|
||||
|
||||
class CBCDecryption
|
||||
{
|
||||
public:
|
||||
|
||||
CBCDecryption () { memset ((uint8_t *)m_IV, 0, 16); };
|
||||
|
||||
void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 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, uint8_t * out); // one block
|
||||
|
||||
ECBDecryption & ECB() { return m_ECBDecryption; }
|
||||
CBCDecryption ();
|
||||
~CBCDecryption ();
|
||||
|
||||
void SetKey (const uint8_t * key) { m_Key = key; }; // 32 bytes
|
||||
void Decrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out);
|
||||
|
||||
private:
|
||||
|
||||
AESAlignedBuffer<16> m_IV;
|
||||
ECBDecryption m_ECBDecryption;
|
||||
AESKey m_Key;
|
||||
EVP_CIPHER_CTX * m_Ctx;
|
||||
};
|
||||
|
||||
class TunnelEncryption // with double IV encryption
|
||||
@@ -260,10 +187,42 @@ 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 (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad
|
||||
class AEADChaCha20Poly1305Encryptor
|
||||
{
|
||||
public:
|
||||
|
||||
AEADChaCha20Poly1305Encryptor ();
|
||||
~AEADChaCha20Poly1305Encryptor ();
|
||||
|
||||
bool Encrypt (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); // msgLen is len without tag
|
||||
|
||||
void Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad
|
||||
|
||||
private:
|
||||
|
||||
EVP_CIPHER_CTX * m_Ctx;
|
||||
};
|
||||
|
||||
class AEADChaCha20Poly1305Decryptor
|
||||
{
|
||||
public:
|
||||
|
||||
AEADChaCha20Poly1305Decryptor ();
|
||||
~AEADChaCha20Poly1305Decryptor ();
|
||||
|
||||
bool Decrypt (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); // msgLen is len without tag
|
||||
|
||||
private:
|
||||
|
||||
EVP_CIPHER_CTX * m_Ctx;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
// ChaCha20
|
||||
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
|
||||
|
||||
@@ -288,7 +247,7 @@ namespace crypto
|
||||
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
|
||||
|
||||
// init and terminate
|
||||
void InitCrypto (bool precomputation, bool aesni, bool force);
|
||||
void InitCrypto (bool precomputation);
|
||||
void TerminateCrypto ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -725,6 +725,8 @@ namespace garlic
|
||||
|
||||
bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||
{
|
||||
auto owner = GetOwner ();
|
||||
if (!owner) return false;
|
||||
uint8_t nonce[12];
|
||||
auto index = m_SendTagset->GetNextIndex ();
|
||||
CreateNonce (index, nonce); // tag's index
|
||||
@@ -732,8 +734,7 @@ namespace garlic
|
||||
if (!tag)
|
||||
{
|
||||
LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset");
|
||||
if (GetOwner ())
|
||||
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
|
||||
owner->RemoveECIESx25519Session (m_RemoteStaticKey);
|
||||
return false;
|
||||
}
|
||||
memcpy (out, &tag, 8);
|
||||
@@ -741,7 +742,7 @@ namespace garlic
|
||||
// ciphertext = ENCRYPT(k, n, payload, ad)
|
||||
uint8_t key[32];
|
||||
m_SendTagset->GetSymmKey (index, key);
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, out, 8, key, nonce, out + 8, outLen - 8, true)) // encrypt
|
||||
if (!owner->AEADChaCha20Poly1305Encrypt (payload, len, out, 8, key, nonce, out + 8, outLen - 8))
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
|
||||
return false;
|
||||
@@ -760,34 +761,35 @@ namespace garlic
|
||||
uint8_t * payload = buf + 8;
|
||||
uint8_t key[32];
|
||||
receiveTagset->GetSymmKey (index, key);
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len - 16, buf, 8, key, nonce, payload, len - 16, false)) // decrypt
|
||||
auto owner = GetOwner ();
|
||||
if (!owner) return true; // drop message
|
||||
|
||||
if (!owner->AEADChaCha20Poly1305Decrypt (payload, len - 16, buf, 8, key, nonce, payload, len - 16))
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
|
||||
return false;
|
||||
}
|
||||
HandlePayload (payload, len - 16, receiveTagset, index);
|
||||
if (GetOwner ())
|
||||
|
||||
int moreTags = 0;
|
||||
if (owner->GetNumRatchetInboundTags () > 0) // override in settings?
|
||||
{
|
||||
int moreTags = 0;
|
||||
if (GetOwner ()->GetNumRatchetInboundTags () > 0) // override in settings?
|
||||
{
|
||||
if (receiveTagset->GetNextIndex () - index < GetOwner ()->GetNumRatchetInboundTags ()/2)
|
||||
moreTags = GetOwner ()->GetNumRatchetInboundTags ();
|
||||
index -= GetOwner ()->GetNumRatchetInboundTags (); // trim behind
|
||||
}
|
||||
else
|
||||
{
|
||||
moreTags = (receiveTagset->GetTagSetID () > 0) ? ECIESX25519_MAX_NUM_GENERATED_TAGS : // for non first tagset
|
||||
(ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 1)); // N/2
|
||||
if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS;
|
||||
moreTags -= (receiveTagset->GetNextIndex () - index);
|
||||
index -= ECIESX25519_MAX_NUM_GENERATED_TAGS; // trim behind
|
||||
}
|
||||
if (moreTags > 0)
|
||||
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
||||
if (index > 0)
|
||||
receiveTagset->SetTrimBehind (index);
|
||||
if (receiveTagset->GetNextIndex () - index < owner->GetNumRatchetInboundTags ()/2)
|
||||
moreTags = owner->GetNumRatchetInboundTags ();
|
||||
index -= owner->GetNumRatchetInboundTags (); // trim behind
|
||||
}
|
||||
else
|
||||
{
|
||||
moreTags = (receiveTagset->GetTagSetID () > 0) ? ECIESX25519_MAX_NUM_GENERATED_TAGS : // for non first tagset
|
||||
(ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 1)); // N/2
|
||||
if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS;
|
||||
moreTags -= (receiveTagset->GetNextIndex () - index);
|
||||
index -= ECIESX25519_MAX_NUM_GENERATED_TAGS; // trim behind
|
||||
}
|
||||
if (moreTags > 0)
|
||||
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
||||
if (index > 0)
|
||||
receiveTagset->SetTrimBehind (index);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace garlic
|
||||
uint8_t iv[32]; // IV is first 16 bytes
|
||||
SHA256(elGamal.preIV, 32, iv);
|
||||
m_Destination->Encrypt ((uint8_t *)&elGamal, buf);
|
||||
m_Encryption.SetIV (iv);
|
||||
m_IV = iv;
|
||||
buf += 514;
|
||||
len += 514;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ namespace garlic
|
||||
memcpy (buf, tag, 32);
|
||||
uint8_t iv[32]; // IV is first 16 bytes
|
||||
SHA256(tag, 32, iv);
|
||||
m_Encryption.SetIV (iv);
|
||||
m_IV = iv;
|
||||
buf += 32;
|
||||
len += 32;
|
||||
}
|
||||
@@ -210,7 +210,7 @@ namespace garlic
|
||||
size_t rem = blockSize % 16;
|
||||
if (rem)
|
||||
blockSize += (16-rem); //padding
|
||||
m_Encryption.Encrypt(buf, blockSize, buf);
|
||||
m_Encryption.Encrypt(buf, blockSize, m_IV, buf);
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
@@ -514,8 +514,7 @@ namespace garlic
|
||||
{
|
||||
uint8_t iv[32]; // IV is first 16 bytes
|
||||
SHA256(buf, 32, iv);
|
||||
decryption->SetIV (iv);
|
||||
decryption->Decrypt (buf + 32, length - 32, buf + 32);
|
||||
decryption->Decrypt (buf + 32, length - 32, iv, buf + 32);
|
||||
HandleAESBlock (buf + 32, length - 32, decryption, msg->from);
|
||||
found = true;
|
||||
}
|
||||
@@ -533,8 +532,7 @@ namespace garlic
|
||||
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
|
||||
uint8_t iv[32]; // IV is first 16 bytes
|
||||
SHA256(elGamal.preIV, 32, iv);
|
||||
decryption->SetIV (iv);
|
||||
decryption->Decrypt(buf + 514, length - 514, buf + 514);
|
||||
decryption->Decrypt(buf + 514, length - 514, iv, buf + 514);
|
||||
HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
|
||||
}
|
||||
else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
|
||||
@@ -550,7 +548,7 @@ namespace garlic
|
||||
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "Garlic: Incoming sessions come too ofter");
|
||||
LogPrint (eLogWarning, "Garlic: Incoming sessions come too often");
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
||||
@@ -1105,5 +1103,17 @@ namespace garlic
|
||||
m_PayloadBuffer = new uint8_t[I2NP_MAX_MESSAGE_SIZE];
|
||||
return m_PayloadBuffer;
|
||||
}
|
||||
|
||||
bool GarlicDestination::AEADChaCha20Poly1305Encrypt (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)
|
||||
{
|
||||
return m_Encryptor.Encrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
|
||||
}
|
||||
|
||||
bool GarlicDestination::AEADChaCha20Poly1305Decrypt (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)
|
||||
{
|
||||
return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,6 +205,7 @@ namespace garlic
|
||||
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
|
||||
|
||||
i2p::crypto::CBCEncryption m_Encryption;
|
||||
i2p::data::Tag<16> m_IV;
|
||||
|
||||
public:
|
||||
|
||||
@@ -241,6 +242,11 @@ namespace garlic
|
||||
void RemoveDeliveryStatusSession (uint32_t msgID);
|
||||
std::shared_ptr<I2NPMessage> WrapMessageForRouter (std::shared_ptr<const i2p::data::RouterInfo> router,
|
||||
std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
bool AEADChaCha20Poly1305Encrypt (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 AEADChaCha20Poly1305Decrypt (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);
|
||||
|
||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||
void AddECIESx25519Key (const uint8_t * key, uint64_t tag); // one tag
|
||||
@@ -286,7 +292,7 @@ namespace garlic
|
||||
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
|
||||
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
|
||||
uint8_t * m_PayloadBuffer; // for ECIESX25519AEADRatchet
|
||||
uint64_t m_LastIncomingSessionTimestamp; // in millseconds
|
||||
uint64_t m_LastIncomingSessionTimestamp; // in milliseconds
|
||||
// incoming
|
||||
int m_NumRatchetInboundTags;
|
||||
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
|
||||
@@ -294,7 +300,10 @@ namespace garlic
|
||||
// DeliveryStatus
|
||||
std::mutex m_DeliveryStatusSessionsMutex;
|
||||
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
||||
|
||||
// encryption
|
||||
i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor;
|
||||
i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor;
|
||||
|
||||
public:
|
||||
|
||||
// for HTTP only
|
||||
|
||||
@@ -120,9 +120,8 @@ namespace transport
|
||||
// encrypt X
|
||||
i2p::crypto::CBCEncryption encryption;
|
||||
encryption.SetKey (m_RemoteIdentHash);
|
||||
encryption.SetIV (m_IV);
|
||||
encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X
|
||||
encryption.GetIV (m_IV); // save IV for SessionCreated
|
||||
encryption.Encrypt (GetPub (), 32, m_IV, m_SessionRequestBuffer); // X
|
||||
memcpy (m_IV, m_SessionRequestBuffer + 16, 16); // save last block as IV for SessionCreated
|
||||
// encryption key for next block
|
||||
if (!KDF1Alice ()) return false;
|
||||
// fill options
|
||||
@@ -161,8 +160,7 @@ namespace transport
|
||||
// encrypt Y
|
||||
i2p::crypto::CBCEncryption encryption;
|
||||
encryption.SetKey (i2p::context.GetIdentHash ());
|
||||
encryption.SetIV (m_IV);
|
||||
encryption.Encrypt (GetPub (), 32, m_SessionCreatedBuffer); // Y
|
||||
encryption.Encrypt (GetPub (), 32, m_IV, m_SessionCreatedBuffer); // Y
|
||||
// encryption key for next block (m_K)
|
||||
if (!KDF2Bob ()) return false;
|
||||
uint8_t options[16];
|
||||
@@ -208,9 +206,8 @@ namespace transport
|
||||
// decrypt X
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (i2p::context.GetIdentHash ());
|
||||
decryption.SetIV (i2p::context.GetNTCP2IV ());
|
||||
decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ());
|
||||
decryption.GetIV (m_IV); // save IV for SessionCreated
|
||||
decryption.Decrypt (m_SessionRequestBuffer, 32, i2p::context.GetNTCP2IV (), GetRemotePub ());
|
||||
memcpy (m_IV, m_SessionRequestBuffer + 16, 16); // save last block as IV for SessionCreated
|
||||
// decryption key for next block
|
||||
if (!KDF1Bob ())
|
||||
{
|
||||
@@ -268,8 +265,7 @@ namespace transport
|
||||
// decrypt Y
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (m_RemoteIdentHash);
|
||||
decryption.SetIV (m_IV);
|
||||
decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ());
|
||||
decryption.Decrypt (m_SessionCreatedBuffer, 32, m_IV, GetRemotePub ());
|
||||
// decryption key for next block (m_K)
|
||||
if (!KDF2Alice ())
|
||||
{
|
||||
@@ -995,7 +991,7 @@ namespace transport
|
||||
i2p::transport::transports.UpdateReceivedBytes (bytes_transferred + 2);
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false))
|
||||
if (m_Server.AEADChaCha20Poly1305Decrypt (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen))
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: Received message decrypted");
|
||||
ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16);
|
||||
@@ -1184,7 +1180,7 @@ namespace transport
|
||||
}
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
|
||||
i2p::crypto::AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers
|
||||
m_Server.AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers
|
||||
SetNextSentFrameLength (totalLen + 16, first->GetNTCP2Header () - 5); // frame length right before first block
|
||||
|
||||
// send buffers
|
||||
@@ -1215,7 +1211,7 @@ namespace transport
|
||||
// encrypt
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
|
||||
i2p::crypto::AEADChaCha20Poly1305Encrypt ({ {m_NextSendBuffer + 2, payloadLen} }, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2);
|
||||
m_Server.AEADChaCha20Poly1305Encrypt ({ {m_NextSendBuffer + 2, payloadLen} }, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2);
|
||||
SetNextSentFrameLength (payloadLen + 16, m_NextSendBuffer);
|
||||
// send
|
||||
m_IsSending = true;
|
||||
@@ -1984,5 +1980,17 @@ namespace transport
|
||||
else
|
||||
m_Address4 = addr;
|
||||
}
|
||||
|
||||
void NTCP2Server::AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs,
|
||||
const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
|
||||
{
|
||||
return m_Encryptor.Encrypt (bufs, key, nonce, mac);
|
||||
}
|
||||
|
||||
bool NTCP2Server::AEADChaCha20Poly1305Decrypt (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)
|
||||
{
|
||||
return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +272,11 @@ namespace transport
|
||||
auto& GetService () { return GetIOService (); };
|
||||
auto& GetEstablisherService () { return m_EstablisherService.GetService (); };
|
||||
std::mt19937& GetRng () { return m_Rng; };
|
||||
void AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs,
|
||||
const uint8_t * key, const uint8_t * nonce, uint8_t * mac);
|
||||
bool AEADChaCha20Poly1305Decrypt (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 AddNTCP2Session (std::shared_ptr<NTCP2Session> session, bool incoming = false);
|
||||
void RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session);
|
||||
@@ -309,9 +314,12 @@ namespace transport
|
||||
uint16_t m_ProxyPort;
|
||||
boost::asio::ip::tcp::resolver m_Resolver;
|
||||
std::unique_ptr<boost::asio::ip::tcp::endpoint> m_ProxyEndpoint;
|
||||
|
||||
std::shared_ptr<boost::asio::ip::tcp::endpoint> m_Address4, m_Address6, m_YggdrasilAddress;
|
||||
std::mt19937 m_Rng;
|
||||
EstablisherService m_EstablisherService;
|
||||
i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor;
|
||||
i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -637,7 +637,7 @@ namespace data
|
||||
if (checkForExpiration && uptime > i2p::transport::SSU2_TO_INTRODUCER_SESSION_DURATION) // 1 hour
|
||||
expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
|
||||
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
|
||||
bool isOffline = checkForExpiration && i2p::transport::transports.GetNumPeers () < NETDB_MIN_TRANSPORTS; // enough routers and uptime, but no tranports
|
||||
bool isOffline = checkForExpiration && i2p::transport::transports.GetNumPeers () < NETDB_MIN_TRANSPORTS; // enough routers and uptime, but no transports
|
||||
|
||||
std::list<std::pair<std::string, std::shared_ptr<RouterInfo::Buffer> > > saveToDisk;
|
||||
std::list<std::string> removeFromDisk;
|
||||
|
||||
@@ -1389,7 +1389,7 @@ namespace transport
|
||||
excluded.insert (ident);
|
||||
}
|
||||
|
||||
// sesssion about to expire are not counted
|
||||
// session about to expire are not counted
|
||||
for (auto i = introducers.size (); i < SSU2_MAX_NUM_INTRODUCERS + numOldSessions; i++)
|
||||
{
|
||||
auto introducer = i2p::data::netdb.GetRandomSSU2Introducer (v4, excluded);
|
||||
@@ -1516,6 +1516,18 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
bool SSU2Server::AEADChaCha20Poly1305Encrypt (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)
|
||||
{
|
||||
return m_Encryptor.Encrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
|
||||
}
|
||||
|
||||
bool SSU2Server::AEADChaCha20Poly1305Decrypt (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)
|
||||
{
|
||||
return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
|
||||
}
|
||||
|
||||
void SSU2Server::SendThroughProxy (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
|
||||
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to)
|
||||
{
|
||||
|
||||
@@ -82,6 +82,10 @@ namespace transport
|
||||
bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep, bool max = true);
|
||||
void AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts);
|
||||
std::mt19937& GetRng () { return m_Rng; }
|
||||
bool AEADChaCha20Poly1305Encrypt (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 AEADChaCha20Poly1305Decrypt (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 IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; }
|
||||
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
|
||||
void AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from);
|
||||
@@ -200,6 +204,8 @@ namespace transport
|
||||
std::unordered_map<uint32_t, std::pair <std::weak_ptr<SSU2PeerTestSession>, uint64_t > > m_RequestedPeerTests; // nonce->(Alice, timestamp)
|
||||
std::list<Packet *> m_ReceivedPacketsQueue;
|
||||
mutable std::mutex m_ReceivedPacketsQueueMutex;
|
||||
i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor;
|
||||
i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor;
|
||||
|
||||
// proxy
|
||||
bool m_IsThroughProxy;
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace transport
|
||||
void SSU2PeerTestSession::HandleAddress (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (!ExtractEndpoint (buf, len, m_OurEndpoint))
|
||||
LogPrint (eLogWarning, "SSU2: Can't hanlde address block from peer test message");
|
||||
LogPrint (eLogWarning, "SSU2: Can't handle address block from peer test message");
|
||||
}
|
||||
|
||||
void SSU2PeerTestSession::HandlePeerTest (const uint8_t * buf, size_t len)
|
||||
@@ -89,7 +89,7 @@ namespace transport
|
||||
{
|
||||
if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ())
|
||||
{
|
||||
m_PeerTestResendTimer.cancel (); // calcel delayed msg 6 if any
|
||||
m_PeerTestResendTimer.cancel (); // cancel delayed msg 6 if any
|
||||
m_IsConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ());
|
||||
if (GetAddress ())
|
||||
{
|
||||
|
||||
@@ -349,7 +349,7 @@ namespace transport
|
||||
|
||||
void SSU2Session::Done ()
|
||||
{
|
||||
m_Server.GetService ().post (std::bind (&SSU2Session::Terminate, shared_from_this ()));
|
||||
boost::asio::post (m_Server.GetService (), std::bind (&SSU2Session::Terminate, shared_from_this ()));
|
||||
}
|
||||
|
||||
void SSU2Session::SendLocalRouterInfo (bool update)
|
||||
@@ -357,7 +357,7 @@ namespace transport
|
||||
if (update || !IsOutgoing ())
|
||||
{
|
||||
auto s = shared_from_this ();
|
||||
m_Server.GetService ().post ([s]()
|
||||
boost::asio::post (m_Server.GetService (), [s]()
|
||||
{
|
||||
if (!s->IsEstablished ()) return;
|
||||
uint8_t payload[SSU2_MAX_PACKET_SIZE];
|
||||
@@ -389,7 +389,7 @@ namespace transport
|
||||
m_IntermediateQueue.splice (m_IntermediateQueue.end (), msgs);
|
||||
}
|
||||
if (empty)
|
||||
m_Server.GetService ().post (std::bind (&SSU2Session::PostI2NPMessages, shared_from_this ()));
|
||||
boost::asio::post (m_Server.GetService (), std::bind (&SSU2Session::PostI2NPMessages, shared_from_this ()));
|
||||
}
|
||||
|
||||
void SSU2Session::PostI2NPMessages ()
|
||||
@@ -1455,7 +1455,7 @@ namespace transport
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (m_SendPacketNum, nonce);
|
||||
uint8_t payload[SSU2_MAX_PACKET_SIZE];
|
||||
i2p::crypto::AEADChaCha20Poly1305 (buf, len, header.buf, 16, m_KeyDataSend, nonce, payload, SSU2_MAX_PACKET_SIZE, true);
|
||||
m_Server.AEADChaCha20Poly1305Encrypt (buf, len, header.buf, 16, m_KeyDataSend, nonce, payload, SSU2_MAX_PACKET_SIZE);
|
||||
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (len - 8));
|
||||
header.ll[1] ^= CreateHeaderMask (m_KeyDataSend + 32, payload + (len + 4));
|
||||
m_Server.Send (header.buf, 16, payload, len + 16, m_RemoteEndpoint);
|
||||
@@ -1495,8 +1495,8 @@ namespace transport
|
||||
uint32_t packetNum = be32toh (header.h.packetNum);
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (packetNum, nonce);
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + 16, payloadSize, header.buf, 16,
|
||||
m_KeyDataReceive, nonce, payload, payloadSize, false))
|
||||
if (!m_Server.AEADChaCha20Poly1305Decrypt (buf + 16, payloadSize, header.buf, 16,
|
||||
m_KeyDataReceive, nonce, payload, payloadSize))
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Data AEAD verification failed ");
|
||||
return;
|
||||
@@ -2052,7 +2052,7 @@ namespace transport
|
||||
auto vec = std::make_shared<std::vector<uint8_t> >(len);
|
||||
memcpy (vec->data (), buf, len);
|
||||
auto s = shared_from_this ();
|
||||
m_Server.GetService ().post ([s, vec, attempts]()
|
||||
boost::asio::post (m_Server.GetService (), [s, vec, attempts]()
|
||||
{
|
||||
LogPrint (eLogDebug, "SSU2: RelayIntro attempt ", attempts + 1);
|
||||
s->HandleRelayIntro (vec->data (), vec->size (), attempts + 1);
|
||||
|
||||
@@ -958,7 +958,7 @@ namespace stream
|
||||
if (choking || requestImmediateAck)
|
||||
{
|
||||
htobe16buf (packet + size, 2); // 2 bytes delay interval
|
||||
htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediated ack interval
|
||||
htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediate ack interval
|
||||
size += 2;
|
||||
if (requestImmediateAck) // ack request sent
|
||||
{
|
||||
@@ -1147,7 +1147,6 @@ namespace stream
|
||||
m_CurrentOutboundTunnel = routingPath->outboundTunnel;
|
||||
m_CurrentRemoteLease = routingPath->remoteLease;
|
||||
m_RTT = routingPath->rtt;
|
||||
m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.3 + m_Jitter)); // TODO: implement it better
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -298,7 +298,7 @@ namespace stream
|
||||
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample;
|
||||
double m_Jitter;
|
||||
uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds
|
||||
m_LastSendTime, m_RemoteLeaseChangeTime; // miliseconds
|
||||
m_LastSendTime, m_RemoteLeaseChangeTime; // milliseconds
|
||||
uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed
|
||||
int m_NumResendAttempts, m_NumPacketsToSend;
|
||||
size_t m_MTU;
|
||||
|
||||
@@ -434,8 +434,7 @@ namespace tunnel
|
||||
else
|
||||
{
|
||||
encryption.SetKey (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET);
|
||||
encryption.SetIV (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET);
|
||||
encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply);
|
||||
encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, reply);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -79,8 +79,7 @@ namespace tunnel
|
||||
uint8_t * record = records + index*TUNNEL_BUILD_RECORD_SIZE;
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (replyKey);
|
||||
decryption.SetIV (replyIV);
|
||||
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record);
|
||||
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, replyIV, record);
|
||||
}
|
||||
|
||||
void ECIESTunnelHopConfig::EncryptECIES (const uint8_t * plainText, size_t len, uint8_t * encrypted)
|
||||
|
||||
@@ -240,13 +240,13 @@ namespace tunnel
|
||||
auto currentTransport = m_CurrentTransport.lock ();
|
||||
if (!currentTransport)
|
||||
{
|
||||
// try to obtain transport from peding reequest or send thought transport is not complete
|
||||
// try to obtain transport from pending request or send thought transport is not complete
|
||||
if (m_PendingTransport.valid ()) // pending request?
|
||||
{
|
||||
if (m_PendingTransport.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
|
||||
{
|
||||
// pending request complete
|
||||
currentTransport = m_PendingTransport.get (); // take tarnsports used in pending request
|
||||
currentTransport = m_PendingTransport.get (); // take transports used in pending request
|
||||
if (currentTransport)
|
||||
{
|
||||
if (currentTransport->IsEstablished ())
|
||||
@@ -257,7 +257,7 @@ namespace tunnel
|
||||
}
|
||||
else // still pending
|
||||
{
|
||||
// send through transports, but don't update pedning transport
|
||||
// send through transports, but don't update pending transport
|
||||
i2p::transport::transports.SendMessages (m_Tunnel.GetNextIdentHash (), std::move (newTunnelMsgs));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -37,9 +37,7 @@ namespace api
|
||||
i2p::fs::Init();
|
||||
|
||||
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
|
||||
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
|
||||
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
|
||||
i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
|
||||
i2p::crypto::InitCrypto (precomputation);
|
||||
|
||||
int netID; i2p::config::GetOption("netid", netID);
|
||||
i2p::context.SetNetID (netID);
|
||||
|
||||
@@ -879,7 +879,7 @@ namespace client
|
||||
if (!remoteSession || !m_Destination->SendMsg (buf + offset, payloadLen, remoteSession, nonce))
|
||||
{
|
||||
i2p::data::IdentHash identHash;
|
||||
SHA256(ident, identSize, identHash); // caclulate ident hash, because we don't need full identity
|
||||
SHA256(ident, identSize, identHash); // calculate ident hash, because we don't need full identity
|
||||
m_Destination->SendMsgTo (buf + offset, payloadLen, identHash, nonce);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace client
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from differend address. Removed");
|
||||
LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from different address. Removed");
|
||||
m_Sessions.erase (it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,10 @@ set(test-eddsa_SRCS
|
||||
test-eddsa.cpp
|
||||
)
|
||||
|
||||
set(test-aes_SRCS
|
||||
test-aes.cpp
|
||||
)
|
||||
|
||||
add_executable(test-http-merge_chunked ${test-http-merge_chunked_SRCS})
|
||||
add_executable(test-http-req ${test-http-req_SRCS})
|
||||
add_executable(test-http-res ${test-http-res_SRCS})
|
||||
@@ -77,6 +81,7 @@ add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS})
|
||||
add_executable(test-blinding ${test-blinding_SRCS})
|
||||
add_executable(test-elligator ${test-elligator_SRCS})
|
||||
add_executable(test-eddsa ${test-eddsa_SRCS})
|
||||
add_executable(test-aes ${test-aes_SRCS})
|
||||
|
||||
set(LIBS
|
||||
libi2pd
|
||||
@@ -101,6 +106,7 @@ target_link_libraries(test-aeadchacha20poly1305 ${LIBS})
|
||||
target_link_libraries(test-blinding ${LIBS})
|
||||
target_link_libraries(test-elligator ${LIBS})
|
||||
target_link_libraries(test-eddsa ${LIBS})
|
||||
target_link_libraries(test-aes ${LIBS})
|
||||
|
||||
add_test(test-http-merge_chunked ${TEST_PATH}/test-http-merge_chunked)
|
||||
add_test(test-http-req ${TEST_PATH}/test-http-req)
|
||||
@@ -114,3 +120,4 @@ add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305)
|
||||
add_test(test-blinding ${TEST_PATH}/test-blinding)
|
||||
add_test(test-elligator ${TEST_PATH}/test-elligator)
|
||||
add_test(test-eddsa ${TEST_PATH}/test-eddsa)
|
||||
add_test(test-aes ${TEST_PATH}/test-aes)
|
||||
|
||||
@@ -8,7 +8,7 @@ LIBI2PD = ../libi2pd.a
|
||||
TESTS = \
|
||||
test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \
|
||||
test-gost test-gost-sig test-base-64 test-aeadchacha20poly1305 test-blinding \
|
||||
test-elligator test-eddsa
|
||||
test-elligator test-eddsa test-aes
|
||||
|
||||
ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
|
||||
CXXFLAGS += -DWIN32_LEAN_AND_MEAN
|
||||
@@ -56,6 +56,9 @@ test-elligator: test-elligator.cpp $(LIBI2PD)
|
||||
test-eddsa: test-eddsa.cpp $(LIBI2PD)
|
||||
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
test-aes: test-aes.cpp $(LIBI2PD)
|
||||
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
run: $(TESTS)
|
||||
@for TEST in $(TESTS); do echo Running $$TEST; ./$$TEST ; done
|
||||
|
||||
|
||||
69
tests/test-aes.cpp
Normal file
69
tests/test-aes.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <cassert>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Crypto.h"
|
||||
|
||||
uint8_t ecb_key1[32] =
|
||||
{
|
||||
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
|
||||
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
|
||||
};
|
||||
|
||||
uint8_t ecb_plain1[16] =
|
||||
{
|
||||
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
|
||||
};
|
||||
|
||||
uint8_t ecb_cipher1[16] =
|
||||
{
|
||||
0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8
|
||||
};
|
||||
|
||||
uint8_t cbc_key1[32] =
|
||||
{
|
||||
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
|
||||
0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
|
||||
};
|
||||
|
||||
uint8_t cbc_iv1[16] =
|
||||
{
|
||||
0xF5, 0x8C, 0x4C, 0x04, 0xD6, 0xE5, 0xF1, 0xBA, 0x77, 0x9E, 0xAB, 0xFB, 0x5F, 0x7B, 0xFB, 0xD6
|
||||
};
|
||||
|
||||
uint8_t cbc_plain1[16] =
|
||||
{
|
||||
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51
|
||||
};
|
||||
|
||||
uint8_t cbc_cipher1[16] =
|
||||
{
|
||||
0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
// ECB encrypt test1
|
||||
i2p::crypto::ECBEncryption ecbencryption;
|
||||
ecbencryption.SetKey (ecb_key1);
|
||||
uint8_t out[16];
|
||||
ecbencryption.Encrypt (ecb_plain1, out);
|
||||
assert (memcmp (ecb_cipher1, out, 16) == 0);
|
||||
|
||||
// ECB decrypt test1
|
||||
i2p::crypto::ECBDecryption ecbdecryption;
|
||||
ecbdecryption.SetKey (ecb_key1);
|
||||
ecbdecryption.Decrypt (ecb_cipher1, out);
|
||||
assert (memcmp (ecb_plain1, out, 16) == 0);
|
||||
// CBC encrypt test
|
||||
i2p::crypto::CBCEncryption cbcencryption;
|
||||
cbcencryption.SetKey (cbc_key1);
|
||||
cbcencryption.Encrypt (cbc_plain1, 16, cbc_iv1, out);
|
||||
assert (memcmp (cbc_cipher1, out, 16) == 0);
|
||||
// CBC decrypt test
|
||||
i2p::crypto::CBCDecryption cbcdecryption;
|
||||
cbcdecryption.SetKey (cbc_key1);
|
||||
cbcdecryption.Decrypt (cbc_cipher1, 16, cbc_iv1, out);
|
||||
assert (memcmp (cbc_plain1, out, 16) == 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user