Browse Source

new tag for each NSR

pull/1515/head
orignal 5 years ago
parent
commit
65e1871cd7
  1. 25
      libi2pd/ECIESX25519AEADRatchetSession.cpp
  2. 4
      libi2pd/ECIESX25519AEADRatchetSession.h

25
libi2pd/ECIESX25519AEADRatchetSession.cpp

@ -386,7 +386,8 @@ namespace garlic
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
// we are Bob // we are Bob
uint64_t tag = CreateNewSessionTagset ()->GetNextSessionTag (); m_NSRTagset = CreateNewSessionTagset ();
uint64_t tag = m_NSRTagset->GetNextSessionTag ();
size_t offset = 0; size_t offset = 0;
memcpy (out + offset, &tag, 8); memcpy (out + offset, &tag, 8);
@ -396,6 +397,8 @@ namespace garlic
LogPrint (eLogError, "Garlic: Can't encode elligator"); LogPrint (eLogError, "Garlic: Can't encode elligator");
return false; return false;
} }
memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR
memcpy (m_NSRH, m_H, 32);
offset += 32; offset += 32;
// KDF for Reply Key Section // KDF for Reply Key Section
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
@ -408,14 +411,13 @@ namespace garlic
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
// calulate hash for zero length // calulate hash for zero length
if (!i2p::crypto::AEADChaCha20Poly1305 (sharedSecret /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
{ {
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
return false; return false;
} }
MixHash (out + offset, 16); // h = SHA256(h || ciphertext) MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
offset += 16; offset += 16;
memcpy (m_NSRHeader, out, 56); // for possible next NSR
// KDF for payload // KDF for payload
uint8_t keydata[64]; uint8_t keydata[64];
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
@ -442,9 +444,21 @@ namespace garlic
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
// we are Bob and sent NSR already // we are Bob and sent NSR already
memcpy (out, m_NSRHeader, 56); uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag
memcpy (out, &tag, 8);
memcpy (out + 8, m_NSREncodedKey, 32);
// recalculte h with new tag
memcpy (m_H, m_NSRH, 32);
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
{
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
return false;
}
MixHash (out + 40, 16); // h = SHA256(h || ciphertext)
// encrypt payload // encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
{ {
@ -568,6 +582,7 @@ namespace garlic
{ {
case eSessionStateNewSessionReplySent: case eSessionStateNewSessionReplySent:
m_State = eSessionStateEstablished; m_State = eSessionStateEstablished;
m_NSRTagset = nullptr;
#if (__cplusplus >= 201703L) // C++ 17 or higher #if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]]; [[fallthrough]];
#endif #endif

4
libi2pd/ECIESX25519AEADRatchetSession.h

@ -147,11 +147,11 @@ namespace garlic
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32]; uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
uint8_t m_NSRHeader[56], m_NSRKey[32]; // new session reply, for incoming only uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
i2p::crypto::X25519Keys m_EphemeralKeys; i2p::crypto::X25519Keys m_EphemeralKeys;
SessionState m_State = eSessionStateNew; SessionState m_State = eSessionStateNew;
uint64_t m_LastActivityTimestamp = 0; // incoming uint64_t m_LastActivityTimestamp = 0; // incoming
std::shared_ptr<RatchetTagSet> m_SendTagset; std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index) std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
bool m_SendReverseKey = false, m_SendForwardKey = false; bool m_SendReverseKey = false, m_SendForwardKey = false;

Loading…
Cancel
Save