mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-16 06:02:18 +02:00
Use noise state Encrypt/Decrypt operations
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
This commit is contained in:
parent
711f5bcc62
commit
f6abbe5908
2 changed files with 49 additions and 41 deletions
|
@ -145,10 +145,12 @@ namespace transport
|
||||||
// 2 bytes reserved
|
// 2 bytes reserved
|
||||||
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds
|
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds
|
||||||
// 4 bytes reserved
|
// 4 bytes reserved
|
||||||
// sign and encrypt options, use m_H as AD
|
// encrypt options
|
||||||
uint8_t nonce[12];
|
if (!Encrypt (options, m_SessionRequestBuffer + 32, 16))
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
{
|
||||||
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionRequestBuffer + 32, 32, true); // encrypt
|
LogPrint (eLogWarning, "NTCP2: SessionRequest failed to encrypt options");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,14 +169,16 @@ namespace transport
|
||||||
memset (options, 0, 16);
|
memset (options, 0, 16);
|
||||||
htobe16buf (options + 2, paddingLen); // padLen
|
htobe16buf (options + 2, paddingLen); // padLen
|
||||||
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds
|
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds
|
||||||
// sign and encrypt options, use m_H as AD
|
// encrypt options
|
||||||
uint8_t nonce[12];
|
if (!Encrypt (options, m_SessionCreatedBuffer + 32, 16))
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
{
|
||||||
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionCreatedBuffer + 32, 32, true); // encrypt
|
LogPrint (eLogWarning, "NTCP2: SessionCreated failed to encrypt options");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Establisher::CreateSessionConfirmedMessagePart1 (const uint8_t * nonce)
|
bool NTCP2Establisher::CreateSessionConfirmedMessagePart1 ()
|
||||||
{
|
{
|
||||||
// update AD
|
// update AD
|
||||||
MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
||||||
|
@ -182,19 +186,28 @@ namespace transport
|
||||||
if (paddingLength > 0)
|
if (paddingLength > 0)
|
||||||
MixHash (m_SessionCreatedBuffer + 64, paddingLength);
|
MixHash (m_SessionCreatedBuffer + 64, paddingLength);
|
||||||
|
|
||||||
// part1 48 bytes
|
// part1 48 bytes, n = 1
|
||||||
i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, GetH (), 32, GetK (), nonce, m_SessionConfirmedBuffer, 48, true); // encrypt
|
if (!Encrypt (i2p::context.GetNTCP2StaticPublicKey (), m_SessionConfirmedBuffer, 32))
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionConfirmed failed to encrypt part1");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::CreateSessionConfirmedMessagePart2 (const uint8_t * nonce)
|
bool NTCP2Establisher::CreateSessionConfirmedMessagePart2 ()
|
||||||
{
|
{
|
||||||
// part 2
|
// part 2
|
||||||
// update AD again
|
// update AD again
|
||||||
MixHash (m_SessionConfirmedBuffer, 48);
|
MixHash (m_SessionConfirmedBuffer, 48);
|
||||||
// encrypt m3p2, it must be filled in SessionRequest
|
// encrypt m3p2, it must be filled in SessionRequest
|
||||||
if (!KDF3Alice ()) return false;
|
if (!KDF3Alice ()) return false; // MixKey, n = 0
|
||||||
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
|
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
|
||||||
i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt
|
if (!Encrypt (m3p2, m3p2, m3p2Len - 16))
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionConfirmed failed to encrypt part2");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// update h again
|
// update h again
|
||||||
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
|
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
|
||||||
return true;
|
return true;
|
||||||
|
@ -214,10 +227,9 @@ namespace transport
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionRequest KDF failed");
|
LogPrint (eLogWarning, "NTCP2: SessionRequest KDF failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// verify MAC and decrypt options block (32 bytes), use m_H as AD
|
// verify MAC and decrypt options block (32 bytes)
|
||||||
uint8_t nonce[12], options[16];
|
uint8_t options[16];
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
if (Decrypt (m_SessionRequestBuffer + 32, options, 16))
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, GetH (), 32, GetK (), nonce, options, 16, false)) // decrypt
|
|
||||||
{
|
{
|
||||||
// options
|
// options
|
||||||
if (options[0] && options[0] != i2p::context.GetNetID ())
|
if (options[0] && options[0] != i2p::context.GetNetID ())
|
||||||
|
@ -274,9 +286,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
// decrypt and verify MAC
|
// decrypt and verify MAC
|
||||||
uint8_t payload[16];
|
uint8_t payload[16];
|
||||||
uint8_t nonce[12];
|
if (Decrypt (m_SessionCreatedBuffer + 32, payload, 16))
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, GetH (), 32, GetK (), nonce, payload, 16, false)) // decrypt
|
|
||||||
{
|
{
|
||||||
// options
|
// options
|
||||||
paddingLen = bufbe16toh(payload + 2);
|
paddingLen = bufbe16toh(payload + 2);
|
||||||
|
@ -297,7 +307,7 @@ namespace transport
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce)
|
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 ()
|
||||||
{
|
{
|
||||||
// update AD
|
// update AD
|
||||||
MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
||||||
|
@ -305,7 +315,8 @@ namespace transport
|
||||||
if (paddingLength > 0)
|
if (paddingLength > 0)
|
||||||
MixHash (m_SessionCreatedBuffer + 64, paddingLength);
|
MixHash (m_SessionCreatedBuffer + 64, paddingLength);
|
||||||
|
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, GetH (), 32, GetK (), nonce, m_RemoteStaticKey, 32, false)) // decrypt S
|
// decrypt S, n = 1
|
||||||
|
if (!Decrypt (m_SessionConfirmedBuffer, m_RemoteStaticKey, 32))
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed ");
|
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed ");
|
||||||
return false;
|
return false;
|
||||||
|
@ -313,17 +324,17 @@ namespace transport
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf)
|
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (uint8_t * m3p2Buf)
|
||||||
{
|
{
|
||||||
// update AD again
|
// update AD again
|
||||||
MixHash (m_SessionConfirmedBuffer, 48);
|
MixHash (m_SessionConfirmedBuffer, 48);
|
||||||
|
|
||||||
if (!KDF3Bob ())
|
if (!KDF3Bob ()) // MixKey, n = 0
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 KDF failed");
|
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 KDF failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt
|
if (Decrypt (m_SessionConfirmedBuffer + 48, m3p2Buf, m3p2Len - 16))
|
||||||
// calculate new h again for KDF data
|
// calculate new h again for KDF data
|
||||||
MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext)
|
MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext)
|
||||||
else
|
else
|
||||||
|
@ -657,11 +668,12 @@ namespace transport
|
||||||
|
|
||||||
void NTCP2Session::SendSessionConfirmed ()
|
void NTCP2Session::SendSessionConfirmed ()
|
||||||
{
|
{
|
||||||
uint8_t nonce[12];
|
if (!m_Establisher->CreateSessionConfirmedMessagePart1 ())
|
||||||
CreateNonce (1, nonce); // set nonce to 1
|
{
|
||||||
m_Establisher->CreateSessionConfirmedMessagePart1 (nonce);
|
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
||||||
memset (nonce, 0, 12); // set nonce back to 0
|
return;
|
||||||
if (!m_Establisher->CreateSessionConfirmedMessagePart2 (nonce))
|
}
|
||||||
|
if (!m_Establisher->CreateSessionConfirmedMessagePart2 ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: Send SessionConfirmed Part2 KDF failed");
|
LogPrint (eLogWarning, "NTCP2: Send SessionConfirmed Part2 KDF failed");
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
||||||
|
@ -740,14 +752,11 @@ namespace transport
|
||||||
// run on establisher thread
|
// run on establisher thread
|
||||||
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
|
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
|
||||||
// part 1
|
// part 1
|
||||||
uint8_t nonce[12];
|
if (m_Establisher->ProcessSessionConfirmedMessagePart1 ())
|
||||||
CreateNonce (1, nonce);
|
|
||||||
if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce))
|
|
||||||
{
|
{
|
||||||
// part 2
|
// part 2
|
||||||
auto buf = std::make_shared<std::vector<uint8_t> > (m_Establisher->m3p2Len - 16); // -MAC
|
auto buf = std::make_shared<std::vector<uint8_t> > (m_Establisher->m3p2Len - 16); // -MAC
|
||||||
memset (nonce, 0, 12); // set nonce to 0 again
|
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (buf->data ())) // TODO:handle in establisher thread
|
||||||
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf->data ())) // TODO:handle in establisher thread
|
|
||||||
{
|
{
|
||||||
// payload
|
// payload
|
||||||
// RI block must be first
|
// RI block must be first
|
||||||
|
|
|
@ -91,7 +91,6 @@ namespace transport
|
||||||
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
|
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
|
||||||
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
|
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
|
||||||
|
|
||||||
const uint8_t * GetK () const { return m_CK + 32; };
|
|
||||||
const uint8_t * GetCK () const { return m_CK; };
|
const uint8_t * GetCK () const { return m_CK; };
|
||||||
const uint8_t * GetH () const { return m_H; };
|
const uint8_t * GetH () const { return m_H; };
|
||||||
|
|
||||||
|
@ -108,13 +107,13 @@ namespace transport
|
||||||
|
|
||||||
bool CreateSessionRequestMessage (std::mt19937& rng);
|
bool CreateSessionRequestMessage (std::mt19937& rng);
|
||||||
bool CreateSessionCreatedMessage (std::mt19937& rng);
|
bool CreateSessionCreatedMessage (std::mt19937& rng);
|
||||||
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
bool CreateSessionConfirmedMessagePart1 ();
|
||||||
bool CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
bool CreateSessionConfirmedMessagePart2 ();
|
||||||
|
|
||||||
bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew);
|
bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew);
|
||||||
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
||||||
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
bool ProcessSessionConfirmedMessagePart1 ();
|
||||||
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
|
bool ProcessSessionConfirmedMessagePart2 (uint8_t * m3p2Buf);
|
||||||
|
|
||||||
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
|
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
|
||||||
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
|
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
|
||||||
|
|
Loading…
Add table
Reference in a new issue