From 521fb83e382d0aedd2b3f2db1320ff1016ebbe7b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Dec 2019 16:18:40 -0500 Subject: [PATCH] initial code for ECIES-X25519-AEAD-Ratchet KDF --- libi2pd/CryptoKey.cpp | 7 ++----- libi2pd/CryptoKey.h | 4 ++-- libi2pd/Destination.h | 2 ++ libi2pd/Garlic.cpp | 36 ++++++++++++++++++++++++++++++++++++ libi2pd/Garlic.h | 3 +++ libi2pd/Identity.h | 2 ++ 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index 1c362c3b..f247f37e 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -1,7 +1,6 @@ #include #include "Log.h" #include "Gost.h" -#include "Elligator.h" #include "CryptoKey.h" namespace i2p @@ -148,11 +147,9 @@ namespace crypto } - bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * keyMaterial, BN_CTX * ctx, bool zeroPadding) + bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding) { - uint8_t key[32]; - if (!GetElligator ()->Decode (epub, key)) return false; - m_StaticKeys.Agree (key, keyMaterial); + m_StaticKeys.Agree (epub, sharedSecret); return true; } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index c4788959..e7cde780 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -125,8 +125,8 @@ namespace crypto ECIESX25519AEADRatchetDecryptor (const uint8_t * priv): m_StaticKeys (priv, nullptr) {}; ~ECIESX25519AEADRatchetDecryptor () {}; - bool Decrypt (const uint8_t * epub, uint8_t * keyMaterial, BN_CTX * ctx, bool zeroPadding); - // take elligator encoded ephemeral pub (32 bytes), agree with static and return in keyMaterial (32 bytes) + bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding); + // agree with static and return in sharedSecret (32 bytes) size_t GetPublicKeyLen () const { return 32; }; private: diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index a32d3ed1..e4489fe0 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -237,6 +237,8 @@ namespace client // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const; std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; + i2p::data::CryptoKeyType GetEncryptionType () const { return m_EncryptionKeyType; }; + const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; protected: diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 888e988c..823f61ea 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1,8 +1,10 @@ #include +#include #include "I2PEndian.h" #include #include #include "Crypto.h" +#include "Elligator.h" #include "RouterContext.h" #include "I2NPProtocol.h" #include "Tunnel.h" @@ -433,6 +435,12 @@ namespace garlic return; } buf += 4; // length + if (GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET) + { + HandleECIESx25519 (buf, length - 4); + return; + } + // otherwise assume ElGamal/AES auto it = m_Tags.find (SessionTag(buf)); if (it != m_Tags.end ()) { @@ -821,5 +829,33 @@ namespace garlic if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT) i2p::fs::Remove (it); } + + void GarlicDestination::HandleECIESx25519 (const uint8_t * buf, size_t len) + { + // KDF + // TODO : use precalculated hashes + static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes + uint8_t h[64], ck[32]; + SHA256 ((const uint8_t *)protocolName, 40, h); + memcpy (ck, h, 32); + SHA256 (h, 32, h); + // we are Bob + memcpy (h + 32, GetEncryptionPublicKey (), 32); + SHA256 (h, 64, h); // h = SHA256(h || bpk) + + uint8_t aepk[32]; + if (!i2p::crypto::GetElligator ()->Decode (buf, aepk)) + { + LogPrint (eLogError, "Garlic: Can't decode elligator"); + return; + } + memcpy (h + 32, aepk, 32); + SHA256 (h, 64, h); // h = SHA256(h || aepk) + + uint8_t sharedSecret[32], keyData[64]; + Decrypt (aepk, sharedSecret, m_Ctx); // x25519 + i2p::crypto::HKDF (ck, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) + memcpy (ck, keyData, 32); // chainKey = keydata[0:31] + } } } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index c5236c90..b34fc00f 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -206,6 +206,9 @@ namespace garlic std::shared_ptr from); void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr from); + // ECIES-X25519-AEAD-Ratchet + void HandleECIESx25519 (const uint8_t * buf, size_t len); + private: BN_CTX * m_Ctx; // incoming diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 2fecc28a..3bacf5da 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -227,6 +227,8 @@ namespace data virtual std::shared_ptr GetIdentity () const = 0; const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); }; + virtual CryptoKeyType GetEncryptionType () const { return GetIdentity ()->GetCryptoKeyType (); }; // override for LeaseSet + virtual const uint8_t * GetEncryptionPublicKey () const { return GetIdentity ()->GetEncryptionPublicKey (); }; // override for LeaseSet }; } }