Browse Source

don't allocate payload buffer for every single ECIESx25519 message

pull/1677/head
orignal 3 years ago
parent
commit
6ecfe0789f
  1. 79
      libi2pd/ECIESX25519AEADRatchetSession.cpp
  2. 2
      libi2pd/ECIESX25519AEADRatchetSession.h
  3. 11
      libi2pd/Garlic.cpp
  4. 2
      libi2pd/Garlic.h

79
libi2pd/ECIESX25519AEADRatchetSession.cpp

@ -795,8 +795,9 @@ namespace garlic
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{ {
auto payload = CreatePayload (msg, m_State != eSessionStateEstablished); uint8_t * payload = GetOwner ()->GetPayloadBuffer ();
size_t len = payload.size (); if (!payload) return nullptr;
size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload);
if (!len) return nullptr; if (!len) return nullptr;
auto m = NewI2NPMessage (len + 100); // 96 + 4 auto m = NewI2NPMessage (len + 100); // 96 + 4
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)
@ -805,27 +806,27 @@ namespace garlic
switch (m_State) switch (m_State)
{ {
case eSessionStateEstablished: case eSessionStateEstablished:
if (!NewExistingSessionMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NewExistingSessionMessage (payload, len, buf, m->maxLen))
return nullptr; return nullptr;
len += 24; len += 24;
break; break;
case eSessionStateNew: case eSessionStateNew:
if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen))
return nullptr; return nullptr;
len += 96; len += 96;
break; break;
case eSessionStateNewSessionReceived: case eSessionStateNewSessionReceived:
if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NewSessionReplyMessage (payload, len, buf, m->maxLen))
return nullptr; return nullptr;
len += 72; len += 72;
break; break;
case eSessionStateNewSessionReplySent: case eSessionStateNewSessionReplySent:
if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NextNewSessionReplyMessage (payload, len, buf, m->maxLen))
return nullptr; return nullptr;
len += 72; len += 72;
break; break;
case eSessionStateOneTime: case eSessionStateOneTime:
if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen, false)) if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false))
return nullptr; return nullptr;
len += 96; len += 96;
break; break;
@ -845,7 +846,7 @@ namespace garlic
return WrapSingleMessage (msg); return WrapSingleMessage (msg);
} }
std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first) size_t ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first, uint8_t * payload)
{ {
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
size_t payloadLen = 0; size_t payloadLen = 0;
@ -907,89 +908,93 @@ namespace garlic
payloadLen += paddingSize + 3; payloadLen += paddingSize + 3;
} }
} }
std::vector<uint8_t> v(payloadLen);
if (payloadLen) if (payloadLen)
{ {
if (payloadLen > I2NP_MAX_MESSAGE_SIZE)
{
LogPrint (eLogError, "Garlic: payload length ", payloadLen, " is too long");
return 0;
}
m_LastSentTimestamp = ts; m_LastSentTimestamp = ts;
size_t offset = 0; size_t offset = 0;
// DateTime // DateTime
if (first) if (first)
{ {
v[offset] = eECIESx25519BlkDateTime; offset++; payload[offset] = eECIESx25519BlkDateTime; offset++;
htobe16buf (v.data () + offset, 4); offset += 2; htobe16buf (payload + offset, 4); offset += 2;
htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds htobe32buf (payload + offset, ts/1000); offset += 4; // in seconds
} }
// LeaseSet // LeaseSet
if (leaseSet) if (leaseSet)
{ {
offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset); offset += CreateLeaseSetClove (leaseSet, ts, payload + offset, payloadLen - offset);
if (!first) if (!first)
{ {
// ack request // ack request
v[offset] = eECIESx25519BlkAckRequest; offset++; payload[offset] = eECIESx25519BlkAckRequest; offset++;
htobe16buf (v.data () + offset, 1); offset += 2; htobe16buf (payload + offset, 1); offset += 2;
v[offset] = 0; offset++; // flags payload[offset] = 0; offset++; // flags
} }
} }
// msg // msg
if (msg) if (msg)
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset); offset += CreateGarlicClove (msg, payload + offset, payloadLen - offset);
// ack // ack
if (m_AckRequests.size () > 0) if (m_AckRequests.size () > 0)
{ {
v[offset] = eECIESx25519BlkAck; offset++; payload[offset] = eECIESx25519BlkAck; offset++;
htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2; htobe16buf (payload + offset, m_AckRequests.size () * 4); offset += 2;
for (auto& it: m_AckRequests) for (auto& it: m_AckRequests)
{ {
htobe16buf (v.data () + offset, it.first); offset += 2; htobe16buf (payload + offset, it.first); offset += 2;
htobe16buf (v.data () + offset, it.second); offset += 2; htobe16buf (payload + offset, it.second); offset += 2;
} }
m_AckRequests.clear (); m_AckRequests.clear ();
} }
// next keys // next keys
if (m_SendReverseKey) if (m_SendReverseKey)
{ {
v[offset] = eECIESx25519BlkNextKey; offset++; payload[offset] = eECIESx25519BlkNextKey; offset++;
htobe16buf (v.data () + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2; htobe16buf (payload + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2;
v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG; payload[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG;
int keyID = m_NextReceiveRatchet->keyID - 1; int keyID = m_NextReceiveRatchet->keyID - 1;
if (m_NextReceiveRatchet->newKey) if (m_NextReceiveRatchet->newKey)
{ {
v[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG; payload[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG;
keyID++; keyID++;
} }
offset++; // flag offset++; // flag
htobe16buf (v.data () + offset, keyID); offset += 2; // keyid htobe16buf (payload + offset, keyID); offset += 2; // keyid
if (m_NextReceiveRatchet->newKey) if (m_NextReceiveRatchet->newKey)
{ {
memcpy (v.data () + offset, m_NextReceiveRatchet->key->GetPublicKey (), 32); memcpy (payload + offset, m_NextReceiveRatchet->key->GetPublicKey (), 32);
offset += 32; // public key offset += 32; // public key
} }
m_SendReverseKey = false; m_SendReverseKey = false;
} }
if (m_SendForwardKey) if (m_SendForwardKey)
{ {
v[offset] = eECIESx25519BlkNextKey; offset++; payload[offset] = eECIESx25519BlkNextKey; offset++;
htobe16buf (v.data () + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2; htobe16buf (payload + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2;
v[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; payload[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG;
if (!m_NextSendRatchet->keyID) v[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only if (!m_NextSendRatchet->keyID) payload[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only
offset++; // flag offset++; // flag
htobe16buf (v.data () + offset, m_NextSendRatchet->keyID); offset += 2; // keyid htobe16buf (payload + offset, m_NextSendRatchet->keyID); offset += 2; // keyid
if (m_NextSendRatchet->newKey) if (m_NextSendRatchet->newKey)
{ {
memcpy (v.data () + offset, m_NextSendRatchet->key->GetPublicKey (), 32); memcpy (payload + offset, m_NextSendRatchet->key->GetPublicKey (), 32);
offset += 32; // public key offset += 32; // public key
} }
} }
// padding // padding
if (paddingSize) if (paddingSize)
{ {
v[offset] = eECIESx25519BlkPadding; offset++; payload[offset] = eECIESx25519BlkPadding; offset++;
htobe16buf (v.data () + offset, paddingSize); offset += 2; htobe16buf (payload + offset, paddingSize); offset += 2;
memset (v.data () + offset, 0, paddingSize); offset += paddingSize; memset (payload + offset, 0, paddingSize); offset += paddingSize;
} }
} }
return v; return payloadLen;
} }
size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len) size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len)

2
libi2pd/ECIESX25519AEADRatchetSession.h

@ -208,7 +208,7 @@ namespace garlic
bool NextNewSessionReplyMessage (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, bool first); size_t CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first, uint8_t * payload);
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len); size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len); size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);

11
libi2pd/Garlic.cpp

@ -433,7 +433,7 @@ namespace garlic
} }
GarlicDestination::GarlicDestination (): m_NumTags (32), // 32 tags by default GarlicDestination::GarlicDestination (): m_NumTags (32), // 32 tags by default
m_NumRatchetInboundTags (0) // 0 means standard m_PayloadBuffer (nullptr), m_NumRatchetInboundTags (0) // 0 means standard
{ {
m_Ctx = BN_CTX_new (); m_Ctx = BN_CTX_new ();
} }
@ -441,6 +441,8 @@ namespace garlic
GarlicDestination::~GarlicDestination () GarlicDestination::~GarlicDestination ()
{ {
BN_CTX_free (m_Ctx); BN_CTX_free (m_Ctx);
if (m_PayloadBuffer)
delete[] m_PayloadBuffer;
} }
void GarlicDestination::CleanUp () void GarlicDestination::CleanUp ()
@ -1121,5 +1123,12 @@ namespace garlic
m_ECIESx25519Sessions.erase (it); m_ECIESx25519Sessions.erase (it);
} }
} }
uint8_t * GarlicDestination::GetPayloadBuffer ()
{
if (!m_PayloadBuffer)
m_PayloadBuffer = new uint8_t[I2NP_MAX_MESSAGE_SIZE];
return m_PayloadBuffer;
}
} }
} }

2
libi2pd/Garlic.h

@ -250,6 +250,7 @@ namespace garlic
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
void RemoveECIESx25519Session (const uint8_t * staticKey); void RemoveECIESx25519Session (const uint8_t * staticKey);
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
uint8_t * GetPayloadBuffer ();
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);
@ -284,6 +285,7 @@ namespace garlic
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions; std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
uint8_t * m_PayloadBuffer; // for ECIESX25519AEADRatchet
// incoming // incoming
int m_NumRatchetInboundTags; int m_NumRatchetInboundTags;
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags; std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;

Loading…
Cancel
Save