Browse Source

handle out of order NSR

pull/1515/head
orignal 4 years ago
parent
commit
3d9c844dca
  1. 52
      libi2pd/ECIESX25519AEADRatchetSession.cpp

52
libi2pd/ECIESX25519AEADRatchetSession.cpp

@ -482,13 +482,18 @@ namespace garlic
} }
buf += 32; len -= 32; buf += 32; len -= 32;
// KDF for Reply Key Section // KDF for Reply Key Section
uint8_t h[32]; memcpy (h, m_H, 32); // save m_H
MixHash (tag, 8); // h = SHA256(h || tag) MixHash (tag, 8); // h = SHA256(h || tag)
MixHash (bepk, 32); // h = SHA256(h || bepk) MixHash (bepk, 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) if (m_State == eSessionStateNewSessionSent)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) {
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk) // only fist time, we assume ephemeral keys the same
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
}
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
// calulate hash for zero length // calulate hash for zero length
@ -502,14 +507,17 @@ namespace garlic
// 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)
// k_ab = keydata[0:31], k_ba = keydata[32:63] if (m_State == eSessionStateNewSessionSent)
m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); {
m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) // k_ab = keydata[0:31], k_ba = keydata[32:63]
m_SendTagset->NextSessionTagRatchet (); m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) m_SendTagset->NextSessionTagRatchet ();
receiveTagset->NextSessionTagRatchet (); auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS); receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
receiveTagset->NextSessionTagRatchet ();
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS);
}
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
// decrypt payload // decrypt payload
std::vector<uint8_t> payload (len - 16); std::vector<uint8_t> payload (len - 16);
@ -518,9 +526,13 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
return false; return false;
} }
m_State = eSessionStateEstablished; if (m_State == eSessionStateNewSessionSent)
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); {
m_State = eSessionStateEstablished;
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
}
memcpy (m_H, h, 32); // restore m_H
HandlePayload (payload.data (), len - 16, nullptr, 0); HandlePayload (payload.data (), len - 16, nullptr, 0);
// we have received reply to NS with LeaseSet in it // we have received reply to NS with LeaseSet in it
@ -587,7 +599,15 @@ namespace garlic
[[fallthrough]]; [[fallthrough]];
#endif #endif
case eSessionStateEstablished: case eSessionStateEstablished:
return HandleExistingSessionMessage (buf, len, receiveTagset, index); if (HandleExistingSessionMessage (buf, len, receiveTagset, index)) return true;
if (index < ECIESX25519_NSR_NUM_GENERATED_TAGS)
{
// check NSR just in case
LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index);
return HandleNewOutgoingSessionReply (buf, len);
}
else
return false;
case eSessionStateNew: case eSessionStateNew:
return HandleNewIncomingSession (buf, len); return HandleNewIncomingSession (buf, len);
case eSessionStateNewSessionSent: case eSessionStateNewSessionSent:

Loading…
Cancel
Save