From 451c3945f051a843c56a326891c053f826a30d53 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Jan 2020 19:33:00 -0500 Subject: [PATCH] create new ECIESX25519AEADRatchet session if not found --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 44 ++++++++++++----------- libi2pd/ECIESX25519AEADRatchetSession.h | 6 ++-- libi2pd/Garlic.cpp | 9 +++-- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 22458a5e..ff40bef1 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -35,7 +35,7 @@ namespace garlic SHA256_Update (&ctx, buf, len); SHA256_Final (m_H, &ctx); } - + bool ECIESX25519AEADRatchetSession::NewIncomingSession (const uint8_t * buf, size_t len, CloveHandler handleClove) { if (!GetOwner ()) return false; @@ -52,15 +52,14 @@ namespace garlic buf += 32; len -= 32; MixHash (aepk, 32); // h = SHA256(h || aepk) - uint8_t sharedSecret[32], keyData[64]; + uint8_t sharedSecret[32]; GetOwner ()->Decrypt (aepk, sharedSecret, nullptr); // x25519(bsk, aepk) - i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) - memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31] - + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) + // decrypt flags/static uint8_t nonce[12], fs[32]; memset (nonce, 0, 12); // n = 0 - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, keyData + 32, nonce, fs, 32, false)) // decrypt + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt { LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); return false; @@ -75,14 +74,13 @@ namespace garlic if (isStatic) { // static key, fs is apk - memcpy (m_StaticKey, fs, 32); + memcpy (m_RemoteStaticKey, fs, 32); GetOwner ()->Decrypt (fs, sharedSecret, nullptr); // x25519(bsk, apk) - i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) - memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31] + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) } else // all zeros flags htole64buf (nonce + 4, 1); // n = 1 - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keyData + 32, nonce, payload.data (), len - 16, false)) // decrypt + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); return false; @@ -132,7 +130,7 @@ namespace garlic bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) { - // we are Alice, bpk is m_StaticKey + // we are Alice, bpk is m_RemoteStaticKey size_t offset = 0; if (!i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), out + offset)) { @@ -142,26 +140,32 @@ namespace garlic offset += 32; // KDF1 - MixHash (m_StaticKey, 32); // h = SHA256(h || bpk) + MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk) MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk) - uint8_t sharedSecret[32], keyData[64]; - m_EphemeralKeys.Agree (m_StaticKey, nullptr); // x25519(aesk, bpk) - i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) - memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31] + uint8_t sharedSecret[32]; + m_EphemeralKeys.Agree (m_RemoteStaticKey, nullptr); // x25519(aesk, bpk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) // encrypt static key section uint8_t nonce[12]; memset (nonce, 0, 12); // n = 0 - if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (), 32, m_H, 32, keyData + 32, nonce, out + offset, 48, true)) // encrypt + if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed "); return false; } MixHash (out + offset, 48); // h = SHA256(h || ciphertext) offset += 48; - // KDF2 - // TODO: // x25519 (ask, bpk) - + GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr); // x25519 (ask, bpk) + i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) + // encrypt payload + if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt + { + LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); + return false; + } + MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext) + return true; } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 8cfd18b9..fd0658a5 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -1,6 +1,7 @@ #ifndef ECIES_X25519_AEAD_RATCHET_SESSION_H__ #define ECIES_X25519_AEAD_RATCHET_SESSION_H__ +#include #include #include #include "Identity.h" @@ -34,7 +35,8 @@ namespace garlic std::shared_ptr WrapSingleMessage (std::shared_ptr msg); bool NewIncomingSession (const uint8_t * buf, size_t len, CloveHandler handleClove); - const uint8_t * GetStaticKey () const { return m_StaticKey; }; + const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } + void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); } private: @@ -46,7 +48,7 @@ namespace garlic private: - uint8_t m_H[32], m_CK[32], m_StaticKey[32]; + uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32]; i2p::crypto::X25519Keys m_EphemeralKeys; }; } diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index a4cbeb01..fc8a4f01 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -664,7 +664,12 @@ namespace garlic auto it = m_ECIESx25519Sessions.find (staticKey); if (it != m_ECIESx25519Sessions.end ()) session = it->second; - // TODO: Alice + if (!session) + { + session = std::make_shared (this); + session->SetRemoteStaticKey (staticKey); + m_ECIESx25519Sessions.emplace (staticKey, session); + } return session; } else @@ -860,7 +865,7 @@ namespace garlic if (session->NewIncomingSession (buf, len, std::bind (&GarlicDestination::HandleECIESx25519GarlicClove, this, std::placeholders::_1, std::placeholders::_2))) { - m_ECIESx25519Sessions.emplace (session->GetStaticKey (), session); + m_ECIESx25519Sessions.emplace (session->GetRemoteStaticKey (), session); } else LogPrint (eLogError, "Garlic: can't decrypt ECIES-X25519-AEAD-Ratchet new session");