mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-17 03:19:56 +00:00
commit
ddf3774aec
@ -1,5 +1,5 @@
|
|||||||
# set defaults instead redefine
|
# set defaults instead redefine
|
||||||
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation -Wno-psabi
|
||||||
LDFLAGS ?= ${LD_DEBUG}
|
LDFLAGS ?= ${LD_DEBUG}
|
||||||
|
|
||||||
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
||||||
|
@ -19,7 +19,6 @@ option(WITH_GUI "Include GUI (currently MS Windows only)" ON)
|
|||||||
option(WITH_MESHNET "Build for cjdns test network" OFF)
|
option(WITH_MESHNET "Build for cjdns test network" OFF)
|
||||||
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
||||||
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
||||||
option(WITH_I2LUA "Build for i2lua" OFF)
|
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
||||||
@ -88,10 +87,6 @@ if (WIN32 OR MSYS)
|
|||||||
list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
|
list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WITH_I2LUA)
|
|
||||||
add_definitions(-DI2LUA)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(libi2pd ${LIBI2PD_SRC})
|
add_library(libi2pd ${LIBI2PD_SRC})
|
||||||
set_target_properties(libi2pd PROPERTIES PREFIX "")
|
set_target_properties(libi2pd PROPERTIES PREFIX "")
|
||||||
|
|
||||||
@ -414,7 +409,6 @@ message(STATUS " PCH : ${WITH_PCH}")
|
|||||||
message(STATUS " MESHNET : ${WITH_MESHNET}")
|
message(STATUS " MESHNET : ${WITH_MESHNET}")
|
||||||
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
||||||
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
|
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
|
||||||
message(STATUS " I2LUA : ${WITH_I2LUA}")
|
|
||||||
message(STATUS "---------------------------------------")
|
message(STATUS "---------------------------------------")
|
||||||
|
|
||||||
#Handle paths nicely
|
#Handle paths nicely
|
||||||
|
@ -1141,6 +1141,8 @@ namespace http {
|
|||||||
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
|
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
|
||||||
{
|
{
|
||||||
reply.add_header("X-Frame-Options", "SAMEORIGIN");
|
reply.add_header("X-Frame-Options", "SAMEORIGIN");
|
||||||
|
reply.add_header("X-Content-Type-Options", "nosniff");
|
||||||
|
reply.add_header("X-XSS-Protection", "1; mode=block");
|
||||||
reply.add_header("Content-Type", "text/html");
|
reply.add_header("Content-Type", "text/html");
|
||||||
reply.body = content;
|
reply.body = content;
|
||||||
|
|
||||||
|
@ -931,32 +931,6 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef I2LUA
|
|
||||||
void ClientDestination::Ready(ReadyPromise & p)
|
|
||||||
{
|
|
||||||
ScheduleCheckForReady(&p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::ScheduleCheckForReady(ReadyPromise * p)
|
|
||||||
{
|
|
||||||
// tick every 100ms
|
|
||||||
m_ReadyChecker.expires_from_now(boost::posix_time::milliseconds(100));
|
|
||||||
m_ReadyChecker.async_wait([&, p] (const boost::system::error_code & ecode) {
|
|
||||||
HandleCheckForReady(ecode, p);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p)
|
|
||||||
{
|
|
||||||
if(ecode) // error happened
|
|
||||||
p->set_value(nullptr);
|
|
||||||
else if(IsReady()) // we are ready
|
|
||||||
p->set_value(std::shared_ptr<ClientDestination>(this));
|
|
||||||
else // we are not ready
|
|
||||||
ScheduleCheckForReady(p);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
uint32_t length = bufbe32toh (buf);
|
uint32_t length = bufbe32toh (buf);
|
||||||
@ -1173,7 +1147,7 @@ namespace client
|
|||||||
if (m_DatagramDestination) m_DatagramDestination->CleanUp ();
|
if (m_DatagramDestination) m_DatagramDestination->CleanUp ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const
|
||||||
{
|
{
|
||||||
if (m_Decryptor)
|
if (m_Decryptor)
|
||||||
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
||||||
|
@ -8,9 +8,6 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#ifdef I2LUA
|
|
||||||
#include <future>
|
|
||||||
#endif
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "TunnelPool.h"
|
#include "TunnelPool.h"
|
||||||
@ -196,13 +193,6 @@ namespace client
|
|||||||
class ClientDestination: public LeaseSetDestination
|
class ClientDestination: public LeaseSetDestination
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#ifdef I2LUA
|
|
||||||
// type for informing that a client destination is ready
|
|
||||||
typedef std::promise<std::shared_ptr<ClientDestination> > ReadyPromise;
|
|
||||||
// informs promise with shared_from_this() when this destination is ready to use
|
|
||||||
// if cancelled before ready, informs promise with nullptr
|
|
||||||
void Ready(ReadyPromise & p);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
||||||
bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
@ -237,7 +227,7 @@ namespace client
|
|||||||
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
|
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
|
||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
||||||
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; };
|
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; };
|
||||||
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; };
|
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; };
|
||||||
@ -251,14 +241,10 @@ namespace client
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<ClientDestination> GetSharedFromThis ()
|
std::shared_ptr<ClientDestination> GetSharedFromThis () {
|
||||||
{ return std::static_pointer_cast<ClientDestination>(shared_from_this ()); }
|
return std::static_pointer_cast<ClientDestination>(shared_from_this ());
|
||||||
|
}
|
||||||
void PersistTemporaryKeys ();
|
void PersistTemporaryKeys ();
|
||||||
#ifdef I2LUA
|
|
||||||
void ScheduleCheckForReady(ReadyPromise * p);
|
|
||||||
void HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
|
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -138,7 +138,7 @@ namespace garlic
|
|||||||
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
|
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
|
||||||
|
|
||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr); // x25519(bsk, aepk)
|
GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, aepk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
|
|
||||||
// decrypt flags/static
|
// decrypt flags/static
|
||||||
@ -160,7 +160,7 @@ namespace garlic
|
|||||||
{
|
{
|
||||||
// static key, fs is apk
|
// static key, fs is apk
|
||||||
memcpy (m_RemoteStaticKey, fs, 32);
|
memcpy (m_RemoteStaticKey, fs, 32);
|
||||||
GetOwner ()->Decrypt (fs, sharedSecret, nullptr); // x25519(bsk, apk)
|
GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, apk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
}
|
}
|
||||||
else // all zeros flags
|
else // all zeros flags
|
||||||
@ -211,7 +211,7 @@ namespace garlic
|
|||||||
case eECIESx25519BlkAckRequest:
|
case eECIESx25519BlkAckRequest:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: ack request");
|
LogPrint (eLogDebug, "Garlic: ack request");
|
||||||
m_AckRequests.push_back ( {bufbe16toh (buf + offset), index});
|
m_AckRequests.push_back ({0, index}); // TODO: use actual tagsetid
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -250,7 +250,7 @@ namespace garlic
|
|||||||
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
|
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
|
||||||
offset += 48;
|
offset += 48;
|
||||||
// KDF2
|
// KDF2
|
||||||
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr); // x25519 (ask, bpk)
|
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bpk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
// encrypt payload
|
// encrypt payload
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
|
||||||
@ -298,7 +298,8 @@ namespace garlic
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
|
MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
|
||||||
out += 16;
|
offset += 16;
|
||||||
|
memcpy (m_NSRHeader, out, 56); // for possible next NSR
|
||||||
// KDF for payload
|
// KDF for payload
|
||||||
uint8_t keydata[64];
|
uint8_t keydata[64];
|
||||||
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
||||||
@ -308,18 +309,33 @@ namespace garlic
|
|||||||
m_SendTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
|
m_SendTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
|
||||||
m_SendTagset.NextSessionTagRatchet ();
|
m_SendTagset.NextSessionTagRatchet ();
|
||||||
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
|
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
|
||||||
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
||||||
// encrypt payload
|
// encrypt payload
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, keydata, nonce, out + offset, len + 16, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
|
LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_State = eSessionStateEstablished;
|
m_State = eSessionStateNewSessionReplySent;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
// we are Bob and sent NSR already
|
||||||
|
memcpy (out, m_NSRHeader, 56);
|
||||||
|
uint8_t nonce[12];
|
||||||
|
CreateNonce (0, nonce);
|
||||||
|
// encrypt payload
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len)
|
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
// we are Alice
|
// we are Alice
|
||||||
@ -339,7 +355,7 @@ namespace garlic
|
|||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
|
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
|
||||||
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr); // x25519 (ask, bepk)
|
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bepk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (0, nonce);
|
CreateNonce (0, nonce);
|
||||||
@ -419,6 +435,11 @@ namespace garlic
|
|||||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||||
switch (m_State)
|
switch (m_State)
|
||||||
{
|
{
|
||||||
|
case eSessionStateNewSessionReplySent:
|
||||||
|
m_State = eSessionStateEstablished;
|
||||||
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
|
[[fallthrough]];
|
||||||
|
#endif
|
||||||
case eSessionStateEstablished:
|
case eSessionStateEstablished:
|
||||||
return HandleExistingSessionMessage (buf, len, index);
|
return HandleExistingSessionMessage (buf, len, index);
|
||||||
case eSessionStateNew:
|
case eSessionStateNew:
|
||||||
@ -456,6 +477,11 @@ namespace garlic
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
len += 72;
|
len += 72;
|
||||||
break;
|
break;
|
||||||
|
case eSessionStateNewSessionReplySent:
|
||||||
|
if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
|
||||||
|
return nullptr;
|
||||||
|
len += 72;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -597,6 +623,41 @@ namespace garlic
|
|||||||
CleanupUnconfirmedLeaseSet (ts);
|
CleanupUnconfirmedLeaseSet (ts);
|
||||||
return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT;
|
return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
|
||||||
|
{
|
||||||
|
auto m = NewI2NPMessage ();
|
||||||
|
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
|
||||||
|
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
|
||||||
|
uint8_t nonce[12];
|
||||||
|
memset (nonce, 0, 12); // n = 0
|
||||||
|
size_t offset = 0;
|
||||||
|
memcpy (buf + offset, &tag, 8); offset += 8;
|
||||||
|
auto payload = buf + offset;
|
||||||
|
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
|
||||||
|
size_t len = cloveSize + 3;
|
||||||
|
payload[0] = eECIESx25519BlkGalicClove; // clove type
|
||||||
|
htobe16buf (payload + 1, cloveSize); // size
|
||||||
|
payload += 3;
|
||||||
|
*payload = 0; payload++; // flag and delivery instructions
|
||||||
|
*payload = msg->GetTypeID (); // I2NP msg type
|
||||||
|
htobe32buf (payload + 1, msg->GetMsgID ()); // msgID
|
||||||
|
htobe32buf (payload + 5, msg->GetExpiration ()/1000); // expiration in seconds
|
||||||
|
memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
|
||||||
|
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
offset += len + 16;
|
||||||
|
|
||||||
|
htobe32buf (m->GetPayload (), offset);
|
||||||
|
m->len += offset + 4;
|
||||||
|
m->FillI2NPMessageHeader (eI2NPGarlic);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ namespace garlic
|
|||||||
eSessionStateNew =0,
|
eSessionStateNew =0,
|
||||||
eSessionStateNewSessionReceived,
|
eSessionStateNewSessionReceived,
|
||||||
eSessionStateNewSessionSent,
|
eSessionStateNewSessionSent,
|
||||||
|
eSessionStateNewSessionReplySent,
|
||||||
eSessionStateEstablished
|
eSessionStateEstablished
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,6 +107,7 @@ namespace garlic
|
|||||||
|
|
||||||
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
|
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
|
|
||||||
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg);
|
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg);
|
||||||
@ -117,14 +119,17 @@ namespace garlic
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
|
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
|
||||||
uint8_t m_Aepk[32]; // Alice's ephemeral keys TODO: for incoming only
|
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
|
||||||
|
uint8_t m_NSRHeader[56], m_NSRKey[32]; // new session reply, for incoming only
|
||||||
i2p::crypto::X25519Keys m_EphemeralKeys;
|
i2p::crypto::X25519Keys m_EphemeralKeys;
|
||||||
SessionState m_State = eSessionStateNew;
|
SessionState m_State = eSessionStateNew;
|
||||||
uint64_t m_LastActivityTimestamp = 0; // incoming
|
uint64_t m_LastActivityTimestamp = 0; // incoming
|
||||||
RatchetTagSet m_SendTagset, m_ReceiveTagset;
|
RatchetTagSet m_SendTagset, m_ReceiveTagset;
|
||||||
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
||||||
std::list<std::pair<uint16_t, int> > m_AckRequests; // (key_id, indeX)
|
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +495,7 @@ namespace garlic
|
|||||||
}
|
}
|
||||||
// otherwise assume ElGamal/AES
|
// otherwise assume ElGamal/AES
|
||||||
ElGamalBlock elGamal;
|
ElGamalBlock elGamal;
|
||||||
if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx))
|
if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
|
||||||
{
|
{
|
||||||
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
|
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
|
||||||
uint8_t iv[32]; // IV is first 16 bytes
|
uint8_t iv[32]; // IV is first 16 bytes
|
||||||
|
@ -95,6 +95,7 @@ namespace i2p
|
|||||||
// DatabaseLookup flags
|
// DatabaseLookup flags
|
||||||
const uint8_t DATABASE_LOOKUP_DELIVERY_FLAG = 0x01;
|
const uint8_t DATABASE_LOOKUP_DELIVERY_FLAG = 0x01;
|
||||||
const uint8_t DATABASE_LOOKUP_ENCRYPTION_FLAG = 0x02;
|
const uint8_t DATABASE_LOOKUP_ENCRYPTION_FLAG = 0x02;
|
||||||
|
const uint8_t DATABASE_LOOKUP_ECIES_FLAG = 0x10;
|
||||||
const uint8_t DATABASE_LOOKUP_TYPE_FLAGS_MASK = 0x0C;
|
const uint8_t DATABASE_LOOKUP_TYPE_FLAGS_MASK = 0x0C;
|
||||||
const uint8_t DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP = 0;
|
const uint8_t DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP = 0;
|
||||||
const uint8_t DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP = 0x04; // 0100
|
const uint8_t DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP = 0x04; // 0100
|
||||||
|
@ -34,12 +34,11 @@ namespace data
|
|||||||
}
|
}
|
||||||
|
|
||||||
IdentityEx::IdentityEx ():
|
IdentityEx::IdentityEx ():
|
||||||
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType):
|
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType)
|
||||||
m_IsVerifierCreated (false)
|
|
||||||
{
|
{
|
||||||
memcpy (m_StandardIdentity.publicKey, publicKey, 256); // publicKey in awlays assumed 256 regardless actual size, padding must be taken care of
|
memcpy (m_StandardIdentity.publicKey, publicKey, 256); // publicKey in awlays assumed 256 regardless actual size, padding must be taken care of
|
||||||
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
|
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
|
||||||
@ -141,19 +140,19 @@ namespace data
|
|||||||
}
|
}
|
||||||
|
|
||||||
IdentityEx::IdentityEx (const uint8_t * buf, size_t len):
|
IdentityEx::IdentityEx (const uint8_t * buf, size_t len):
|
||||||
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
||||||
{
|
{
|
||||||
FromBuffer (buf, len);
|
FromBuffer (buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityEx::IdentityEx (const IdentityEx& other):
|
IdentityEx::IdentityEx (const IdentityEx& other):
|
||||||
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
||||||
{
|
{
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityEx::IdentityEx (const Identity& standard):
|
IdentityEx::IdentityEx (const Identity& standard):
|
||||||
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
|
||||||
{
|
{
|
||||||
*this = standard;
|
*this = standard;
|
||||||
}
|
}
|
||||||
@ -161,6 +160,7 @@ namespace data
|
|||||||
IdentityEx::~IdentityEx ()
|
IdentityEx::~IdentityEx ()
|
||||||
{
|
{
|
||||||
delete[] m_ExtendedBuffer;
|
delete[] m_ExtendedBuffer;
|
||||||
|
delete m_Verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityEx& IdentityEx::operator=(const IdentityEx& other)
|
IdentityEx& IdentityEx::operator=(const IdentityEx& other)
|
||||||
@ -178,8 +178,8 @@ namespace data
|
|||||||
else
|
else
|
||||||
m_ExtendedBuffer = nullptr;
|
m_ExtendedBuffer = nullptr;
|
||||||
|
|
||||||
|
delete m_Verifier;
|
||||||
m_Verifier = nullptr;
|
m_Verifier = nullptr;
|
||||||
m_IsVerifierCreated = false;
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -193,8 +193,8 @@ namespace data
|
|||||||
m_ExtendedBuffer = nullptr;
|
m_ExtendedBuffer = nullptr;
|
||||||
m_ExtendedLen = 0;
|
m_ExtendedLen = 0;
|
||||||
|
|
||||||
|
delete m_Verifier;
|
||||||
m_Verifier = nullptr;
|
m_Verifier = nullptr;
|
||||||
m_IsVerifierCreated = false;
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -233,6 +233,7 @@ namespace data
|
|||||||
}
|
}
|
||||||
SHA256(buf, GetFullLen (), m_IdentHash);
|
SHA256(buf, GetFullLen (), m_IdentHash);
|
||||||
|
|
||||||
|
delete m_Verifier;
|
||||||
m_Verifier = nullptr;
|
m_Verifier = nullptr;
|
||||||
|
|
||||||
return GetFullLen ();
|
return GetFullLen ();
|
||||||
@ -381,33 +382,27 @@ namespace data
|
|||||||
|
|
||||||
void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const
|
void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const
|
||||||
{
|
{
|
||||||
if (!m_Verifier)
|
bool del = false;
|
||||||
{
|
{
|
||||||
auto created = m_IsVerifierCreated.exchange (true);
|
std::lock_guard<std::mutex> l(m_VerifierMutex);
|
||||||
if (!created)
|
if (!m_Verifier)
|
||||||
m_Verifier.reset (verifier);
|
m_Verifier = verifier;
|
||||||
else
|
else
|
||||||
{
|
del = true;
|
||||||
delete verifier;
|
|
||||||
int count = 0;
|
|
||||||
while (!m_Verifier && count < 500) // 5 seconds
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for (std::chrono::milliseconds(10));
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
if (!m_Verifier)
|
|
||||||
LogPrint (eLogError, "Identity: couldn't get verifier in 5 seconds");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
if (del)
|
||||||
delete verifier;
|
delete verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdentityEx::DropVerifier () const
|
void IdentityEx::DropVerifier () const
|
||||||
{
|
{
|
||||||
// TODO: potential race condition with Verify
|
i2p::crypto::Verifier * verifier;
|
||||||
m_IsVerifierCreated = false;
|
{
|
||||||
m_Verifier = nullptr;
|
std::lock_guard<std::mutex> l(m_VerifierMutex);
|
||||||
|
verifier = m_Verifier;
|
||||||
|
m_Verifier = nullptr;
|
||||||
|
}
|
||||||
|
delete verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key)
|
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Signature.h"
|
#include "Signature.h"
|
||||||
#include "CryptoKey.h"
|
#include "CryptoKey.h"
|
||||||
@ -125,8 +126,8 @@ namespace data
|
|||||||
|
|
||||||
Identity m_StandardIdentity;
|
Identity m_StandardIdentity;
|
||||||
IdentHash m_IdentHash;
|
IdentHash m_IdentHash;
|
||||||
mutable std::unique_ptr<i2p::crypto::Verifier> m_Verifier;
|
mutable i2p::crypto::Verifier * m_Verifier = nullptr;
|
||||||
mutable std::atomic_bool m_IsVerifierCreated; // make sure we don't create twice
|
mutable std::mutex m_VerifierMutex;
|
||||||
size_t m_ExtendedLen;
|
size_t m_ExtendedLen;
|
||||||
uint8_t * m_ExtendedBuffer;
|
uint8_t * m_ExtendedBuffer;
|
||||||
};
|
};
|
||||||
@ -224,7 +225,7 @@ namespace data
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~LocalDestination() {};
|
virtual ~LocalDestination() {};
|
||||||
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const = 0;
|
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL) const = 0;
|
||||||
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
|
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
|
||||||
|
|
||||||
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
|
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
|
||||||
|
@ -706,9 +706,13 @@ namespace transport
|
|||||||
// ready to communicate
|
// ready to communicate
|
||||||
auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already
|
auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already
|
||||||
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
|
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
|
||||||
m_Server.AddNTCP2Session (shared_from_this (), true);
|
if (m_Server.AddNTCP2Session (shared_from_this (), true))
|
||||||
Established ();
|
{
|
||||||
ReceiveLength ();
|
Established ();
|
||||||
|
ReceiveLength ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Terminate ();
|
Terminate ();
|
||||||
@ -1258,8 +1262,11 @@ namespace transport
|
|||||||
if (it != m_NTCP2Sessions.end ())
|
if (it != m_NTCP2Sessions.end ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: session to ", ident.ToBase64 (), " already exists");
|
LogPrint (eLogWarning, "NTCP2: session to ", ident.ToBase64 (), " already exists");
|
||||||
session->Terminate();
|
if (incoming)
|
||||||
return false;
|
// replace by new session
|
||||||
|
it->second->Terminate ();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
m_NTCP2Sessions.insert (std::make_pair (ident, session));
|
m_NTCP2Sessions.insert (std::make_pair (ident, session));
|
||||||
return true;
|
return true;
|
||||||
@ -1301,6 +1308,8 @@ namespace transport
|
|||||||
});
|
});
|
||||||
conn->GetSocket ().async_connect (boost::asio::ip::tcp::endpoint (address, port), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer));
|
conn->GetSocket ().async_connect (boost::asio::ip::tcp::endpoint (address, port), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
conn->Terminate ();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
#include "NTCP2.h"
|
#include "NTCP2.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
#include "NetDb.hpp"
|
#include "ECIESX25519AEADRatchetSession.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "NetDb.hpp"
|
||||||
|
|
||||||
using namespace i2p::transport;
|
using namespace i2p::transport;
|
||||||
|
|
||||||
@ -949,10 +950,20 @@ namespace data
|
|||||||
const uint8_t numTags = excluded[32];
|
const uint8_t numTags = excluded[32];
|
||||||
if (numTags)
|
if (numTags)
|
||||||
{
|
{
|
||||||
const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag
|
if (flag & DATABASE_LOOKUP_ECIES_FLAG)
|
||||||
i2p::garlic::ElGamalAESSession garlic (sessionKey, sessionTag);
|
{
|
||||||
replyMsg = garlic.WrapSingleMessage (replyMsg);
|
uint64_t tag;
|
||||||
if(replyMsg == nullptr) LogPrint(eLogError, "NetDb: failed to wrap message");
|
memcpy (&tag, excluded + 33, 8);
|
||||||
|
replyMsg = i2p::garlic::WrapECIESX25519AEADRatchetMessage (replyMsg, sessionKey, tag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag
|
||||||
|
i2p::garlic::ElGamalAESSession garlic (sessionKey, sessionTag);
|
||||||
|
replyMsg = garlic.WrapSingleMessage (replyMsg);
|
||||||
|
}
|
||||||
|
if (!replyMsg)
|
||||||
|
LogPrint (eLogError, "NetDb: failed to wrap message");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint(eLogWarning, "NetDb: encrypted reply requested but no tags provided");
|
LogPrint(eLogWarning, "NetDb: encrypted reply requested but no tags provided");
|
||||||
|
@ -724,7 +724,7 @@ namespace i2p
|
|||||||
return std::chrono::duration_cast<std::chrono::seconds> (std::chrono::steady_clock::now() - m_StartupTime).count ();
|
return std::chrono::duration_cast<std::chrono::seconds> (std::chrono::steady_clock::now() - m_StartupTime).count ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const
|
||||||
{
|
{
|
||||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, true) : false;
|
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, true) : false;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ namespace i2p
|
|||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
|
||||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
|
||||||
void SetLeaseSetUpdated () {};
|
void SetLeaseSetUpdated () {};
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
@ -67,8 +68,16 @@ namespace transport
|
|||||||
|
|
||||||
std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; }
|
std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; }
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetRemoteIdentity () { return m_RemoteIdentity; };
|
std::shared_ptr<const i2p::data::IdentityEx> GetRemoteIdentity ()
|
||||||
void SetRemoteIdentity (std::shared_ptr<const i2p::data::IdentityEx> ident) { m_RemoteIdentity = ident; };
|
{
|
||||||
|
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
|
||||||
|
return m_RemoteIdentity;
|
||||||
|
}
|
||||||
|
void SetRemoteIdentity (std::shared_ptr<const i2p::data::IdentityEx> ident)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
|
||||||
|
m_RemoteIdentity = ident;
|
||||||
|
}
|
||||||
|
|
||||||
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||||
@ -85,6 +94,7 @@ namespace transport
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
|
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
|
||||||
|
mutable std::mutex m_RemoteIdentityMutex;
|
||||||
std::shared_ptr<i2p::crypto::DHKeys> m_DHKeysPair; // X - for client and Y - for server
|
std::shared_ptr<i2p::crypto::DHKeys> m_DHKeysPair; // X - for client and Y - for server
|
||||||
size_t m_NumSentBytes, m_NumReceivedBytes;
|
size_t m_NumSentBytes, m_NumReceivedBytes;
|
||||||
bool m_IsOutgoing;
|
bool m_IsOutgoing;
|
||||||
|
@ -576,7 +576,6 @@ namespace tunnel
|
|||||||
for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();)
|
for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();)
|
||||||
{
|
{
|
||||||
auto tunnel = it->second;
|
auto tunnel = it->second;
|
||||||
auto pool = tunnel->GetTunnelPool();
|
|
||||||
switch (tunnel->GetState ())
|
switch (tunnel->GetState ())
|
||||||
{
|
{
|
||||||
case eTunnelStatePending:
|
case eTunnelStatePending:
|
||||||
@ -599,8 +598,6 @@ namespace tunnel
|
|||||||
hop = hop->next;
|
hop = hop->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for i2lua
|
|
||||||
if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultTimeout);
|
|
||||||
// delete
|
// delete
|
||||||
it = pendingTunnels.erase (it);
|
it = pendingTunnels.erase (it);
|
||||||
m_NumFailedTunnelCreations++;
|
m_NumFailedTunnelCreations++;
|
||||||
@ -610,9 +607,6 @@ namespace tunnel
|
|||||||
break;
|
break;
|
||||||
case eTunnelStateBuildFailed:
|
case eTunnelStateBuildFailed:
|
||||||
LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted");
|
LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted");
|
||||||
// for i2lua
|
|
||||||
if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultRejected);
|
|
||||||
|
|
||||||
it = pendingTunnels.erase (it);
|
it = pendingTunnels.erase (it);
|
||||||
m_NumFailedTunnelCreations++;
|
m_NumFailedTunnelCreations++;
|
||||||
break;
|
break;
|
||||||
|
@ -88,8 +88,6 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
if (m_LocalDestination)
|
if (m_LocalDestination)
|
||||||
m_LocalDestination->SetLeaseSetUpdated ();
|
m_LocalDestination->SetLeaseSetUpdated ();
|
||||||
|
|
||||||
OnTunnelBuildResult(createdTunnel, eBuildResultOkay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelPool::TunnelExpired (std::shared_ptr<InboundTunnel> expiredTunnel)
|
void TunnelPool::TunnelExpired (std::shared_ptr<InboundTunnel> expiredTunnel)
|
||||||
@ -112,8 +110,6 @@ namespace tunnel
|
|||||||
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
|
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
|
||||||
m_OutboundTunnels.insert (createdTunnel);
|
m_OutboundTunnels.insert (createdTunnel);
|
||||||
}
|
}
|
||||||
OnTunnelBuildResult(createdTunnel, eBuildResultOkay);
|
|
||||||
|
|
||||||
//CreatePairedInboundTunnel (createdTunnel);
|
//CreatePairedInboundTunnel (createdTunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,11 +592,5 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
return tun;
|
return tun;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelPool::OnTunnelBuildResult(std::shared_ptr<Tunnel> tunnel, TunnelBuildResult result)
|
|
||||||
{
|
|
||||||
auto peers = tunnel->GetPeers();
|
|
||||||
if(m_CustomPeerSelector) m_CustomPeerSelector->OnBuildResult(peers, tunnel->IsInbound(), result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,6 @@ namespace tunnel
|
|||||||
class InboundTunnel;
|
class InboundTunnel;
|
||||||
class OutboundTunnel;
|
class OutboundTunnel;
|
||||||
|
|
||||||
|
|
||||||
enum TunnelBuildResult {
|
|
||||||
eBuildResultOkay, // tunnel was built okay
|
|
||||||
eBuildResultRejected, // tunnel build was explicitly rejected
|
|
||||||
eBuildResultTimeout // tunnel build timed out
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::shared_ptr<const i2p::data::IdentityEx> Peer;
|
typedef std::shared_ptr<const i2p::data::IdentityEx> Peer;
|
||||||
typedef std::vector<Peer> Path;
|
typedef std::vector<Peer> Path;
|
||||||
|
|
||||||
@ -38,7 +31,6 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
virtual ~ITunnelPeerSelector() {};
|
virtual ~ITunnelPeerSelector() {};
|
||||||
virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0;
|
virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0;
|
||||||
virtual bool OnBuildResult(const Path & peers, bool isInbound, TunnelBuildResult result) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -98,8 +90,6 @@ namespace tunnel
|
|||||||
std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude=nullptr) const;
|
std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude=nullptr) const;
|
||||||
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude=nullptr) const;
|
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude=nullptr) const;
|
||||||
|
|
||||||
void OnTunnelBuildResult(std::shared_ptr<Tunnel> tunnel, TunnelBuildResult result);
|
|
||||||
|
|
||||||
// for overriding tunnel peer selection
|
// for overriding tunnel peer selection
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
|
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ namespace client
|
|||||||
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), m_EncryptionPrivateKey);
|
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), m_EncryptionPrivateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const
|
||||||
{
|
{
|
||||||
if (m_Decryptor)
|
if (m_Decryptor)
|
||||||
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
||||||
|
@ -80,7 +80,7 @@ namespace client
|
|||||||
void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession
|
void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession
|
||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
|
||||||
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; };
|
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; };
|
||||||
// TODO: implement GetEncryptionPublicKey
|
// TODO: implement GetEncryptionPublicKey
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Identity; };
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Identity; };
|
||||||
|
@ -94,10 +94,5 @@ namespace client
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MatchedTunnelDestination::OnBuildResult(const i2p::tunnel::Path & path, bool inbound, i2p::tunnel::TunnelBuildResult result)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ namespace client
|
|||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound);
|
bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound);
|
||||||
bool OnBuildResult(const i2p::tunnel::Path & peers, bool inbound, i2p::tunnel::TunnelBuildResult result);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ResolveCurrentLeaseSet();
|
void ResolveCurrentLeaseSet();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user