mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-10 06:34:15 +00:00
move handshake messages processing to NTCP2Establisher
This commit is contained in:
parent
86782aeb1b
commit
e4ab51329d
@ -244,6 +244,119 @@ namespace transport
|
|||||||
SHA256_Final (m_H, &ctx); //h = SHA256(h || ciphertext)
|
SHA256_Final (m_H, &ctx); //h = SHA256(h || ciphertext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen)
|
||||||
|
{
|
||||||
|
// decrypt X
|
||||||
|
i2p::crypto::CBCDecryption decryption;
|
||||||
|
decryption.SetKey (i2p::context.GetIdentHash ());
|
||||||
|
decryption.SetIV (i2p::context.GetNTCP2IV ());
|
||||||
|
decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ());
|
||||||
|
decryption.GetIV (m_IV); // save IV for SessionCreated
|
||||||
|
// decryption key for next block
|
||||||
|
KDF1Bob ();
|
||||||
|
// verify MAC and decrypt options block (32 bytes), use m_H as AD
|
||||||
|
uint8_t nonce[12], options[16];
|
||||||
|
memset (nonce, 0, 12); // set nonce to zero
|
||||||
|
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, m_H, 32, m_K, nonce, options, 16, false)) // decrypt
|
||||||
|
{
|
||||||
|
if (options[1] == 2)
|
||||||
|
{
|
||||||
|
paddingLen = bufbe16toh (options + 2);
|
||||||
|
m_SessionRequestBufferLen = paddingLen + 64;
|
||||||
|
m3p2Len = bufbe16toh (options + 4);
|
||||||
|
// TODO: check tsA
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionRequest version mismatch ", (int)options[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NTCP2Establisher::ProcessSessionCreatedMessage (uint16_t& paddingLen)
|
||||||
|
{
|
||||||
|
m_SessionCreatedBufferLen = 64;
|
||||||
|
// decrypt Y
|
||||||
|
i2p::crypto::CBCDecryption decryption;
|
||||||
|
decryption.SetKey (m_RemoteIdentHash);
|
||||||
|
decryption.SetIV (m_IV);
|
||||||
|
decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ());
|
||||||
|
// decryption key for next block (m_K)
|
||||||
|
KDF2Alice ();
|
||||||
|
// decrypt and verify MAC
|
||||||
|
uint8_t payload[16];
|
||||||
|
uint8_t nonce[12];
|
||||||
|
memset (nonce, 0, 12); // set nonce to zero
|
||||||
|
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, m_H, 32, m_K, nonce, payload, 16, false)) // decrypt
|
||||||
|
{
|
||||||
|
paddingLen = bufbe16toh(payload + 2);
|
||||||
|
// TODO: check tsB
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce)
|
||||||
|
{
|
||||||
|
// update AD
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
SHA256_Init (&ctx);
|
||||||
|
SHA256_Update (&ctx, m_H, 32);
|
||||||
|
SHA256_Update (&ctx, m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
||||||
|
SHA256_Final (m_H, &ctx);
|
||||||
|
|
||||||
|
int paddingLength = m_SessionCreatedBufferLen - 64;
|
||||||
|
if (paddingLength > 0)
|
||||||
|
{
|
||||||
|
SHA256_CTX ctx1;
|
||||||
|
SHA256_Init (&ctx1);
|
||||||
|
SHA256_Update (&ctx1, m_H, 32);
|
||||||
|
SHA256_Update (&ctx1, m_SessionCreatedBuffer + 64, paddingLength);
|
||||||
|
SHA256_Final (m_H, &ctx1);
|
||||||
|
}
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, m_H, 32, m_K, nonce, m_RemoteStaticKey, 32, false)) // decrypt S
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf)
|
||||||
|
{
|
||||||
|
// update AD again
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
SHA256_Init (&ctx);
|
||||||
|
SHA256_Update (&ctx, m_H, 32);
|
||||||
|
SHA256_Update (&ctx, m_SessionConfirmedBuffer, 48);
|
||||||
|
SHA256_Final (m_H, &ctx);
|
||||||
|
|
||||||
|
KDF3Bob ();
|
||||||
|
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, m_H, 32, m_K, nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt
|
||||||
|
{
|
||||||
|
// caclulate new h again for KDF data
|
||||||
|
memcpy (m_SessionConfirmedBuffer + 16, m_H, 32); // h || ciphertext
|
||||||
|
SHA256 (m_SessionConfirmedBuffer + 16, m3p2Len + 32, m_H); //h = SHA256(h || ciphertext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
|
NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
|
||||||
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
|
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
|
||||||
m_Server (server), m_Socket (m_Server.GetService ()),
|
m_Server (server), m_Socket (m_Server.GetService ()),
|
||||||
@ -368,52 +481,28 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// decrypt X
|
LogPrint (eLogDebug, "NTCP2: SessionRequest received ", bytes_transferred);
|
||||||
i2p::crypto::CBCDecryption decryption;
|
uint16_t paddingLen = 0;
|
||||||
decryption.SetKey (i2p::context.GetIdentHash ());
|
if (m_Establisher->ProcessSessionRequestMessage (paddingLen))
|
||||||
decryption.SetIV (i2p::context.GetNTCP2IV ());
|
|
||||||
decryption.Decrypt (m_Establisher->m_SessionRequestBuffer, 32, m_Establisher->GetRemotePub ());
|
|
||||||
decryption.GetIV (m_Establisher->m_IV); // save IV for SessionCreated
|
|
||||||
// decryption key for next block
|
|
||||||
m_Establisher->KDF1Bob ();
|
|
||||||
// verify MAC and decrypt options block (32 bytes), use m_H as AD
|
|
||||||
uint8_t nonce[12], options[16];
|
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionRequestBuffer + 32, 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, options, 16, false)) // decrypt
|
|
||||||
{
|
{
|
||||||
if (options[1] == 2)
|
if (paddingLen > 0)
|
||||||
{
|
{
|
||||||
uint16_t paddingLen = bufbe16toh (options + 2);
|
if (paddingLen <= 287 - 64) // session request is 287 bytes max
|
||||||
m_Establisher->m_SessionRequestBufferLen = paddingLen + 64;
|
|
||||||
m_Establisher->m3p2Len = bufbe16toh (options + 4);
|
|
||||||
// TODO: check tsA
|
|
||||||
if (paddingLen > 0)
|
|
||||||
{
|
{
|
||||||
if (paddingLen <= 287 - 64) // session request is 287 bytes max
|
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (),
|
||||||
{
|
std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||||
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (),
|
|
||||||
std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
|
||||||
Terminate ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendSessionCreated ();
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
||||||
|
Terminate ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
SendSessionCreated ();
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionRequest version mismatch ", (int)options[1]);
|
|
||||||
Terminate ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed ");
|
|
||||||
Terminate ();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,23 +535,9 @@ namespace transport
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NTCP2: SessionCreated received ", bytes_transferred);
|
LogPrint (eLogDebug, "NTCP2: SessionCreated received ", bytes_transferred);
|
||||||
m_Establisher->m_SessionCreatedBufferLen = 64;
|
uint16_t paddingLen = 0;
|
||||||
// decrypt Y
|
if (m_Establisher->ProcessSessionCreatedMessage (paddingLen))
|
||||||
i2p::crypto::CBCDecryption decryption;
|
{
|
||||||
decryption.SetKey (GetRemoteIdentity ()->GetIdentHash ());
|
|
||||||
decryption.SetIV (m_Establisher->m_IV);
|
|
||||||
decryption.Decrypt (m_Establisher->m_SessionCreatedBuffer, 32, m_Establisher->GetRemotePub ());
|
|
||||||
// decryption key for next block (m_K)
|
|
||||||
m_Establisher->KDF2Alice ();
|
|
||||||
// decrypt and verify MAC
|
|
||||||
uint8_t payload[16];
|
|
||||||
uint8_t nonce[12];
|
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionCreatedBuffer + 32, 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, payload, 16, false)) // decrypt
|
|
||||||
{
|
|
||||||
uint16_t paddingLen = bufbe16toh(payload + 2);
|
|
||||||
LogPrint (eLogDebug, "NTCP2: padding length ", paddingLen);
|
|
||||||
// TODO: check tsB
|
|
||||||
if (paddingLen > 0)
|
if (paddingLen > 0)
|
||||||
{
|
{
|
||||||
if (paddingLen <= 287 - 64) // session created is 287 bytes max
|
if (paddingLen <= 287 - 64) // session created is 287 bytes max
|
||||||
@ -480,10 +555,7 @@ namespace transport
|
|||||||
SendSessionConfirmed ();
|
SendSessionConfirmed ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed ");
|
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,38 +631,16 @@ namespace transport
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
|
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
|
||||||
// update AD
|
|
||||||
uint8_t h[80];
|
|
||||||
memcpy (h, m_Establisher->GetH (), 32);
|
|
||||||
memcpy (h + 32, m_Establisher->m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
|
||||||
SHA256 (h, 64, h);
|
|
||||||
int paddingLength = m_Establisher->m_SessionCreatedBufferLen - 64;
|
|
||||||
if (paddingLength > 0)
|
|
||||||
{
|
|
||||||
SHA256_CTX ctx;
|
|
||||||
SHA256_Init (&ctx);
|
|
||||||
SHA256_Update (&ctx, h, 32);
|
|
||||||
SHA256_Update (&ctx, m_Establisher->m_SessionCreatedBuffer + 64, paddingLength);
|
|
||||||
SHA256_Final (h, &ctx);
|
|
||||||
}
|
|
||||||
// part 1
|
// part 1
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (1, nonce);
|
CreateNonce (1, nonce);
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionConfirmedBuffer, 32, h, 32, m_Establisher->GetK (), nonce, m_Establisher->m_RemoteStaticKey, 32, false)) // decrypt S
|
if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce))
|
||||||
{
|
{
|
||||||
// part 2
|
// part 2
|
||||||
// update AD again
|
|
||||||
memcpy (h + 32, m_Establisher->m_SessionConfirmedBuffer, 48);
|
|
||||||
SHA256 (h, 80, m_Establisher->m_H);
|
|
||||||
|
|
||||||
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
|
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
|
||||||
m_Establisher->KDF3Bob ();
|
|
||||||
memset (nonce, 0, 12); // set nonce to 0 again
|
memset (nonce, 0, 12); // set nonce to 0 again
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionConfirmedBuffer + 48, m_Establisher->m3p2Len - 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, buf.data (), m_Establisher->m3p2Len - 16, false)) // decrypt
|
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf.data ()))
|
||||||
{
|
{
|
||||||
// caclulate new h again for KDF data
|
|
||||||
memcpy (m_Establisher->m_SessionConfirmedBuffer + 16, m_Establisher->GetH (), 32); // h || ciphertext
|
|
||||||
SHA256 (m_Establisher->m_SessionConfirmedBuffer + 16, m_Establisher->m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
|
|
||||||
KeyDerivationFunctionDataPhase ();
|
KeyDerivationFunctionDataPhase ();
|
||||||
// Bob data phase keys
|
// Bob data phase keys
|
||||||
m_SendKey = m_Kba;
|
m_SendKey = m_Kba;
|
||||||
@ -599,7 +649,7 @@ namespace transport
|
|||||||
m_ReceiveSipKey = m_Sipkeysab;
|
m_ReceiveSipKey = m_Sipkeysab;
|
||||||
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
|
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
|
||||||
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
|
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
|
||||||
|
// payload
|
||||||
// process RI
|
// process RI
|
||||||
if (buf[0] != eNTCP2BlkRouterInfo)
|
if (buf[0] != eNTCP2BlkRouterInfo)
|
||||||
{
|
{
|
||||||
@ -644,19 +694,13 @@ namespace transport
|
|||||||
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
|
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
|
||||||
m_Server.AddNTCP2Session (shared_from_this ());
|
m_Server.AddNTCP2Session (shared_from_this ());
|
||||||
Established ();
|
Established ();
|
||||||
ReceiveLength ();
|
ReceiveLength ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed ");
|
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed ");
|
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,12 +735,20 @@ namespace transport
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
i2p::crypto::Siphash<8> (m_ReceiveIV.buf, m_ReceiveIV.buf, 8, m_ReceiveSipKey);
|
i2p::crypto::Siphash<8> (m_ReceiveIV.buf, m_ReceiveIV.buf, 8, m_ReceiveSipKey);
|
||||||
// m_NextRecivedLen comes from the network in BigEndian
|
// m_NextReceivedLen comes from the network in BigEndian
|
||||||
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
|
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
|
||||||
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
|
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
|
||||||
if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer;
|
if (m_NextReceivedLen >= 16)
|
||||||
m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen];
|
{
|
||||||
Receive ();
|
if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer;
|
||||||
|
m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen];
|
||||||
|
Receive ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "NTCP2: received length ", m_NextReceivedLen, " is too short");
|
||||||
|
Terminate ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,11 @@ namespace transport
|
|||||||
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||||
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
||||||
|
|
||||||
|
bool ProcessSessionRequestMessage (uint16_t& paddingLen);
|
||||||
|
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
||||||
|
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||||
|
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
|
||||||
|
|
||||||
BN_CTX * m_Ctx;
|
BN_CTX * m_Ctx;
|
||||||
uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], m_RemoteEphemeralPublicKey[32]; // x25519
|
uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], m_RemoteEphemeralPublicKey[32]; // x25519
|
||||||
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/;
|
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user