diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index cbf5175a..2a0f5cb4 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -100,7 +100,7 @@ namespace garlic m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT; } - bool RatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index) + bool ReceiveRatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index) { auto session = GetSession (); if (!session) return false; @@ -108,7 +108,7 @@ namespace garlic } DatabaseLookupTagSet::DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key): - RatchetTagSet (nullptr), m_Destination (destination) + ReceiveRatchetTagSet (nullptr), m_Destination (destination) { memcpy (m_Key, key, 32); Expire (); @@ -203,12 +203,12 @@ namespace garlic return false; } - std::shared_ptr ECIESX25519AEADRatchetSession::CreateNewSessionTagset () + std::shared_ptr ECIESX25519AEADRatchetSession::CreateNewSessionTagset () { uint8_t tagsetKey[32]; i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32) // Session Tag Ratchet - auto tagsetNsr = (m_State == eSessionStateNewSessionReceived) ? std::make_shared(shared_from_this ()): + auto tagsetNsr = (m_State == eSessionStateNewSessionReceived) ? std::make_shared(shared_from_this ()): std::make_shared(shared_from_this ()); tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) tagsetNsr->NextSessionTagRatchet (); @@ -284,7 +284,7 @@ namespace garlic return true; } - void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index) + void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index) { size_t offset = 0; while (offset < len) @@ -352,7 +352,7 @@ namespace garlic } } - void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset) + void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset) { uint8_t flag = buf[0]; buf++; // flag if (flag & ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG) @@ -367,7 +367,7 @@ namespace garlic uint8_t sharedSecret[32], tagsetKey[32]; m_NextSendRatchet->key->Agree (m_NextSendRatchet->remote, sharedSecret); i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32) - auto newTagset = std::make_shared (shared_from_this ()); + auto newTagset = std::make_shared (); newTagset->SetTagSetID (1 + m_NextSendRatchet->keyID + keyID); newTagset->DHInitialize (m_SendTagset->GetNextRootKey (), tagsetKey); newTagset->NextSessionTagRatchet (); @@ -409,7 +409,7 @@ namespace garlic uint8_t sharedSecret[32], tagsetKey[32]; m_NextReceiveRatchet->key->Agree (m_NextReceiveRatchet->remote, sharedSecret); i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32) - auto newTagset = std::make_shared(shared_from_this ()); + auto newTagset = std::make_shared(shared_from_this ()); newTagset->SetTagSetID (tagsetID); newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey); newTagset->NextSessionTagRatchet (); @@ -582,10 +582,10 @@ namespace garlic uint8_t keydata[64]; i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) // k_ab = keydata[0:31], k_ba = keydata[32:63] - auto receiveTagset = std::make_shared(shared_from_this ()); + auto receiveTagset = std::make_shared(shared_from_this()); receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) receiveTagset->NextSessionTagRatchet (); - m_SendTagset = std::make_shared(shared_from_this ()); + m_SendTagset = std::make_shared(); m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) m_SendTagset->NextSessionTagRatchet (); GenerateMoreReceiveTags (receiveTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ? @@ -674,10 +674,10 @@ namespace garlic { // only first time, then we keep using existing tagsets // k_ab = keydata[0:31], k_ba = keydata[32:63] - m_SendTagset = std::make_shared(shared_from_this ()); + m_SendTagset = std::make_shared(); m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) m_SendTagset->NextSessionTagRatchet (); - auto receiveTagset = std::make_shared(shared_from_this ()); + auto receiveTagset = std::make_shared(shared_from_this ()); receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) receiveTagset->NextSessionTagRatchet (); GenerateMoreReceiveTags (receiveTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ? @@ -736,7 +736,7 @@ namespace garlic } bool ECIESX25519AEADRatchetSession::HandleExistingSessionMessage (uint8_t * buf, size_t len, - std::shared_ptr receiveTagset, int index) + std::shared_ptr receiveTagset, int index) { uint8_t nonce[12]; CreateNonce (index, nonce); // tag's index @@ -775,7 +775,7 @@ namespace garlic } bool ECIESX25519AEADRatchetSession::HandleNextMessage (uint8_t * buf, size_t len, - std::shared_ptr receiveTagset, int index) + std::shared_ptr receiveTagset, int index) { m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); switch (m_State) @@ -1086,7 +1086,7 @@ namespace garlic return cloveSize + 3; } - void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags) + void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags) { if (GetOwner ()) { diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 86e3ffc0..0cc7935e 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -39,12 +39,13 @@ namespace garlic const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */ // - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */ - class ECIESX25519AEADRatchetSession; - class RatchetTagSet: public std::enable_shared_from_this + class RatchetTagSet { public: - RatchetTagSet (std::shared_ptr session): m_Session (session) {}; + RatchetTagSet () {}; + virtual ~RatchetTagSet () {}; + virtual bool IsNS () const { return false; }; void DHInitialize (const uint8_t * rootKey, const uint8_t * k); @@ -55,16 +56,12 @@ namespace garlic void GetSymmKey (int index, uint8_t * key); void DeleteSymmKey (int index); - std::shared_ptr GetSession () { return m_Session.lock (); }; int GetTagSetID () const { return m_TagSetID; }; void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; }; - void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; }; - + void Expire (); bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; }; - virtual bool IsIndexExpired (int index) const { return m_Session.expired () || index < m_TrimBehindIndex; }; - - virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index); + private: @@ -79,19 +76,39 @@ namespace garlic } m_KeyData; uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32]; - int m_NextIndex, m_NextSymmKeyIndex, m_TrimBehindIndex = 0; + int m_NextIndex, m_NextSymmKeyIndex; std::unordered_map > m_ItermediateSymmKeys; - std::weak_ptr m_Session; + int m_TagSetID = 0; uint64_t m_ExpirationTimestamp = 0; }; - class NSRatchetTagSet: public RatchetTagSet + class ECIESX25519AEADRatchetSession; + class ReceiveRatchetTagSet: public RatchetTagSet, + public std::enable_shared_from_this + { + public: + + ReceiveRatchetTagSet (std::shared_ptr session): m_Session (session) {}; + + std::shared_ptr GetSession () { return m_Session.lock (); }; + void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; }; + + virtual bool IsIndexExpired (int index) const { return m_Session.expired () || index < m_TrimBehindIndex; }; + virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index); + + private: + + int m_TrimBehindIndex = 0; + std::weak_ptr m_Session; + }; + + class NSRatchetTagSet: public ReceiveRatchetTagSet { public: NSRatchetTagSet (std::shared_ptr session): - RatchetTagSet (session), m_DummySession (session) {}; + ReceiveRatchetTagSet (session), m_DummySession (session) {}; bool IsNS () const { return true; }; @@ -100,7 +117,7 @@ namespace garlic std::shared_ptr m_DummySession; // we need a strong pointer for NS }; - class DatabaseLookupTagSet: public RatchetTagSet + class DatabaseLookupTagSet: public ReceiveRatchetTagSet { public: @@ -160,7 +177,7 @@ namespace garlic ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet); ~ECIESX25519AEADRatchetSession (); - bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index = 0); + bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index = 0); bool HandleNextMessageForRouter (const uint8_t * buf, size_t len); std::shared_ptr WrapSingleMessage (std::shared_ptr msg); std::shared_ptr WrapOneTimeMessage (std::shared_ptr msg, bool isForRouter = false); @@ -185,13 +202,13 @@ namespace garlic void CreateNonce (uint64_t seqn, uint8_t * nonce); bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes - std::shared_ptr CreateNewSessionTagset (); + std::shared_ptr CreateNewSessionTagset (); bool HandleNewIncomingSession (const uint8_t * buf, size_t len); bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len); - bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index); - void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index); - void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset); + bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index); + void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index); + void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset); bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic = true); bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); @@ -203,7 +220,7 @@ namespace garlic size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len); size_t CreateLeaseSetClove (std::shared_ptr ls, uint64_t ts, uint8_t * buf, size_t len); - void GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags); + void GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags); void NewNextSendRatchet (); private: diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 6f9a37b9..17406b4f 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1060,7 +1060,7 @@ namespace garlic } } - uint64_t GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset) + uint64_t GarlicDestination::AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset) { auto index = tagset->GetNextIndex (); uint64_t tag = tagset->GetNextSessionTag (); diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 379477e8..a8806921 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -215,12 +215,12 @@ namespace garlic class ECIESX25519AEADRatchetSession; typedef std::shared_ptr ECIESX25519AEADRatchetSessionPtr; - class RatchetTagSet; - typedef std::shared_ptr RatchetTagSetPtr; + class ReceiveRatchetTagSet; + typedef std::shared_ptr ReceiveRatchetTagSetPtr; struct ECIESX25519AEADRatchetIndexTagset { int index; - RatchetTagSetPtr tagset; + ReceiveRatchetTagSetPtr tagset; }; class GarlicDestination: public i2p::data::LocalDestination @@ -245,7 +245,7 @@ namespace garlic void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); - uint64_t AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset); + uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void RemoveECIESx25519Session (const uint8_t * staticKey); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); @@ -285,7 +285,7 @@ namespace garlic int m_NumRatchetInboundTags; std::unordered_map, std::hash > > m_Tags; std::unordered_map m_ECIESx25519Tags; // session tag -> session - RatchetTagSetPtr m_LastTagset; // tagset last message came for + ReceiveRatchetTagSetPtr m_LastTagset; // tagset last message came for // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::unordered_map m_DeliveryStatusSessions; // msgID -> session