From ec29597dbdb06d962b9aecd2580b639976100a25 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Apr 2020 15:46:02 -0400 Subject: [PATCH] associate tagset for ECIESx25519 tags --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 52 +++++++++++------------ libi2pd/ECIESX25519AEADRatchetSession.h | 14 ++++-- libi2pd/Garlic.cpp | 9 ++-- libi2pd/Garlic.h | 12 +++--- 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 989588f7..954df461 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -120,15 +120,15 @@ namespace garlic return false; } - uint64_t ECIESX25519AEADRatchetSession::CreateNewSessionTag () const + 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 - RatchetTagSet tagsetNsr; - tagsetNsr.DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) - tagsetNsr.NextSessionTagRatchet (); - return tagsetNsr.GetNextSessionTag (); + auto tagsetNsr = std::make_shared(shared_from_this ()); + tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) + tagsetNsr->NextSessionTagRatchet (); + return tagsetNsr; } bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len) @@ -283,7 +283,7 @@ namespace garlic m_State = eSessionStateNewSessionSent; if (GetOwner ()) - GetOwner ()->AddECIESx25519SessionTag (0, CreateNewSessionTag (), shared_from_this ()); + GetOwner ()->AddECIESx25519SessionNextTag (CreateNewSessionTagset ()); return true; } @@ -291,7 +291,7 @@ namespace garlic bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { // we are Bob - uint64_t tag = CreateNewSessionTag (); + uint64_t tag = CreateNewSessionTagset ()->GetNextSessionTag (); size_t offset = 0; memcpy (out + offset, &tag, 8); @@ -325,10 +325,12 @@ 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] - m_ReceiveTagset.DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) - m_ReceiveTagset.NextSessionTagRatchet (); - m_SendTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) - m_SendTagset.NextSessionTagRatchet (); + m_ReceiveTagset = std::make_shared(shared_from_this ()); + m_ReceiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) + m_ReceiveTagset->NextSessionTagRatchet (); + m_SendTagset = std::make_shared(shared_from_this ()); + m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) + m_SendTagset->NextSessionTagRatchet (); GenerateMoreReceiveTags (GetOwner ()->GetNumTags ()); i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) // encrypt payload @@ -392,10 +394,12 @@ 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] - m_SendTagset.DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) - m_SendTagset.NextSessionTagRatchet (); - m_ReceiveTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) - m_ReceiveTagset.NextSessionTagRatchet (); + m_SendTagset = std::make_shared(shared_from_this ()); + m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) + m_SendTagset->NextSessionTagRatchet (); + m_ReceiveTagset = std::make_shared(shared_from_this ()); + m_ReceiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) + m_ReceiveTagset->NextSessionTagRatchet (); GenerateMoreReceiveTags (GetOwner ()->GetNumTags ()); i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) // decrypt payload @@ -420,14 +424,14 @@ namespace garlic bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { uint8_t nonce[12]; - auto index = m_SendTagset.GetNextIndex (); + auto index = m_SendTagset->GetNextIndex (); CreateNonce (index, nonce); // tag's index - uint64_t tag = m_SendTagset.GetNextSessionTag (); + uint64_t tag = m_SendTagset->GetNextSessionTag (); memcpy (out, &tag, 8); // ad = The session tag, 8 bytes // ciphertext = ENCRYPT(k, n, payload, ad) uint8_t key[32]; - m_SendTagset.GetSymmKey (index, key); + m_SendTagset->GetSymmKey (index, key); if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, out, 8, key, nonce, out + 8, outLen - 8, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); @@ -443,14 +447,14 @@ namespace garlic len -= 8; // tag std::vector payload (len - 16); uint8_t key[32]; - m_ReceiveTagset.GetSymmKey (index, key); + m_ReceiveTagset->GetSymmKey (index, key); if (!i2p::crypto::AEADChaCha20Poly1305 (buf + 8, len - 16, buf, 8, key, nonce, payload.data (), len - 16, false)) // decrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); return false; } HandlePayload (payload.data (), len - 16, index); - if (m_ReceiveTagset.GetNextIndex () - index <= GetOwner ()->GetNumTags ()*2/3) + if (m_ReceiveTagset->GetNextIndex () - index <= GetOwner ()->GetNumTags ()*2/3) GenerateMoreReceiveTags (GetOwner ()->GetNumTags ()); return true; } @@ -532,7 +536,7 @@ namespace garlic { // ack request SetLeaseSetUpdateStatus (eLeaseSetSubmitted); - SetLeaseSetUpdateMsgID (m_SendTagset.GetNextIndex ()); + SetLeaseSetUpdateMsgID (m_SendTagset->GetNextIndex ()); SetLeaseSetSubmissionTime (ts); payloadLen += 4; } @@ -646,11 +650,7 @@ namespace garlic void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (int numTags) { for (int i = 0; i < numTags; i++) - { - auto index = m_ReceiveTagset.GetNextIndex (); - uint64_t tag = m_ReceiveTagset.GetNextSessionTag (); - GetOwner ()->AddECIESx25519SessionTag (index, tag, shared_from_this ()); - } + GetOwner ()->AddECIESx25519SessionNextTag (m_ReceiveTagset); } bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 129dbbed..3798d34b 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -17,16 +17,21 @@ namespace i2p { namespace garlic { + class ECIESX25519AEADRatchetSession; class RatchetTagSet { public: - + + RatchetTagSet (std::shared_ptr session): m_Session (session) {}; + void DHInitialize (const uint8_t * rootKey, const uint8_t * k); void NextSessionTagRatchet (); uint64_t GetNextSessionTag (); int GetNextIndex () const { return m_NextIndex; }; void GetSymmKey (int index, uint8_t * key); - + + std::shared_ptr GetSession () { return m_Session.lock (); }; + private: union @@ -42,6 +47,7 @@ namespace garlic uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64]; int m_NextIndex, m_NextSymmKeyIndex; std::unordered_map > m_ItermediateSymmKeys; + std::weak_ptr m_Session; }; enum ECIESx25519BlockType @@ -97,7 +103,7 @@ namespace garlic void MixHash (const uint8_t * buf, size_t len); void CreateNonce (uint64_t seqn, uint8_t * nonce); bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes - uint64_t CreateNewSessionTag () const; + std::shared_ptr CreateNewSessionTagset (); bool HandleNewIncomingSession (const uint8_t * buf, size_t len); bool HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len); @@ -123,7 +129,7 @@ namespace garlic i2p::crypto::X25519Keys m_EphemeralKeys; SessionState m_State = eSessionStateNew; uint64_t m_LastActivityTimestamp = 0; // incoming - RatchetTagSet m_SendTagset, m_ReceiveTagset; + std::shared_ptr m_SendTagset, m_ReceiveTagset; std::unique_ptr m_Destination;// TODO: might not need it std::list > m_AckRequests; // (tagsetid, index) }; diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 393148e4..d10c48cb 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -498,7 +498,8 @@ namespace garlic if (it1 != m_ECIESx25519Tags.end ()) { found = true; - if (!it1->second.session->HandleNextMessage (buf, length, it1->second.index)) + auto session = it1->second.tagset->GetSession (); + if (!session || !session->HandleNextMessage (buf, length, it1->second.index)) LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); m_ECIESx25519Tags.erase (it1); } @@ -988,9 +989,11 @@ namespace garlic } } - void GarlicDestination::AddECIESx25519SessionTag (int index, uint64_t tag, ECIESX25519AEADRatchetSessionPtr session) + void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset) { - m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexSession{index, session, i2p::util::GetSecondsSinceEpoch ()}); + auto index = tagset->GetNextIndex (); + uint64_t tag = tagset->GetNextSessionTag (); + m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()}); } void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session) diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index ebcb70a4..ffb66245 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -201,11 +201,13 @@ namespace garlic typedef std::shared_ptr ElGamalAESSessionPtr; class ECIESX25519AEADRatchetSession; - typedef std::shared_ptr ECIESX25519AEADRatchetSessionPtr; - struct ECIESX25519AEADRatchetIndexSession + typedef std::shared_ptr ECIESX25519AEADRatchetSessionPtr; + class RatchetTagSet; + typedef std::shared_ptr RatchetTagSetPtr; + struct ECIESX25519AEADRatchetIndexTagset { int index; - ECIESX25519AEADRatchetSessionPtr session; + RatchetTagSetPtr tagset; uint64_t creationTime; // seconds since epoch }; @@ -228,7 +230,7 @@ namespace garlic 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 void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); - void AddECIESx25519SessionTag (int index, uint64_t tag, ECIESX25519AEADRatchetSessionPtr session); + void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); @@ -265,7 +267,7 @@ namespace garlic std::unordered_map, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session // incoming std::unordered_map, std::hash > > m_Tags; - std::unordered_map m_ECIESx25519Tags; // session tag -> session + std::unordered_map m_ECIESx25519Tags; // session tag -> session // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::unordered_map m_DeliveryStatusSessions; // msgID -> session