don't re-create noise state for every message

pull/1662/head
orignal 3 years ago
parent 3b051dbba3
commit 83fd289e46

@ -1109,21 +1109,22 @@ namespace garlic
bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len)
{
if (!GetOwner ()) return false;
i2p::crypto::NoiseSymmetricState state (GetNoiseState ());
m_CurrentNoiseState = GetNoiseState ();
// we are Bob
state.MixHash (buf, 32);
m_CurrentNoiseState.MixHash (buf, 32);
uint8_t sharedSecret[32];
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");
return false;
}
state.MixKey (sharedSecret);
m_CurrentNoiseState.MixKey (sharedSecret);
buf += 32; len -= 32;
uint8_t nonce[12];
CreateNonce (0, nonce);
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");
return false;

@ -249,6 +249,11 @@ namespace garlic
RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState);
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);

@ -426,8 +426,8 @@ namespace i2p
uint8_t nonce[12];
memset (nonce, 0, 12);
auto& noiseState = i2p::context.GetCurrentNoiseState ();
if (!noiseState || !i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16,
noiseState->m_H, 32, noiseState->m_CK, nonce, reply, TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
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
{
LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed");
return false;
@ -611,13 +611,8 @@ namespace i2p
return;
}
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)
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 (
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
@ -653,7 +648,7 @@ namespace i2p
otbrm->len += (payload - otbrm->GetPayload ());
otbrm->FillI2NPMessageHeader (eI2NPOutboundTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
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;
memcpy (&tag, replyKeys + 32, 8);
// send garlic to reply tunnel
@ -674,14 +669,14 @@ namespace i2p
{
// TODO: fill reply
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");
return;
}
}
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;
}
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET,

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

@ -125,7 +125,7 @@ namespace garlic
void SetSupportsV4 (bool supportsV4);
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; };
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 UpdateStats ();
@ -185,7 +185,7 @@ namespace garlic
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
std::unique_ptr<i2p::crypto::X25519Keys> m_StaticKeys;
// for ECIESx25519
std::unique_ptr<i2p::crypto::NoiseSymmetricState> m_InitialNoiseState, m_CurrentNoiseState;
i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState;
// i18n
std::shared_ptr<const i2p::i18n::Locale> m_Language;

Loading…
Cancel
Save