|
|
@ -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 (); |
|
|
|
|
|
|
|
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) |
|
|
|
// create new session tags and session key
|
|
|
|
m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); |
|
|
|
RAND_bytes (m_SessionKey, 32); |
|
|
|
m_LeaseSetUpdateMsgID = 0; |
|
|
|
m_Encryption.SetKey (m_SessionKey); |
|
|
|
} |
|
|
|
|
|
|
|
return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool GarlicRoutingSession::CleanupUnconfirmedTags () |
|
|
|
ElGamalAESSession::ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag) |
|
|
|
{ |
|
|
|
|
|
|
|
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) |
|
|
|
memcpy (m_SessionKey, sessionKey, 32); |
|
|
|
m_Owner->RemoveDeliveryStatusSession (it->first); |
|
|
|
m_Encryption.SetKey (m_SessionKey); |
|
|
|
it = m_UnconfirmedTagsMsgs.erase (it); |
|
|
|
m_SessionTags.push_back (sessionTag); |
|
|
|
ret = true; |
|
|
|
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch (); |
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
|