diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 8ae621d7..f01573e4 100644 --- a/NTCPSession.cpp +++ b/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)); } diff --git a/NTCPSession.h b/NTCPSession.h index 1d03708b..2ebe6b5f 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -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;