mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
reduced memory usage
This commit is contained in:
parent
c8cdeead44
commit
6069055c9e
107
NTCPSession.cpp
107
NTCPSession.cpp
@ -25,10 +25,12 @@ namespace ntcp
|
||||
m_NumSentBytes (0), m_NumReceivedBytes (0)
|
||||
{
|
||||
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
||||
m_Establisher = new Establisher;
|
||||
}
|
||||
|
||||
NTCPSession::~NTCPSession ()
|
||||
{
|
||||
delete m_Establisher;
|
||||
delete m_DHKeysPair;
|
||||
if (m_NextMessage)
|
||||
i2p::DeleteI2NPMessage (m_NextMessage);
|
||||
@ -95,6 +97,9 @@ namespace ntcp
|
||||
LogPrint ("NTCP session connected");
|
||||
m_IsEstablished = true;
|
||||
|
||||
delete m_Establisher;
|
||||
m_Establisher = nullptr;
|
||||
|
||||
SendTimeSyncMessage ();
|
||||
SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are
|
||||
|
||||
@ -110,20 +115,20 @@ namespace ntcp
|
||||
{
|
||||
// send Phase1
|
||||
const uint8_t * x = m_DHKeysPair->publicKey;
|
||||
memcpy (m_Phase1.pubKey, x, 256);
|
||||
CryptoPP::SHA256().CalculateDigest(m_Phase1.HXxorHI, x, 256);
|
||||
memcpy (m_Establisher->phase1.pubKey, x, 256);
|
||||
CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256);
|
||||
const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash ();
|
||||
for (int i = 0; i < 32; i++)
|
||||
m_Phase1.HXxorHI[i] ^= ident[i];
|
||||
m_Establisher->phase1.HXxorHI[i] ^= ident[i];
|
||||
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Phase1, sizeof (m_Phase1)), boost::asio::transfer_all (),
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase1, sizeof (NTCPPhase1)), boost::asio::transfer_all (),
|
||||
boost::bind(&NTCPSession::HandlePhase1Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void NTCPSession::ServerLogin ()
|
||||
{
|
||||
// receive Phase1
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Phase1, sizeof (m_Phase1)),
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Establisher->phase1, sizeof (NTCPPhase1)),
|
||||
boost::bind(&NTCPSession::HandlePhase1Received, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
@ -138,7 +143,7 @@ namespace ntcp
|
||||
else
|
||||
{
|
||||
LogPrint ("Phase 1 sent: ", bytes_transferred);
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Phase2, sizeof (m_Phase2)),
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Establisher->phase2, sizeof (NTCPPhase2)),
|
||||
boost::bind(&NTCPSession::HandlePhase2Received, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
@ -156,11 +161,11 @@ namespace ntcp
|
||||
LogPrint ("Phase 1 received: ", bytes_transferred);
|
||||
// verify ident
|
||||
uint8_t digest[32];
|
||||
CryptoPP::SHA256().CalculateDigest(digest, m_Phase1.pubKey, 256);
|
||||
CryptoPP::SHA256().CalculateDigest(digest, m_Establisher->phase1.pubKey, 256);
|
||||
const uint8_t * ident = i2p::context.GetRouterInfo ().GetIdentHash ();
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if ((m_Phase1.HXxorHI[i] ^ ident[i]) != digest[i])
|
||||
if ((m_Establisher->phase1.HXxorHI[i] ^ ident[i]) != digest[i])
|
||||
{
|
||||
LogPrint ("Wrong ident");
|
||||
Terminate ();
|
||||
@ -175,24 +180,24 @@ namespace ntcp
|
||||
void NTCPSession::SendPhase2 ()
|
||||
{
|
||||
const uint8_t * y = m_DHKeysPair->publicKey;
|
||||
memcpy (m_Phase2.pubKey, y, 256);
|
||||
memcpy (m_Establisher->phase2.pubKey, y, 256);
|
||||
uint8_t xy[512];
|
||||
memcpy (xy, m_Phase1.pubKey, 256);
|
||||
memcpy (xy, m_Establisher->phase1.pubKey, 256);
|
||||
memcpy (xy + 256, y, 256);
|
||||
CryptoPP::SHA256().CalculateDigest(m_Phase2.encrypted.hxy, xy, 512);
|
||||
CryptoPP::SHA256().CalculateDigest(m_Establisher->phase2.encrypted.hxy, xy, 512);
|
||||
uint32_t tsB = htobe32 (i2p::util::GetSecondsSinceEpoch ());
|
||||
m_Phase2.encrypted.timestamp = tsB;
|
||||
m_Establisher->phase2.encrypted.timestamp = tsB;
|
||||
// TODO: fill filler
|
||||
|
||||
uint8_t aesKey[32];
|
||||
CreateAESKey (m_Phase1.pubKey, aesKey);
|
||||
CreateAESKey (m_Establisher->phase1.pubKey, aesKey);
|
||||
m_Encryption.SetKey (aesKey);
|
||||
m_Encryption.SetIV (y + 240);
|
||||
m_Decryption.SetKey (aesKey);
|
||||
m_Decryption.SetIV (m_Phase1.HXxorHI + 16);
|
||||
m_Decryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
||||
|
||||
m_Encryption.Encrypt ((uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted), (uint8_t *)&m_Phase2.encrypted);
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Phase2, sizeof (m_Phase2)), boost::asio::transfer_all (),
|
||||
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase2, sizeof (NTCPPhase2)), boost::asio::transfer_all (),
|
||||
boost::bind(&NTCPSession::HandlePhase2Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsB));
|
||||
|
||||
}
|
||||
@ -207,7 +212,7 @@ namespace ntcp
|
||||
else
|
||||
{
|
||||
LogPrint ("Phase 2 sent: ", bytes_transferred);
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Phase3, sizeof (m_Phase3)),
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Establisher->phase3, sizeof (NTCPPhase3)),
|
||||
boost::bind(&NTCPSession::HandlePhase3Received, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsB));
|
||||
}
|
||||
@ -226,19 +231,19 @@ namespace ntcp
|
||||
LogPrint ("Phase 2 received: ", bytes_transferred);
|
||||
|
||||
uint8_t aesKey[32];
|
||||
CreateAESKey (m_Phase2.pubKey, aesKey);
|
||||
CreateAESKey (m_Establisher->phase2.pubKey, aesKey);
|
||||
m_Decryption.SetKey (aesKey);
|
||||
m_Decryption.SetIV (m_Phase2.pubKey + 240);
|
||||
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
|
||||
m_Encryption.SetKey (aesKey);
|
||||
m_Encryption.SetIV (m_Phase1.HXxorHI + 16);
|
||||
m_Encryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
||||
|
||||
m_Decryption.Decrypt((uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted), (uint8_t *)&m_Phase2.encrypted);
|
||||
m_Decryption.Decrypt((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
||||
// verify
|
||||
uint8_t xy[512], hxy[32];
|
||||
memcpy (xy, m_DHKeysPair->publicKey, 256);
|
||||
memcpy (xy + 256, m_Phase2.pubKey, 256);
|
||||
memcpy (xy + 256, m_Establisher->phase2.pubKey, 256);
|
||||
CryptoPP::SHA256().CalculateDigest(hxy, xy, 512);
|
||||
if (memcmp (hxy, m_Phase2.encrypted.hxy, 32))
|
||||
if (memcmp (hxy, m_Establisher->phase2.encrypted.hxy, 32))
|
||||
{
|
||||
LogPrint ("Incorrect hash");
|
||||
Terminate ();
|
||||
@ -250,22 +255,22 @@ namespace ntcp
|
||||
|
||||
void NTCPSession::SendPhase3 ()
|
||||
{
|
||||
m_Phase3.size = htons (sizeof (m_Phase3.ident));
|
||||
memcpy (&m_Phase3.ident, &i2p::context.GetRouterIdentity (), sizeof (m_Phase3.ident));
|
||||
m_Establisher->phase3.size = htons (i2p::data::DEFAULT_IDENTITY_SIZE);
|
||||
memcpy (&m_Establisher->phase3.ident, &i2p::context.GetRouterIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE);
|
||||
uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ());
|
||||
m_Phase3.timestamp = tsA;
|
||||
m_Establisher->phase3.timestamp = tsA;
|
||||
|
||||
SignedData s;
|
||||
memcpy (s.x, m_Phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Phase2.pubKey, 256);
|
||||
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
||||
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32);
|
||||
s.tsA = tsA;
|
||||
s.tsB = m_Phase2.encrypted.timestamp;
|
||||
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Phase3.signature);
|
||||
s.tsB = m_Establisher->phase2.encrypted.timestamp;
|
||||
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase3.signature);
|
||||
|
||||
m_Encryption.Encrypt((uint8_t *)&m_Phase3, sizeof(m_Phase3), (uint8_t *)&m_Phase3);
|
||||
m_Encryption.Encrypt((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3);
|
||||
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Phase3, sizeof (m_Phase3)), boost::asio::transfer_all (),
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase3, sizeof (NTCPPhase3)), boost::asio::transfer_all (),
|
||||
boost::bind(&NTCPSession::HandlePhase3Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsA));
|
||||
}
|
||||
|
||||
@ -279,7 +284,7 @@ namespace ntcp
|
||||
else
|
||||
{
|
||||
LogPrint ("Phase 3 sent: ", bytes_transferred);
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Phase4, sizeof (m_Phase4)),
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_Establisher->phase4, sizeof (NTCPPhase4)),
|
||||
boost::bind(&NTCPSession::HandlePhase4Received, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsA));
|
||||
}
|
||||
@ -295,20 +300,20 @@ namespace ntcp
|
||||
else
|
||||
{
|
||||
LogPrint ("Phase 3 received: ", bytes_transferred);
|
||||
m_Decryption.Decrypt ((uint8_t *)&m_Phase3, sizeof(m_Phase3), (uint8_t *)&m_Phase3);
|
||||
m_RemoteRouterInfo.SetRouterIdentity (m_Phase3.ident);
|
||||
m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3);
|
||||
m_RemoteRouterInfo.SetRouterIdentity (m_Establisher->phase3.ident);
|
||||
|
||||
SignedData s;
|
||||
memcpy (s.x, m_Phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Phase2.pubKey, 256);
|
||||
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
||||
memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32);
|
||||
s.tsA = m_Phase3.timestamp;
|
||||
s.tsA = m_Establisher->phase3.timestamp;
|
||||
s.tsB = tsB;
|
||||
|
||||
CryptoPP::DSA::PublicKey pubKey;
|
||||
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
|
||||
CryptoPP::DSA::Verifier verifier (pubKey);
|
||||
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Phase3.signature, 40))
|
||||
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature, 40))
|
||||
{
|
||||
LogPrint ("signature verification failed");
|
||||
Terminate ();
|
||||
@ -322,15 +327,15 @@ namespace ntcp
|
||||
void NTCPSession::SendPhase4 (uint32_t tsB)
|
||||
{
|
||||
SignedData s;
|
||||
memcpy (s.x, m_Phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Phase2.pubKey, 256);
|
||||
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
||||
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32);
|
||||
s.tsA = m_Phase3.timestamp;
|
||||
s.tsA = m_Establisher->phase3.timestamp;
|
||||
s.tsB = tsB;
|
||||
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Phase4.signature);
|
||||
m_Encryption.Encrypt ((uint8_t *)&m_Phase4, sizeof(m_Phase4), (uint8_t *)&m_Phase4);
|
||||
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase4.signature);
|
||||
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase4, sizeof(NTCPPhase4), (uint8_t *)&m_Establisher->phase4);
|
||||
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Phase4, sizeof (m_Phase4)), boost::asio::transfer_all (),
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase4, sizeof (NTCPPhase4)), boost::asio::transfer_all (),
|
||||
boost::bind(&NTCPSession::HandlePhase4Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
@ -362,20 +367,20 @@ namespace ntcp
|
||||
else
|
||||
{
|
||||
LogPrint ("Phase 4 received: ", bytes_transferred);
|
||||
m_Decryption.Decrypt((uint8_t *)&m_Phase4, sizeof(m_Phase4), (uint8_t *)&m_Phase4);
|
||||
m_Decryption.Decrypt((uint8_t *)&m_Establisher->phase4, sizeof(NTCPPhase4), (uint8_t *)&m_Establisher->phase4);
|
||||
|
||||
// verify signature
|
||||
SignedData s;
|
||||
memcpy (s.x, m_Phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Phase2.pubKey, 256);
|
||||
memcpy (s.x, m_Establisher->phase1.pubKey, 256);
|
||||
memcpy (s.y, m_Establisher->phase2.pubKey, 256);
|
||||
memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32);
|
||||
s.tsA = tsA;
|
||||
s.tsB = m_Phase2.encrypted.timestamp;
|
||||
s.tsB = m_Establisher->phase2.encrypted.timestamp;
|
||||
|
||||
CryptoPP::DSA::PublicKey pubKey;
|
||||
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
|
||||
CryptoPP::DSA::Verifier verifier (pubKey);
|
||||
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Phase4.signature, 40))
|
||||
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature, 40))
|
||||
{
|
||||
LogPrint ("signature verification failed");
|
||||
Terminate ();
|
||||
@ -391,7 +396,7 @@ namespace ntcp
|
||||
|
||||
void NTCPSession::Receive ()
|
||||
{
|
||||
m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, NTCP_MAX_MESSAGE_SIZE*2 -m_ReceiveBufferOffset),
|
||||
m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, NTCP_BUFFER_SIZE - m_ReceiveBufferOffset),
|
||||
boost::bind(&NTCPSession::HandleReceived, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ namespace ntcp
|
||||
#pragma pack()
|
||||
|
||||
const size_t NTCP_MAX_MESSAGE_SIZE = 16384;
|
||||
const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028)
|
||||
const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
|
||||
class NTCPSession
|
||||
{
|
||||
@ -133,13 +134,16 @@ namespace ntcp
|
||||
CryptoPP::Adler32 m_Adler;
|
||||
|
||||
i2p::data::RouterInfo& m_RemoteRouterInfo;
|
||||
|
||||
struct Establisher
|
||||
{
|
||||
NTCPPhase1 phase1;
|
||||
NTCPPhase2 phase2;
|
||||
NTCPPhase3 phase3;
|
||||
NTCPPhase4 phase4;
|
||||
} * m_Establisher;
|
||||
|
||||
NTCPPhase1 m_Phase1;
|
||||
NTCPPhase2 m_Phase2;
|
||||
NTCPPhase3 m_Phase3;
|
||||
NTCPPhase4 m_Phase4;
|
||||
|
||||
uint8_t m_ReceiveBuffer[NTCP_MAX_MESSAGE_SIZE*2], m_TimeSyncBuffer[16];
|
||||
uint8_t m_ReceiveBuffer[NTCP_BUFFER_SIZE], m_TimeSyncBuffer[16];
|
||||
int m_ReceiveBufferOffset;
|
||||
|
||||
i2p::I2NPMessage * m_NextMessage;
|
||||
|
Loading…
Reference in New Issue
Block a user