mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-27 21:34:17 +00:00
GarlicRoutingSession/ElGamalAESSession split
This commit is contained in:
parent
bcfe44db54
commit
d7d964bf57
@ -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):
|
||||||
|
GarlicRoutingSession (owner, destination, attachLeaseSet), m_NumTags (numTags)
|
||||||
{
|
{
|
||||||
auto tags = new UnconfirmedTags (m_NumTags);
|
// create new session tags and session key
|
||||||
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
|
RAND_bytes (m_SessionKey, 32);
|
||||||
for (int i = 0; i < m_NumTags; i++)
|
m_Encryption.SetKey (m_SessionKey);
|
||||||
{
|
|
||||||
RAND_bytes (tags->sessionTags[i], 32);
|
|
||||||
tags->sessionTags[i].creationTime = tags->tagsCreationTime;
|
|
||||||
}
|
|
||||||
return tags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicRoutingSession::MessageConfirmed (uint32_t msgID)
|
ElGamalAESSession::ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag)
|
||||||
{
|
{
|
||||||
TagsConfirmed (msgID);
|
memcpy (m_SessionKey, sessionKey, 32);
|
||||||
if (msgID == m_LeaseSetUpdateMsgID)
|
m_Encryption.SetKey (m_SessionKey);
|
||||||
{
|
m_SessionTags.push_back (sessionTag);
|
||||||
m_LeaseSetUpdateStatus = eLeaseSetUpToDate;
|
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
m_LeaseSetUpdateMsgID = 0;
|
|
||||||
LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
CleanupExpiredTags ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicRoutingSession::TagsConfirmed (uint32_t msgID)
|
std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
||||||
{
|
|
||||||
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 ();
|
|
||||||
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 (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 ()
|
|
||||||
{
|
|
||||||
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 (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)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
115
libi2pd/Garlic.h
115
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,11 +116,65 @@ 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; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
|
||||||
|
void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
|
||||||
|
uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
|
||||||
|
void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
|
||||||
|
|
||||||
|
void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
|
||||||
|
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;
|
||||||
|
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
|
||||||
|
|
||||||
|
LeaseSetUpdateStatus m_LeaseSetUpdateStatus;
|
||||||
|
uint32_t m_LeaseSetUpdateMsgID;
|
||||||
|
uint64_t m_LeaseSetSubmissionTime; // in milliseconds
|
||||||
|
|
||||||
|
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// for HTTP only
|
||||||
|
virtual size_t GetNumOutgoingTags () const { return 0; };
|
||||||
|
};
|
||||||
|
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
|
||||||
|
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 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 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 CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination);
|
||||||
@ -139,31 +182,21 @@ namespace garlic
|
|||||||
|
|
||||||
void TagsConfirmed (uint32_t msgID);
|
void TagsConfirmed (uint32_t msgID);
|
||||||
UnconfirmedTags * GenerateSessionTags ();
|
UnconfirmedTags * GenerateSessionTags ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
private:
|
i2p::crypto::AESKey m_SessionKey;
|
||||||
|
|
||||||
GarlicDestination * m_Owner;
|
|
||||||
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
|
|
||||||
|
|
||||||
i2p::crypto::AESKey m_SessionKey;
|
|
||||||
std::list<SessionTag> m_SessionTags;
|
std::list<SessionTag> m_SessionTags;
|
||||||
int m_NumTags;
|
int m_NumTags;
|
||||||
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
|
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
|
||||||
|
|
||||||
LeaseSetUpdateStatus m_LeaseSetUpdateStatus;
|
i2p::crypto::CBCEncryption m_Encryption;
|
||||||
uint32_t m_LeaseSetUpdateMsgID;
|
|
||||||
uint64_t m_LeaseSetSubmissionTime; // in milliseconds
|
|
||||||
|
|
||||||
i2p::crypto::CBCEncryption m_Encryption;
|
public:
|
||||||
|
|
||||||
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
|
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
|
||||||
};
|
};
|
||||||
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
|
typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr;
|
||||||
typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
|
|
||||||
|
|
||||||
class GarlicDestination: public i2p::data::LocalDestination
|
class GarlicDestination: public i2p::data::LocalDestination
|
||||||
{
|
{
|
||||||
@ -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:
|
||||||
|
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user