Browse Source

don't re-create noise state for every message

pull/1662/head
orignal 4 years ago
parent
commit
83fd289e46
  1. 9
      libi2pd/ECIESX25519AEADRatchetSession.cpp
  2. 5
      libi2pd/ECIESX25519AEADRatchetSession.h
  3. 17
      libi2pd/I2NPProtocol.cpp
  4. 19
      libi2pd/RouterContext.cpp
  5. 4
      libi2pd/RouterContext.h

9
libi2pd/ECIESX25519AEADRatchetSession.cpp

@ -1109,21 +1109,22 @@ namespace garlic
bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len) bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len)
{ {
if (!GetOwner ()) return false; if (!GetOwner ()) return false;
i2p::crypto::NoiseSymmetricState state (GetNoiseState ()); m_CurrentNoiseState = GetNoiseState ();
// we are Bob // we are Bob
state.MixHash (buf, 32); m_CurrentNoiseState.MixHash (buf, 32);
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
if (!GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk) if (!GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
{ {
LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key"); LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key");
return false; return false;
} }
state.MixKey (sharedSecret); m_CurrentNoiseState.MixKey (sharedSecret);
buf += 32; len -= 32; buf += 32; len -= 32;
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
std::vector<uint8_t> payload (len - 16); std::vector<uint8_t> payload (len - 16);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, state.m_H, 32, state.m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_CurrentNoiseState.m_H, 32,
m_CurrentNoiseState.m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
{ {
LogPrint (eLogWarning, "Garlic: Payload for router AEAD verification failed"); LogPrint (eLogWarning, "Garlic: Payload for router AEAD verification failed");
return false; return false;

5
libi2pd/ECIESX25519AEADRatchetSession.h

@ -249,6 +249,11 @@ namespace garlic
RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState); RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState);
bool HandleNextMessage (const uint8_t * buf, size_t len); bool HandleNextMessage (const uint8_t * buf, size_t len);
i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; };
private:
i2p::crypto::NoiseSymmetricState m_CurrentNoiseState;
}; };
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag); std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);

17
libi2pd/I2NPProtocol.cpp

@ -426,8 +426,8 @@ namespace i2p
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); memset (nonce, 0, 12);
auto& noiseState = i2p::context.GetCurrentNoiseState (); auto& noiseState = i2p::context.GetCurrentNoiseState ();
if (!noiseState || !i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16, if (!i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16,
noiseState->m_H, 32, noiseState->m_CK, nonce, reply, TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt noiseState.m_H, 32, noiseState.m_CK, nonce, reply, TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
{ {
LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed"); LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed");
return false; return false;
@ -611,13 +611,8 @@ namespace i2p
return; return;
} }
auto& noiseState = i2p::context.GetCurrentNoiseState (); auto& noiseState = i2p::context.GetCurrentNoiseState ();
if (!noiseState)
{
LogPrint (eLogWarning, "I2NP: Invalid Noise state for short reply encryption");
return;
}
uint8_t layerKeys[64]; // (layer key, iv key) uint8_t layerKeys[64]; // (layer key, iv key)
i2p::crypto::HKDF (noiseState->m_CK + 32, nullptr, 0, "LayerAndIVKeys", layerKeys); // TODO: correct domain i2p::crypto::HKDF (noiseState.m_CK + 32, nullptr, 0, "LayerAndIVKeys", layerKeys); // TODO: correct domain
auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
@ -653,7 +648,7 @@ namespace i2p
otbrm->len += (payload - otbrm->GetPayload ()); otbrm->len += (payload - otbrm->GetPayload ());
otbrm->FillI2NPMessageHeader (eI2NPOutboundTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); otbrm->FillI2NPMessageHeader (eI2NPOutboundTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
uint8_t replyKeys[64]; // (reply key, tag) uint8_t replyKeys[64]; // (reply key, tag)
i2p::crypto::HKDF (noiseState->m_CK, nullptr, 0, "ReplyKeyAndTag", replyKeys); // TODO: correct domain i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "ReplyKeyAndTag", replyKeys); // TODO: correct domain
uint64_t tag; uint64_t tag;
memcpy (&tag, replyKeys + 32, 8); memcpy (&tag, replyKeys + 32, 8);
// send garlic to reply tunnel // send garlic to reply tunnel
@ -674,14 +669,14 @@ namespace i2p
{ {
// TODO: fill reply // TODO: fill reply
if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16, if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16,
noiseState->m_H, 32, noiseState->m_CK, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt noiseState.m_H, 32, noiseState.m_CK, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
{ {
LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed"); LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed");
return; return;
} }
} }
else else
i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, noiseState->m_CK, nonce, reply); i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, noiseState.m_CK, nonce, reply);
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; reply += SHORT_TUNNEL_BUILD_RECORD_SIZE;
} }
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET,

