Browse Source

GarlicRoutingSession/ElGamalAESSession split

pull/1458/head
orignal 5 years ago
parent
commit
d7d964bf57
  1. 242
      libi2pd/Garlic.cpp
  2. 111
      libi2pd/Garlic.h
  3. 2
      libi2pd/NetDb.cpp

242
libi2pd/Garlic.cpp

@ -19,23 +19,16 @@ namespace i2p
namespace garlic namespace garlic
{ {
GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner,
std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet): std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet):
m_Owner (owner), m_Destination (destination), m_NumTags (numTags), m_Owner (owner), m_Destination (destination),
m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend),
m_LeaseSetUpdateMsgID (0) m_LeaseSetUpdateMsgID (0)
{ {
// create new session tags and session key
RAND_bytes (m_SessionKey, 32);
m_Encryption.SetKey (m_SessionKey);
} }
GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): GarlicRoutingSession::GarlicRoutingSession ():
m_Owner (nullptr), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) m_Owner (nullptr), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0)
{ {
memcpy (m_SessionKey, sessionKey, 32);
m_Encryption.SetKey (m_SessionKey);
m_SessionTags.push_back (sessionTag);
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
} }
GarlicRoutingSession::~GarlicRoutingSession () GarlicRoutingSession::~GarlicRoutingSession ()
@ -67,88 +60,24 @@ namespace garlic
m_SharedRoutingPath = path; m_SharedRoutingPath = path;
} }
GarlicRoutingSession::UnconfirmedTags * GarlicRoutingSession::GenerateSessionTags () ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
{ std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
auto tags = new UnconfirmedTags (m_NumTags); GarlicRoutingSession (owner, destination, attachLeaseSet), m_NumTags (numTags)
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
for (int i = 0; i < m_NumTags; i++)
{
RAND_bytes (tags->sessionTags[i], 32);
tags->sessionTags[i].creationTime = tags->tagsCreationTime;
}
return tags;
}
void GarlicRoutingSession::MessageConfirmed (uint32_t msgID)
{
TagsConfirmed (msgID);
if (msgID == m_LeaseSetUpdateMsgID)
{
m_LeaseSetUpdateStatus = eLeaseSetUpToDate;
m_LeaseSetUpdateMsgID = 0;
LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed");
}
else
CleanupExpiredTags ();
}
void GarlicRoutingSession::TagsConfirmed (uint32_t msgID)
{
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
auto it = m_UnconfirmedTagsMsgs.find (msgID);
if (it != m_UnconfirmedTagsMsgs.end ())
{
auto& tags = it->second;
if (ts < tags->tagsCreationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT)
{
for (int i = 0; i < tags->numTags; i++)
m_SessionTags.push_back (tags->sessionTags[i]);
}
m_UnconfirmedTagsMsgs.erase (it);
}
}
bool GarlicRoutingSession::CleanupExpiredTags ()
{ {
auto ts = i2p::util::GetSecondsSinceEpoch (); // create new session tags and session key
for (auto it = m_SessionTags.begin (); it != m_SessionTags.end ();) RAND_bytes (m_SessionKey, 32);
{ m_Encryption.SetKey (m_SessionKey);
if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT)
it = m_SessionTags.erase (it);
else
++it;
}
CleanupUnconfirmedTags ();
if (m_LeaseSetUpdateMsgID && ts*1000LL > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT)
{
if (m_Owner)
m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID);
m_LeaseSetUpdateMsgID = 0;
}
return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty ();
} }
bool GarlicRoutingSession::CleanupUnconfirmedTags () ElGamalAESSession::ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag)
{ {
bool ret = false; memcpy (m_SessionKey, sessionKey, 32);
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); m_Encryption.SetKey (m_SessionKey);
// delete expired unconfirmed tags m_SessionTags.push_back (sessionTag);
for (auto it = m_UnconfirmedTagsMsgs.begin (); it != m_UnconfirmedTagsMsgs.end ();) m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
{
if (ts >= it->second->tagsCreationTime + OUTGOING_TAGS_CONFIRMATION_TIMEOUT)
{
if (m_Owner)
m_Owner->RemoveDeliveryStatusSession (it->first);
it = m_UnconfirmedTagsMsgs.erase (it);
ret = true;
}
else
++it;
}
return ret;
} }
std::shared_ptr<I2NPMessage> GarlicRoutingSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{ {
auto m = NewI2NPMessage (); auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4) m->Align (12); // in order to get buf aligned to 16 (12 + 4)
@ -178,7 +107,7 @@ namespace garlic
if (!tagFound) // new session if (!tagFound) // new session
{ {
LogPrint (eLogInfo, "Garlic: No tags available, will use ElGamal"); LogPrint (eLogInfo, "Garlic: No tags available, will use ElGamal");
if (!m_Destination) if (!GetDestination ())
{ {
LogPrint (eLogError, "Garlic: Can't use ElGamal for unknown destination"); LogPrint (eLogError, "Garlic: Can't use ElGamal for unknown destination");
return nullptr; return nullptr;
@ -190,7 +119,7 @@ namespace garlic
uint8_t iv[32]; // IV is first 16 bytes uint8_t iv[32]; // IV is first 16 bytes
SHA256(elGamal.preIV, 32, iv); SHA256(elGamal.preIV, 32, iv);
BN_CTX * ctx = BN_CTX_new (); BN_CTX * ctx = BN_CTX_new ();
m_Destination->Encrypt ((uint8_t *)&elGamal, buf, ctx); GetDestination ()->Encrypt ((uint8_t *)&elGamal, buf, ctx);
BN_CTX_free (ctx); BN_CTX_free (ctx);
m_Encryption.SetIV (iv); m_Encryption.SetIV (iv);
buf += 514; buf += 514;
@ -214,10 +143,10 @@ namespace garlic
return m; return m;
} }
size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg) size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
{ {
size_t blockSize = 0; size_t blockSize = 0;
bool createNewTags = m_Owner && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3); bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3);
UnconfirmedTags * newTags = createNewTags ? GenerateSessionTags () : nullptr; UnconfirmedTags * newTags = createNewTags ? GenerateSessionTags () : nullptr;
htobuf16 (buf, newTags ? htobe16 (newTags->numTags) : 0); // tag count htobuf16 (buf, newTags ? htobe16 (newTags->numTags) : 0); // tag count
blockSize += 2; blockSize += 2;
@ -246,7 +175,7 @@ namespace garlic
return blockSize; return blockSize;
} }
size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags) size_t ElGamalAESSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags)
{ {
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
uint32_t msgID; uint32_t msgID;
@ -256,17 +185,17 @@ namespace garlic
*numCloves = 0; *numCloves = 0;
size++; size++;
if (m_Owner) if (GetOwner ())
{ {
// resubmit non-confirmed LeaseSet // resubmit non-confirmed LeaseSet
if (m_LeaseSetUpdateStatus == eLeaseSetSubmitted && ts > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT) if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
{ {
m_LeaseSetUpdateStatus = eLeaseSetUpdated; SetLeaseSetUpdateStatus (eLeaseSetUpdated);
SetSharedRoutingPath (nullptr); // invalidate path since leaseset was not confirmed SetSharedRoutingPath (nullptr); // invalidate path since leaseset was not confirmed
} }
// attach DeviveryStatus if necessary // attach DeviveryStatus if necessary
if (newTags || m_LeaseSetUpdateStatus == eLeaseSetUpdated) // new tags created or leaseset updated if (newTags || GetLeaseSetUpdateStatus () == eLeaseSetUpdated) // new tags created or leaseset updated
{ {
// clove is DeliveryStatus // clove is DeliveryStatus
auto cloveSize = CreateDeliveryStatusClove (payload + size, msgID); auto cloveSize = CreateDeliveryStatusClove (payload + size, msgID);
@ -280,27 +209,27 @@ namespace garlic
m_UnconfirmedTagsMsgs.insert (std::make_pair(msgID, std::unique_ptr<UnconfirmedTags>(newTags))); m_UnconfirmedTagsMsgs.insert (std::make_pair(msgID, std::unique_ptr<UnconfirmedTags>(newTags)));
newTags = nullptr; // got acquired newTags = nullptr; // got acquired
} }
m_Owner->DeliveryStatusSent (shared_from_this (), msgID); GetOwner ()->DeliveryStatusSent (shared_from_this (), msgID);
} }
else else
LogPrint (eLogWarning, "Garlic: DeliveryStatus clove was not created"); LogPrint (eLogWarning, "Garlic: DeliveryStatus clove was not created");
} }
// attach LeaseSet // attach LeaseSet
if (m_LeaseSetUpdateStatus == eLeaseSetUpdated) if (GetLeaseSetUpdateStatus () == eLeaseSetUpdated)
{ {
if (m_LeaseSetUpdateMsgID) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); // remove previous if (GetLeaseSetUpdateMsgID ()) GetOwner ()->RemoveDeliveryStatusSession (GetLeaseSetUpdateMsgID ()); // remove previous
m_LeaseSetUpdateStatus = eLeaseSetSubmitted; SetLeaseSetUpdateStatus (eLeaseSetSubmitted);
m_LeaseSetUpdateMsgID = msgID; SetLeaseSetUpdateMsgID (msgID);
m_LeaseSetSubmissionTime = ts; SetLeaseSetSubmissionTime (ts);
// clove if our leaseSet must be attached // clove if our leaseSet must be attached
auto leaseSet = CreateDatabaseStoreMsg (m_Owner->GetLeaseSet ()); auto leaseSet = CreateDatabaseStoreMsg (GetOwner ()->GetLeaseSet ());
size += CreateGarlicClove (payload + size, leaseSet, false); size += CreateGarlicClove (payload + size, leaseSet, false);
(*numCloves)++; (*numCloves)++;
} }
} }
if (msg) // clove message ifself if presented if (msg) // clove message ifself if presented
{ {
size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false); size += CreateGarlicClove (payload + size, msg, IsDestination ());
(*numCloves)++; (*numCloves)++;
} }
memset (payload + size, 0, 3); // certificate of message memset (payload + size, 0, 3); // certificate of message
@ -314,7 +243,7 @@ namespace garlic
return size; return size;
} }
size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination) size_t ElGamalAESSession::CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination)
{ {
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec
size_t size = 0; size_t size = 0;
@ -322,7 +251,7 @@ namespace garlic
{ {
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
size++; size++;
memcpy (buf + size, m_Destination->GetIdentHash (), 32); memcpy (buf + size, GetDestination ()->GetIdentHash (), 32);
size += 32; size += 32;
} }
else else
@ -344,12 +273,12 @@ namespace garlic
return size; return size;
} }
size_t GarlicRoutingSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID) size_t ElGamalAESSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID)
{ {
size_t size = 0; size_t size = 0;
if (m_Owner) if (GetOwner ())
{ {
auto inboundTunnel = m_Owner->GetTunnelPool ()->GetNextInboundTunnel (); auto inboundTunnel = GetOwner ()->GetTunnelPool ()->GetNextInboundTunnel ();
if (inboundTunnel) if (inboundTunnel)
{ {
buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel
@ -361,14 +290,14 @@ namespace garlic
size += 4; size += 4;
// create msg // create msg
auto msg = CreateDeliveryStatusMsg (msgID); auto msg = CreateDeliveryStatusMsg (msgID);
if (m_Owner) if (GetOwner ())
{ {
//encrypt //encrypt
uint8_t key[32], tag[32]; uint8_t key[32], tag[32];
RAND_bytes (key, 32); // random session key RAND_bytes (key, 32); // random session key
RAND_bytes (tag, 32); // random session tag RAND_bytes (tag, 32); // random session tag
m_Owner->SubmitSessionKey (key, tag); GetOwner ()->SubmitSessionKey (key, tag);
GarlicRoutingSession garlic (key, tag); ElGamalAESSession garlic (key, tag);
msg = garlic.WrapSingleMessage (msg); msg = garlic.WrapSingleMessage (msg);
} }
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
@ -393,6 +322,87 @@ namespace garlic
return size; return size;
} }
ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
{
auto tags = new UnconfirmedTags (m_NumTags);
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
for (int i = 0; i < m_NumTags; i++)
{
RAND_bytes (tags->sessionTags[i], 32);
tags->sessionTags[i].creationTime = tags->tagsCreationTime;
}
return tags;
}
void ElGamalAESSession::MessageConfirmed (uint32_t msgID)
{
TagsConfirmed (msgID);
if (msgID == GetLeaseSetUpdateMsgID ())
{
SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
SetLeaseSetUpdateMsgID (0);
LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed");
}
else
CleanupExpiredTags ();
}
void ElGamalAESSession::TagsConfirmed (uint32_t msgID)
{
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
auto it = m_UnconfirmedTagsMsgs.find (msgID);
if (it != m_UnconfirmedTagsMsgs.end ())
{
auto& tags = it->second;
if (ts < tags->tagsCreationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT)
{
for (int i = 0; i < tags->numTags; i++)
m_SessionTags.push_back (tags->sessionTags[i]);
}
m_UnconfirmedTagsMsgs.erase (it);
}
}
bool ElGamalAESSession::CleanupExpiredTags ()
{
auto ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it = m_SessionTags.begin (); it != m_SessionTags.end ();)
{
if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT)
it = m_SessionTags.erase (it);
else
++it;
}
CleanupUnconfirmedTags ();
if (GetLeaseSetUpdateMsgID () && ts*1000LL > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
{
if (GetOwner ())
GetOwner ()->RemoveDeliveryStatusSession (GetLeaseSetUpdateMsgID ());
SetLeaseSetUpdateMsgID (0);
}
return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty ();
}
bool ElGamalAESSession::CleanupUnconfirmedTags ()
{
bool ret = false;
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
// delete expired unconfirmed tags
for (auto it = m_UnconfirmedTagsMsgs.begin (); it != m_UnconfirmedTagsMsgs.end ();)
{
if (ts >= it->second->tagsCreationTime + OUTGOING_TAGS_CONFIRMATION_TIMEOUT)
{
if (GetOwner ())
GetOwner ()->RemoveDeliveryStatusSession (it->first);
it = m_UnconfirmedTagsMsgs.erase (it);
ret = true;
}
else
++it;
}
return ret;
}
GarlicDestination::GarlicDestination (): m_NumTags (32) // 32 tags by default GarlicDestination::GarlicDestination (): m_NumTags (32) // 32 tags by default
{ {
m_Ctx = BN_CTX_new (); m_Ctx = BN_CTX_new ();
@ -646,7 +656,7 @@ namespace garlic
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession ( std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet) std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
{ {
GarlicRoutingSessionPtr session; ElGamalAESSessionPtr session;
{ {
std::unique_lock<std::mutex> l(m_SessionsMutex); std::unique_lock<std::mutex> l(m_SessionsMutex);
auto it = m_Sessions.find (destination->GetIdentHash ()); auto it = m_Sessions.find (destination->GetIdentHash ());
@ -655,7 +665,7 @@ namespace garlic
} }
if (!session) if (!session)
{ {
session = std::make_shared<GarlicRoutingSession> (this, destination, session = std::make_shared<ElGamalAESSession> (this, destination,
attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
std::unique_lock<std::mutex> l(m_SessionsMutex); std::unique_lock<std::mutex> l(m_SessionsMutex);
m_Sessions[destination->GetIdentHash ()] = session; m_Sessions[destination->GetIdentHash ()] = session;
@ -716,7 +726,7 @@ namespace garlic
m_DeliveryStatusSessions.erase (msgID); m_DeliveryStatusSessions.erase (msgID);
} }
void GarlicDestination::DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID) void GarlicDestination::DeliveryStatusSent (ElGamalAESSessionPtr session, uint32_t msgID)
{ {
std::unique_lock<std::mutex> l(m_DeliveryStatusSessionsMutex); std::unique_lock<std::mutex> l(m_DeliveryStatusSessionsMutex);
m_DeliveryStatusSessions[msgID] = session; m_DeliveryStatusSessions[msgID] = session;
@ -724,7 +734,7 @@ namespace garlic
void GarlicDestination::HandleDeliveryStatusMessage (uint32_t msgID) void GarlicDestination::HandleDeliveryStatusMessage (uint32_t msgID)
{ {
GarlicRoutingSessionPtr session; ElGamalAESSessionPtr session;
{ {
std::unique_lock<std::mutex> l(m_DeliveryStatusSessionsMutex); std::unique_lock<std::mutex> l(m_DeliveryStatusSessionsMutex);
auto it = m_DeliveryStatusSessions.find (msgID); auto it = m_DeliveryStatusSessions.find (msgID);

111
libi2pd/Garlic.h

@ -85,8 +85,10 @@ namespace garlic
}; };
class GarlicDestination; class GarlicDestination;
class GarlicRoutingSession: public std::enable_shared_from_this<GarlicRoutingSession> class GarlicRoutingSession
{ {
protected:
enum LeaseSetUpdateStatus enum LeaseSetUpdateStatus
{ {
eLeaseSetUpToDate = 0, eLeaseSetUpToDate = 0,
@ -95,26 +97,13 @@ namespace garlic
eLeaseSetDoNotSend eLeaseSetDoNotSend
}; };
struct UnconfirmedTags
{
UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
~UnconfirmedTags () { delete[] sessionTags; };
uint32_t msgID;
int numTags;
SessionTag * sessionTags;
uint32_t tagsCreationTime;
};
public: public:
GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination, GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet);
int numTags, bool attachLeaseSet); GarlicRoutingSession ();
GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption virtual ~GarlicRoutingSession ();
~GarlicRoutingSession (); virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0;
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg); virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
void MessageConfirmed (uint32_t msgID);
bool CleanupExpiredTags (); // returns true if something left
bool CleanupUnconfirmedTags (); // returns true if something has been deleted
void SetLeaseSetUpdated () void SetLeaseSetUpdated ()
{ {
@ -127,44 +116,88 @@ namespace garlic
std::shared_ptr<GarlicRoutingPath> GetSharedRoutingPath (); std::shared_ptr<GarlicRoutingPath> GetSharedRoutingPath ();
void SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path); void SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path);
const GarlicDestination * GetOwner () const { return m_Owner; } GarlicDestination * GetOwner () const { return m_Owner; }
void SetOwner (GarlicDestination * owner) { m_Owner = owner; } void SetOwner (GarlicDestination * owner) { m_Owner = owner; }
private: protected:
size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg); LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags); void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
size_t CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination); uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
size_t CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID); void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
void TagsConfirmed (uint32_t msgID); void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
UnconfirmedTags * GenerateSessionTags (); bool IsDestination () const { return m_Destination ? m_Destination->IsDestination () : false; }
const std::shared_ptr<const i2p::data::RoutingDestination>& GetDestination () const { return m_Destination; }
private: private:
GarlicDestination * m_Owner; GarlicDestination * m_Owner;
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination; std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
i2p::crypto::AESKey m_SessionKey;
std::list<SessionTag> m_SessionTags;
int m_NumTags;
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
LeaseSetUpdateStatus m_LeaseSetUpdateStatus; LeaseSetUpdateStatus m_LeaseSetUpdateStatus;
uint32_t m_LeaseSetUpdateMsgID; uint32_t m_LeaseSetUpdateMsgID;
uint64_t m_LeaseSetSubmissionTime; // in milliseconds uint64_t m_LeaseSetSubmissionTime; // in milliseconds
i2p::crypto::CBCEncryption m_Encryption;
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath; std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
public: public:
// for HTTP only // for HTTP only
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; virtual size_t GetNumOutgoingTags () const { return 0; };
}; };
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>; //using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this<ElGamalAESSession>
{
struct UnconfirmedTags
{
UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
~UnconfirmedTags () { delete[] sessionTags; };
uint32_t msgID;
int numTags;
SessionTag * sessionTags;
uint32_t tagsCreationTime;
};
public:
ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
int numTags, bool attachLeaseSet);
ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption
~ElGamalAESSession () {};
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
void MessageConfirmed (uint32_t msgID);
bool CleanupExpiredTags (); // returns true if something left
bool CleanupUnconfirmedTags (); // returns true if something has been deleted
private:
size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg);
size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags);
size_t CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination);
size_t CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID);
void TagsConfirmed (uint32_t msgID);
UnconfirmedTags * GenerateSessionTags ();
private:
i2p::crypto::AESKey m_SessionKey;
std::list<SessionTag> m_SessionTags;
int m_NumTags;
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
i2p::crypto::CBCEncryption m_Encryption;
public:
// for HTTP only
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
};
typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr;
class GarlicDestination: public i2p::data::LocalDestination class GarlicDestination: public i2p::data::LocalDestination
{ {
public: public:
@ -182,7 +215,7 @@ namespace garlic
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); void DeliveryStatusSent (ElGamalAESSessionPtr session, uint32_t msgID);
virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg); virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
virtual void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg); virtual void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
@ -217,12 +250,12 @@ namespace garlic
// outgoing sessions // outgoing sessions
int m_NumTags; int m_NumTags;
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, GarlicRoutingSessionPtr> m_Sessions; std::map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
// incoming // incoming
std::map<SessionTag, std::shared_ptr<AESDecryption> > m_Tags; std::map<SessionTag, std::shared_ptr<AESDecryption> > m_Tags;
// DeliveryStatus // DeliveryStatus
std::mutex m_DeliveryStatusSessionsMutex; std::mutex m_DeliveryStatusSessionsMutex;
std::map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session std::map<uint32_t, ElGamalAESSessionPtr> m_DeliveryStatusSessions; // msgID -> session
public: public:

2
libi2pd/NetDb.cpp

@ -950,7 +950,7 @@ namespace data
if (numTags) if (numTags)
{ {
const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag
i2p::garlic::GarlicRoutingSession garlic (sessionKey, sessionTag); i2p::garlic::ElGamalAESSession garlic (sessionKey, sessionTag);
replyMsg = garlic.WrapSingleMessage (replyMsg); replyMsg = garlic.WrapSingleMessage (replyMsg);
if(replyMsg == nullptr) LogPrint(eLogError, "NetDb: failed to wrap message"); if(replyMsg == nullptr) LogPrint(eLogError, "NetDb: failed to wrap message");
} }

Loading…
Cancel
Save