diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 29171584..3a732876 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -137,6 +137,7 @@ namespace garlic } if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext) m_State = eSessionStateNewSessionReceived; + GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); HandlePayload (payload.data (), len - 16, handleClove); @@ -273,8 +274,52 @@ namespace garlic bool ECIESX25519AEADRatchetSession::NewOutgoingSessionReply (const uint8_t * buf, size_t len, CloveHandler handleClove) { - // TODO + // we are Alice LogPrint (eLogDebug, "Garlic: reply received"); + const uint8_t * tag = buf; + buf += 8; len -= 8; // tag + uint8_t bepk[32]; // Bob's ephemeral key + if (!i2p::crypto::GetElligator ()->Decode (buf, bepk)) + { + LogPrint (eLogError, "Garlic: Can't decode elligator"); + return false; + } + buf += 32; len -= 32; + // KDF for Reply Key Section + MixHash (tag, 8); // h = SHA256(h || tag) + MixHash (bepk, 32); // h = SHA256(h || bepk) + uint8_t sharedSecret[32]; + m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) + uint8_t nonce[12]; + memset (nonce, 0, 12); // n = 0 + // calulate hash for zero length + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anyting */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only + { + LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed"); + return false; + } + MixHash (buf, 16); // h = SHA256(h || ciphertext) + buf += 16; len -= 16; + // KDF for payload + 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_TagsetAB.DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) + m_TagsetBA.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) + i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) + // decrypt payload + std::vector payload (len - 16); + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, payload.data (), len - 16, false)) // decrypt + { + LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); + return false; + } + + // TODO: change state + GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); + HandlePayload (payload.data (), len - 16, handleClove); + return true; } diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 833817f7..b6a870f0 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -869,23 +869,14 @@ namespace garlic { // TODO auto session = it->second; - if (session->NewOutgoingSessionReply (buf, len, handleClove)) - m_ECIESx25519Sessions.emplace (session->GetRemoteStaticKey (), session); - else - { + if (!session->NewOutgoingSessionReply (buf, len, handleClove)) LogPrint (eLogError, "Garlic: can't decrypt ECIES-X25519-AEAD-Ratchet new session reply"); - m_ECIESx25519Tags.erase (tag); - m_ECIESx25519Sessions.erase (session->GetRemoteStaticKey ()); - } + m_ECIESx25519Tags.erase (tag); } else { auto session = std::make_shared (this); - if (session->NewIncomingSession (buf, len, handleClove)) - { - m_ECIESx25519Sessions.emplace (session->GetRemoteStaticKey (), session); - } - else + if (!session->NewIncomingSession (buf, len, handleClove)) LogPrint (eLogError, "Garlic: can't decrypt ECIES-X25519-AEAD-Ratchet new session"); } } @@ -950,5 +941,11 @@ namespace garlic { m_ECIESx25519Tags.emplace (tag, session); } + + void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session) + { + m_ECIESx25519Sessions.emplace (staticKey, session); + } + } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 08bbfc5b..4e66f75f 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -218,6 +218,7 @@ namespace garlic virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread void DeliveryStatusSent (ElGamalAESSessionPtr session, uint32_t msgID); void AddECIESx25519SessionTag (uint64_t tag, ECIESX25519AEADRatchetSessionPtr session); + void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); virtual void ProcessGarlicMessage (std::shared_ptr msg); virtual void ProcessDeliveryStatusMessage (std::shared_ptr msg);