reduced memory usage

pull/97/head
orignal 10 years ago
parent c8cdeead44
commit 6069055c9e

@ -25,10 +25,12 @@ namespace ntcp
m_NumSentBytes (0), m_NumReceivedBytes (0) m_NumSentBytes (0), m_NumReceivedBytes (0)
{ {
m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
m_Establisher = new Establisher;
} }
NTCPSession::~NTCPSession () NTCPSession::~NTCPSession ()
{ {
delete m_Establisher;
delete m_DHKeysPair; delete m_DHKeysPair;
if (m_NextMessage) if (m_NextMessage)
i2p::DeleteI2NPMessage (m_NextMessage); i2p::DeleteI2NPMessage (m_NextMessage);
@ -95,6 +97,9 @@ namespace ntcp
LogPrint ("NTCP session connected"); LogPrint ("NTCP session connected");
m_IsEstablished = true; m_IsEstablished = true;
delete m_Establisher;
m_Establisher = nullptr;
SendTimeSyncMessage (); SendTimeSyncMessage ();
SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are
@ -110,20 +115,20 @@ namespace ntcp
{ {
// send Phase1 // send Phase1
const uint8_t * x = m_DHKeysPair->publicKey; const uint8_t * x = m_DHKeysPair->publicKey;
memcpy (m_Phase1.pubKey, x, 256); memcpy (m_Establisher->phase1.pubKey, x, 256);
CryptoPP::SHA256().CalculateDigest(m_Phase1.HXxorHI, x, 256); CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256);
const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash (); const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash ();
for (int i = 0; i < 32; i++) 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)); boost::bind(&NTCPSession::HandlePhase1Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
} }
void NTCPSession::ServerLogin () void NTCPSession::ServerLogin ()
{ {
// receive Phase1 // 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::bind(&NTCPSession::HandlePhase1Received, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
} }
@ -138,7 +143,7 @@ namespace ntcp
else else
{ {
LogPrint ("Phase 1 sent: ", bytes_transferred); 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::bind(&NTCPSession::HandlePhase2Received, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
} }
@ -156,11 +161,11 @@ namespace ntcp
LogPrint ("Phase 1 received: ", bytes_transferred); LogPrint ("Phase 1 received: ", bytes_transferred);
// verify ident // verify ident
uint8_t digest[32]; 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 (); const uint8_t * ident = i2p::context.GetRouterInfo ().GetIdentHash ();
for (int i = 0; i < 32; i++) 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"); LogPrint ("Wrong ident");
Terminate (); Terminate ();
@ -175,24 +180,24 @@ namespace ntcp
void NTCPSession::SendPhase2 () void NTCPSession::SendPhase2 ()
{ {
const uint8_t * y = m_DHKeysPair->publicKey; const uint8_t * y = m_DHKeysPair->publicKey;
memcpy (m_Phase2.pubKey, y, 256); memcpy (m_Establisher->phase2.pubKey, y, 256);
uint8_t xy[512]; uint8_t xy[512];
memcpy (xy, m_Phase1.pubKey, 256); memcpy (xy, m_Establisher->phase1.pubKey, 256);
memcpy (xy + 256, y, 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 ()); uint32_t tsB = htobe32 (i2p::util::GetSecondsSinceEpoch ());
m_Phase2.encrypted.timestamp = tsB; m_Establisher->phase2.encrypted.timestamp = tsB;
// TODO: fill filler // TODO: fill filler
uint8_t aesKey[32]; uint8_t aesKey[32];
CreateAESKey (m_Phase1.pubKey, aesKey); CreateAESKey (m_Establisher->phase1.pubKey, aesKey);
m_Encryption.SetKey (aesKey); m_Encryption.SetKey (aesKey);
m_Encryption.SetIV (y + 240); m_Encryption.SetIV (y + 240);
m_Decryption.SetKey (aesKey); 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); 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_Phase2, sizeof (m_Phase2)), boost::asio::transfer_all (), 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)); boost::bind(&NTCPSession::HandlePhase2Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsB));
} }
@ -207,7 +212,7 @@ namespace ntcp
else else
{ {
LogPrint ("Phase 2 sent: ", bytes_transferred); 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::bind(&NTCPSession::HandlePhase3Received, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsB)); boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsB));
} }
@ -226,19 +231,19 @@ namespace ntcp
LogPrint ("Phase 2 received: ", bytes_transferred); LogPrint ("Phase 2 received: ", bytes_transferred);
uint8_t aesKey[32]; uint8_t aesKey[32];
CreateAESKey (m_Phase2.pubKey, aesKey); CreateAESKey (m_Establisher->phase2.pubKey, aesKey);
m_Decryption.SetKey (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.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 // verify
uint8_t xy[512], hxy[32]; uint8_t xy[512], hxy[32];
memcpy (xy, m_DHKeysPair->publicKey, 256); 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); 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"); LogPrint ("Incorrect hash");
Terminate (); Terminate ();
@ -250,22 +255,22 @@ namespace ntcp
void NTCPSession::SendPhase3 () void NTCPSession::SendPhase3 ()
{ {
m_Phase3.size = htons (sizeof (m_Phase3.ident)); m_Establisher->phase3.size = htons (i2p::data::DEFAULT_IDENTITY_SIZE);
memcpy (&m_Phase3.ident, &i2p::context.GetRouterIdentity (), sizeof (m_Phase3.ident)); memcpy (&m_Establisher->phase3.ident, &i2p::context.GetRouterIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE);
uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ()); uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ());
m_Phase3.timestamp = tsA; m_Establisher->phase3.timestamp = tsA;
SignedData s; SignedData s;
memcpy (s.x, m_Phase1.pubKey, 256); memcpy (s.x, m_Establisher->phase1.pubKey, 256);
memcpy (s.y, m_Phase2.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256);
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32); memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32);
s.tsA = tsA; s.tsA = tsA;
s.tsB = m_Phase2.encrypted.timestamp; s.tsB = m_Establisher->phase2.encrypted.timestamp;
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Phase3.signature); 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)); boost::bind(&NTCPSession::HandlePhase3Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsA));
} }
@ -279,7 +284,7 @@ namespace ntcp
else else
{ {
LogPrint ("Phase 3 sent: ", bytes_transferred); 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::bind(&NTCPSession::HandlePhase4Received, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsA)); boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsA));
} }
@ -295,20 +300,20 @@ namespace ntcp
else else
{ {
LogPrint ("Phase 3 received: ", bytes_transferred); LogPrint ("Phase 3 received: ", bytes_transferred);
m_Decryption.Decrypt ((uint8_t *)&m_Phase3, sizeof(m_Phase3), (uint8_t *)&m_Phase3); m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3);
m_RemoteRouterInfo.SetRouterIdentity (m_Phase3.ident); m_RemoteRouterInfo.SetRouterIdentity (m_Establisher->phase3.ident);
SignedData s; SignedData s;
memcpy (s.x, m_Phase1.pubKey, 256); memcpy (s.x, m_Establisher->phase1.pubKey, 256);
memcpy (s.y, m_Phase2.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256);
memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32); memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32);
s.tsA = m_Phase3.timestamp; s.tsA = m_Establisher->phase3.timestamp;
s.tsB = tsB; s.tsB = tsB;
CryptoPP::DSA::PublicKey pubKey; CryptoPP::DSA::PublicKey pubKey;
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128)); pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
CryptoPP::DSA::Verifier verifier (pubKey); 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"); LogPrint ("signature verification failed");
Terminate (); Terminate ();
@ -322,15 +327,15 @@ namespace ntcp
void NTCPSession::SendPhase4 (uint32_t tsB) void NTCPSession::SendPhase4 (uint32_t tsB)
{ {
SignedData s; SignedData s;
memcpy (s.x, m_Phase1.pubKey, 256); memcpy (s.x, m_Establisher->phase1.pubKey, 256);
memcpy (s.y, m_Phase2.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256);
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32); memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32);
s.tsA = m_Phase3.timestamp; s.tsA = m_Establisher->phase3.timestamp;
s.tsB = tsB; s.tsB = tsB;
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Phase4.signature); i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase4.signature);
m_Encryption.Encrypt ((uint8_t *)&m_Phase4, sizeof(m_Phase4), (uint8_t *)&m_Phase4); 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)); boost::bind(&NTCPSession::HandlePhase4Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
} }
@ -362,20 +367,20 @@ namespace ntcp
else else
{ {
LogPrint ("Phase 4 received: ", bytes_transferred); 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 // verify signature
SignedData s; SignedData s;
memcpy (s.x, m_Phase1.pubKey, 256); memcpy (s.x, m_Establisher->phase1.pubKey, 256);
memcpy (s.y, m_Phase2.pubKey, 256); memcpy (s.y, m_Establisher->phase2.pubKey, 256);
memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32); memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32);
s.tsA = tsA; s.tsA = tsA;
s.tsB = m_Phase2.encrypted.timestamp; s.tsB = m_Establisher->phase2.encrypted.timestamp;
CryptoPP::DSA::PublicKey pubKey; CryptoPP::DSA::PublicKey pubKey;
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128)); pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
CryptoPP::DSA::Verifier verifier (pubKey); 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"); LogPrint ("signature verification failed");
Terminate (); Terminate ();
@ -391,7 +396,7 @@ namespace ntcp
void NTCPSession::Receive () 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::bind(&NTCPSession::HandleReceived, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
} }

