Browse Source

create new ECIESX25519AEADRatchet session if not found

pull/1458/head
orignal 5 years ago
parent
commit
451c3945f0
  1. 38
      libi2pd/ECIESX25519AEADRatchetSession.cpp
  2. 6
      libi2pd/ECIESX25519AEADRatchetSession.h
  3. 9
      libi2pd/Garlic.cpp

38
libi2pd/ECIESX25519AEADRatchetSession.cpp

@ -52,15 +52,14 @@ namespace garlic
buf += 32; len -= 32; buf += 32; len -= 32;
MixHash (aepk, 32); // h = SHA256(h || aepk) 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) GetOwner ()->Decrypt (aepk, sharedSecret, nullptr); // x25519(bsk, aepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31]
// decrypt flags/static // decrypt flags/static
uint8_t nonce[12], fs[32]; uint8_t nonce[12], fs[32];
memset (nonce, 0, 12); // n = 0 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 "); LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed ");
return false; return false;
@ -75,14 +74,13 @@ namespace garlic
if (isStatic) if (isStatic)
{ {
// static key, fs is apk // static key, fs is apk
memcpy (m_StaticKey, fs, 32); memcpy (m_RemoteStaticKey, fs, 32);
GetOwner ()->Decrypt (fs, sharedSecret, nullptr); // x25519(bsk, apk) GetOwner ()->Decrypt (fs, sharedSecret, nullptr); // x25519(bsk, apk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31]
} }
else // all zeros flags else // all zeros flags
htole64buf (nonce + 4, 1); // n = 1 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"); LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
return false; return false;
@ -132,7 +130,7 @@ namespace garlic
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) 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; size_t offset = 0;
if (!i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), out + offset)) if (!i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), out + offset))
{ {
@ -142,25 +140,31 @@ namespace garlic
offset += 32; offset += 32;
// KDF1 // 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) MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32], keyData[64]; uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (m_StaticKey, nullptr); // x25519(aesk, bpk) m_EphemeralKeys.Agree (m_RemoteStaticKey, nullptr); // x25519(aesk, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31]
// encrypt static key section // encrypt static key section
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); // n = 0 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 "); LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
return false; return false;
} }
MixHash (out + offset, 48); // h = SHA256(h || ciphertext) MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
offset += 48; offset += 48;
// KDF2 // 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; return true;
} }

6
libi2pd/ECIESX25519AEADRatchetSession.h

@ -1,6 +1,7 @@
#ifndef ECIES_X25519_AEAD_RATCHET_SESSION_H__ #ifndef ECIES_X25519_AEAD_RATCHET_SESSION_H__
#define ECIES_X25519_AEAD_RATCHET_SESSION_H__ #define ECIES_X25519_AEAD_RATCHET_SESSION_H__
#include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <functional> #include <functional>
#include "Identity.h" #include "Identity.h"
@ -34,7 +35,8 @@ namespace garlic
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg); std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
bool NewIncomingSession (const uint8_t * buf, size_t len, CloveHandler handleClove); 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: private:
@ -46,7 +48,7 @@ namespace garlic
private: 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; i2p::crypto::X25519Keys m_EphemeralKeys;
}; };
} }

9
libi2pd/Garlic.cpp

@ -664,7 +664,12 @@ namespace garlic
auto it = m_ECIESx25519Sessions.find (staticKey); auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ()) if (it != m_ECIESx25519Sessions.end ())
session = it->second; session = it->second;
// TODO: Alice if (!session)
{
session = std::make_shared<ECIESX25519AEADRatchetSession> (this);
session->SetRemoteStaticKey (staticKey);
m_ECIESx25519Sessions.emplace (staticKey, session);
}
return session; return session;
} }
else else
@ -860,7 +865,7 @@ namespace garlic
if (session->NewIncomingSession (buf, len, std::bind (&GarlicDestination::HandleECIESx25519GarlicClove, if (session->NewIncomingSession (buf, len, std::bind (&GarlicDestination::HandleECIESx25519GarlicClove,
this, std::placeholders::_1, std::placeholders::_2))) this, std::placeholders::_1, std::placeholders::_2)))
{ {
m_ECIESx25519Sessions.emplace (session->GetStaticKey (), session); m_ECIESx25519Sessions.emplace (session->GetRemoteStaticKey (), session);
} }
else else
LogPrint (eLogError, "Garlic: can't decrypt ECIES-X25519-AEAD-Ratchet new session"); LogPrint (eLogError, "Garlic: can't decrypt ECIES-X25519-AEAD-Ratchet new session");

Loading…
Cancel
Save