19
libi2pd/RouterContext.cpp

@ -45,10 +45,8 @@ namespace i2p
UpdateRouterInfo (); UpdateRouterInfo ();
if (IsECIES ()) if (IsECIES ())
{ {
auto initState = new i2p::crypto::NoiseSymmetricState (); i2p::crypto::InitNoiseNState (m_InitialNoiseState, GetIdentity ()->GetEncryptionPublicKey ());
i2p::crypto::InitNoiseNState (*initState, GetIdentity ()->GetEncryptionPublicKey ()); m_ECIESSession = std::make_shared<i2p::garlic::RouterIncomingRatchetSession>(m_InitialNoiseState);
m_InitialNoiseState.reset (initState);
m_ECIESSession = std::make_shared<i2p::garlic::RouterIncomingRatchetSession>(*initState);
} }
} }
@ -889,27 +887,26 @@ namespace i2p
bool RouterContext::DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize) bool RouterContext::DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize)
{ {
if (!m_InitialNoiseState || !m_TunnelDecryptor) return false;
// m_InitialNoiseState is h = SHA256(h || hepk) // m_InitialNoiseState is h = SHA256(h || hepk)
m_CurrentNoiseState.reset (new i2p::crypto::NoiseSymmetricState (*m_InitialNoiseState)); m_CurrentNoiseState = m_InitialNoiseState;
m_CurrentNoiseState->MixHash (encrypted, 32); // h = SHA256(h || sepk) m_CurrentNoiseState.MixHash (encrypted, 32); // h = SHA256(h || sepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
if (!m_TunnelDecryptor->Decrypt (encrypted, sharedSecret, nullptr, false)) if (!m_TunnelDecryptor->Decrypt (encrypted, sharedSecret, nullptr, false))
{ {
LogPrint (eLogWarning, "Router: Incorrect ephemeral public key"); LogPrint (eLogWarning, "Router: Incorrect ephemeral public key");
return false; return false;
} }
m_CurrentNoiseState->MixKey (sharedSecret); m_CurrentNoiseState.MixKey (sharedSecret);
encrypted += 32; encrypted += 32;
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); memset (nonce, 0, 12);
if (!i2p::crypto::AEADChaCha20Poly1305 (encrypted, clearTextSize, m_CurrentNoiseState->m_H, 32, if (!i2p::crypto::AEADChaCha20Poly1305 (encrypted, clearTextSize, m_CurrentNoiseState.m_H, 32,
m_CurrentNoiseState->m_CK + 32, nonce, data, clearTextSize, false)) // decrypt m_CurrentNoiseState.m_CK + 32, nonce, data, clearTextSize, false)) // decrypt
{ {
LogPrint (eLogWarning, "Router: Tunnel record AEAD decryption failed"); LogPrint (eLogWarning, "Router: Tunnel record AEAD decryption failed");
return false; return false;
} }
m_CurrentNoiseState->MixHash (encrypted, clearTextSize + 16); // h = SHA256(h || ciphertext) m_CurrentNoiseState.MixHash (encrypted, clearTextSize + 16); // h = SHA256(h || ciphertext)
return true; return true;
} }

4
libi2pd/RouterContext.h

@ -125,7 +125,7 @@ namespace garlic
void SetSupportsV4 (bool supportsV4); void SetSupportsV4 (bool supportsV4);
void SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host); void SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host);
bool IsECIES () const { return GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }; bool IsECIES () const { return GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
std::unique_ptr<i2p::crypto::NoiseSymmetricState>& GetCurrentNoiseState () { return m_CurrentNoiseState; }; i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; };
void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove
void UpdateStats (); void UpdateStats ();
@ -185,7 +185,7 @@ namespace garlic
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys; std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
std::unique_ptr<i2p::crypto::X25519Keys> m_StaticKeys; std::unique_ptr<i2p::crypto::X25519Keys> m_StaticKeys;
// for ECIESx25519 // for ECIESx25519
std::unique_ptr<i2p::crypto::NoiseSymmetricState> m_InitialNoiseState, m_CurrentNoiseState; i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState;
// i18n // i18n
std::shared_ptr<const i2p::i18n::Locale> m_Language; std::shared_ptr<const i2p::i18n::Locale> m_Language;

Loading…
Cancel
Save