@ -63,6 +63,7 @@ namespace ntcp
#pragma pack() #pragma pack()
const size_t NTCP_MAX_MESSAGE_SIZE = 16384; 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 const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
class NTCPSession class NTCPSession
{ {
@ -133,13 +134,16 @@ namespace ntcp
CryptoPP::Adler32 m_Adler; CryptoPP::Adler32 m_Adler;
i2p::data::RouterInfo& m_RemoteRouterInfo; i2p::data::RouterInfo& m_RemoteRouterInfo;
struct Establisher
{
NTCPPhase1 phase1;
NTCPPhase2 phase2;
NTCPPhase3 phase3;
NTCPPhase4 phase4;
} * m_Establisher;
NTCPPhase1 m_Phase1; uint8_t m_ReceiveBuffer[NTCP_BUFFER_SIZE], m_TimeSyncBuffer[16];
NTCPPhase2 m_Phase2;
NTCPPhase3 m_Phase3;
NTCPPhase4 m_Phase4;
uint8_t m_ReceiveBuffer[NTCP_MAX_MESSAGE_SIZE*2], m_TimeSyncBuffer[16];
int m_ReceiveBufferOffset; int m_ReceiveBufferOffset;
i2p::I2NPMessage * m_NextMessage; i2p::I2NPMessage * m_NextMessage;

Loading…
Cancel
Save