|
|
@ -15,8 +15,8 @@ namespace i2p |
|
|
|
namespace garlic |
|
|
|
namespace garlic |
|
|
|
{ |
|
|
|
{ |
|
|
|
GarlicRoutingSession::GarlicRoutingSession (const i2p::data::RoutingDestination * destination, int numTags): |
|
|
|
GarlicRoutingSession::GarlicRoutingSession (const i2p::data::RoutingDestination * destination, int numTags): |
|
|
|
m_Destination (destination), m_FirstMsgID (0), m_IsAcknowledged (false), |
|
|
|
m_Destination (destination), m_FirstMsgID (0), m_IsAcknowledged (false), m_NumTags (numTags), |
|
|
|
m_NumTags (numTags), m_NextTag (-1), m_SessionTags (0), m_TagsCreationTime (0) |
|
|
|
m_NextTag (-1), m_SessionTags (0), m_TagsCreationTime (0), m_LocalLeaseSet (nullptr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// create new session tags and session key
|
|
|
|
// create new session tags and session key
|
|
|
|
m_Rnd.GenerateBlock (m_SessionKey, 32); |
|
|
|
m_Rnd.GenerateBlock (m_SessionKey, 32); |
|
|
@ -31,7 +31,8 @@ namespace garlic |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): |
|
|
|
GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): |
|
|
|
m_Destination (nullptr), m_FirstMsgID (0), m_IsAcknowledged (true), m_NumTags (1), m_NextTag (0) |
|
|
|
m_Destination (nullptr), m_FirstMsgID (0), m_IsAcknowledged (true), m_NumTags (1), m_NextTag (0), |
|
|
|
|
|
|
|
m_LocalLeaseSet (nullptr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
memcpy (m_SessionKey, sessionKey, 32); |
|
|
|
memcpy (m_SessionKey, sessionKey, 32); |
|
|
|
m_Encryption.SetKey (m_SessionKey); |
|
|
|
m_Encryption.SetKey (m_SessionKey); |
|
|
@ -56,8 +57,9 @@ namespace garlic |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
I2NPMessage * GarlicRoutingSession::WrapSingleMessage (I2NPMessage * msg, I2NPMessage * leaseSet) |
|
|
|
I2NPMessage * GarlicRoutingSession::WrapSingleMessage (I2NPMessage * msg, const i2p::data::LeaseSet * leaseSet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
if (leaseSet) m_LocalLeaseSet = leaseSet; |
|
|
|
I2NPMessage * m = NewI2NPMessage (); |
|
|
|
I2NPMessage * m = NewI2NPMessage (); |
|
|
|
size_t len = 0; |
|
|
|
size_t len = 0; |
|
|
|
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
|
|
|
|
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
|
|
|
@ -122,12 +124,10 @@ namespace garlic |
|
|
|
FillI2NPMessageHeader (m, eI2NPGarlic); |
|
|
|
FillI2NPMessageHeader (m, eI2NPGarlic); |
|
|
|
if (msg) |
|
|
|
if (msg) |
|
|
|
DeleteI2NPMessage (msg); |
|
|
|
DeleteI2NPMessage (msg); |
|
|
|
if (leaseSet) |
|
|
|
|
|
|
|
DeleteI2NPMessage (leaseSet); |
|
|
|
|
|
|
|
return m; |
|
|
|
return m; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, const I2NPMessage * msg, const I2NPMessage * leaseSet) |
|
|
|
size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, const I2NPMessage * msg, bool attachLeaseSet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t blockSize = 0; |
|
|
|
size_t blockSize = 0; |
|
|
|
*(uint16_t *)buf = m_NextTag < 0 ? htobe16 (m_NumTags) : 0; // tag count
|
|
|
|
*(uint16_t *)buf = m_NextTag < 0 ? htobe16 (m_NumTags) : 0; // tag count
|
|
|
@ -146,7 +146,7 @@ namespace garlic |
|
|
|
blockSize += 32; |
|
|
|
blockSize += 32; |
|
|
|
buf[blockSize] = 0; // flag
|
|
|
|
buf[blockSize] = 0; // flag
|
|
|
|
blockSize++; |
|
|
|
blockSize++; |
|
|
|
size_t len = CreateGarlicPayload (buf + blockSize, msg, leaseSet); |
|
|
|
size_t len = CreateGarlicPayload (buf + blockSize, msg, attachLeaseSet); |
|
|
|
*payloadSize = htobe32 (len); |
|
|
|
*payloadSize = htobe32 (len); |
|
|
|
CryptoPP::SHA256().CalculateDigest(payloadHash, buf + blockSize, len); |
|
|
|
CryptoPP::SHA256().CalculateDigest(payloadHash, buf + blockSize, len); |
|
|
|
blockSize += len; |
|
|
|
blockSize += len; |
|
|
@ -157,7 +157,7 @@ namespace garlic |
|
|
|
return blockSize; |
|
|
|
return blockSize; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, const I2NPMessage * msg, const I2NPMessage * leaseSet) |
|
|
|
size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, const I2NPMessage * msg, bool attachLeaseSet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 5000; // 5 sec
|
|
|
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 5000; // 5 sec
|
|
|
|
uint32_t msgID = m_Rnd.GenerateWord32 (); |
|
|
|
uint32_t msgID = m_Rnd.GenerateWord32 (); |
|
|
@ -166,18 +166,28 @@ namespace garlic |
|
|
|
*numCloves = 0; |
|
|
|
*numCloves = 0; |
|
|
|
size++; |
|
|
|
size++; |
|
|
|
|
|
|
|
|
|
|
|
if (m_NextTag < 0) // new session
|
|
|
|
if (m_LocalLeaseSet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// clove is DeliveryStatus
|
|
|
|
if (m_NextTag < 0) // new session
|
|
|
|
size += CreateDeliveryStatusClove (payload + size, msgID); |
|
|
|
{ |
|
|
|
(*numCloves)++; |
|
|
|
// clove is DeliveryStatus
|
|
|
|
m_FirstMsgID = msgID; |
|
|
|
size += CreateDeliveryStatusClove (payload + size, msgID); |
|
|
|
} |
|
|
|
if (size > 0) // successive?
|
|
|
|
if (leaseSet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
(*numCloves)++; |
|
|
|
// clove is our leaseSet if presented
|
|
|
|
m_FirstMsgID = msgID; |
|
|
|
size += CreateGarlicClove (payload + size, leaseSet, false); |
|
|
|
} |
|
|
|
(*numCloves)++; |
|
|
|
else |
|
|
|
|
|
|
|
LogPrint ("DeliveryStatus clove was not created"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (attachLeaseSet) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// clove if our leaseSet must be attached
|
|
|
|
|
|
|
|
auto leaseSet = CreateDatabaseStoreMsg (m_LocalLeaseSet); |
|
|
|
|
|
|
|
size += CreateGarlicClove (payload + size, leaseSet, false); |
|
|
|
|
|
|
|
DeleteI2NPMessage (leaseSet); |
|
|
|
|
|
|
|
(*numCloves)++; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (msg) // clove message ifself if presented
|
|
|
|
if (msg) // clove message ifself if presented
|
|
|
|
{ |
|
|
|
{ |
|
|
@ -225,36 +235,38 @@ namespace garlic |
|
|
|
size_t GarlicRoutingSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID) |
|
|
|
size_t GarlicRoutingSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID) |
|
|
|
{ |
|
|
|
{ |
|
|
|
size_t size = 0; |
|
|
|
size_t size = 0; |
|
|
|
auto tunnel = i2p::tunnel::tunnels.GetNextInboundTunnel (); |
|
|
|
if (m_LocalLeaseSet) |
|
|
|
if (tunnel) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel
|
|
|
|
auto leases = m_LocalLeaseSet->GetNonExpiredLeases (); |
|
|
|
size++; |
|
|
|
if (!leases.empty ()) |
|
|
|
// hash and tunnelID sequence is reversed for Garlic
|
|
|
|
{ |
|
|
|
memcpy (buf + size, tunnel->GetNextIdentHash (), 32); // To Hash
|
|
|
|
buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel
|
|
|
|
size += 32; |
|
|
|
size++; |
|
|
|
*(uint32_t *)(buf + size) = htobe32 (tunnel->GetNextTunnelID ()); // tunnelID
|
|
|
|
uint32_t i = m_Rnd.GenerateWord32 (0, leases.size () - 1); |
|
|
|
size += 4; |
|
|
|
// hash and tunnelID sequence is reversed for Garlic
|
|
|
|
|
|
|
|
memcpy (buf + size, leases[i].tunnelGateway, 32); // To Hash
|
|
|
|
|
|
|
|
size += 32; |
|
|
|
|
|
|
|
*(uint32_t *)(buf + size) = htobe32 (leases[i].tunnelID); // tunnelID
|
|
|
|
|
|
|
|
size += 4; |
|
|
|
|
|
|
|
// create msg
|
|
|
|
|
|
|
|
I2NPMessage * msg = CreateDeliveryStatusMsg (msgID); |
|
|
|
|
|
|
|
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); |
|
|
|
|
|
|
|
size += msg->GetLength (); |
|
|
|
|
|
|
|
DeleteI2NPMessage (msg); |
|
|
|
|
|
|
|
// fill clove
|
|
|
|
|
|
|
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 5000; // 5 sec
|
|
|
|
|
|
|
|
*(uint32_t *)(buf + size) = htobe32 (m_Rnd.GenerateWord32 ()); // CloveID
|
|
|
|
|
|
|
|
size += 4; |
|
|
|
|
|
|
|
*(uint64_t *)(buf + size) = htobe64 (ts); // Expiration of clove
|
|
|
|
|
|
|
|
size += 8; |
|
|
|
|
|
|
|
memset (buf + size, 0, 3); // certificate of clove
|
|
|
|
|
|
|
|
size += 3; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
LogPrint ("All tunnels of local LeaseSet expired"); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
LogPrint ("Missing local LeaseSet"); |
|
|
|
LogPrint ("No reply tunnels for garlic DeliveryStatus found"); |
|
|
|
|
|
|
|
buf[size] = 0;// delivery instructions flag local
|
|
|
|
|
|
|
|
size++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
I2NPMessage * msg = CreateDeliveryStatusMsg (msgID); |
|
|
|
|
|
|
|
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); |
|
|
|
|
|
|
|
size += msg->GetLength (); |
|
|
|
|
|
|
|
DeleteI2NPMessage (msg); |
|
|
|
|
|
|
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 5000; // 5 sec
|
|
|
|
|
|
|
|
*(uint32_t *)(buf + size) = htobe32 (m_Rnd.GenerateWord32 ()); // CloveID
|
|
|
|
|
|
|
|
size += 4; |
|
|
|
|
|
|
|
*(uint64_t *)(buf + size) = htobe64 (ts); // Expiration of clove
|
|
|
|
|
|
|
|
size += 8; |
|
|
|
|
|
|
|
memset (buf + size, 0, 3); // certificate of clove
|
|
|
|
|
|
|
|
size += 3; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return size; |
|
|
|
return size; |
|
|
|
} |
|
|
|
} |
|
|
@ -296,7 +308,7 @@ namespace garlic |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
I2NPMessage * GarlicRouting::WrapMessage (const i2p::data::RoutingDestination& destination, |
|
|
|
I2NPMessage * GarlicRouting::WrapMessage (const i2p::data::RoutingDestination& destination, |
|
|
|
I2NPMessage * msg, I2NPMessage * leaseSet) |
|
|
|
I2NPMessage * msg, const i2p::data::LeaseSet * leaseSet) |
|
|
|
{ |
|
|
|
{ |
|
|
|
auto it = m_Sessions.find (destination.GetIdentHash ()); |
|
|
|
auto it = m_Sessions.find (destination.GetIdentHash ()); |
|
|
|
GarlicRoutingSession * session = nullptr; |
|
|
|
GarlicRoutingSession * session = nullptr; |
|
|
|