Browse Source

calculate shared key in separate thread for incoming connection

pull/660/merge
orignal 8 years ago
parent
commit
a746f5657f
  1. 45
      NTCPSession.cpp
  2. 4
      NTCPSession.h

45
NTCPSession.cpp

@ -36,12 +36,12 @@ namespace transport
delete m_Establisher; delete m_Establisher;
} }
void NTCPSession::CreateAESKey (uint8_t * pubKey, i2p::crypto::AESKey& key) void NTCPSession::CreateAESKey (uint8_t * pubKey)
{ {
uint8_t sharedKey[256]; uint8_t sharedKey[256];
m_DHKeysPair->Agree (pubKey, sharedKey); // time consuming operation m_DHKeysPair->Agree (pubKey, sharedKey); // time consuming operation
uint8_t * aesKey = key; i2p::crypto::AESKey aesKey;
if (sharedKey[0] & 0x80) if (sharedKey[0] & 0x80)
{ {
aesKey[0] = 0; aesKey[0] = 0;
@ -64,6 +64,9 @@ namespace transport
} }
memcpy (aesKey, nonZero, 32); memcpy (aesKey, nonZero, 32);
} }
m_Decryption.SetKey (aesKey);
m_Encryption.SetKey (aesKey);
} }
void NTCPSession::Done () void NTCPSession::Done ()
@ -164,15 +167,25 @@ namespace transport
return; return;
} }
} }
SendPhase2 (); // TODO: check for number of pending keys
auto s = shared_from_this ();
auto keyCreated = std::async (std::launch::async, [s] ()
{
if (!s->m_DHKeysPair)
s->m_DHKeysPair = transports.GetNextDHKeysPair ();
s->CreateAESKey (s->m_Establisher->phase1.pubKey);
}).share ();
m_Server.GetService ().post ([s, keyCreated]()
{
keyCreated.get ();
s->SendPhase2 ();
});
} }
} }
void NTCPSession::SendPhase2 () void NTCPSession::SendPhase2 ()
{ {
if (!m_DHKeysPair)
m_DHKeysPair = transports.GetNextDHKeysPair ();
const uint8_t * y = m_DHKeysPair->GetPublicKey (); const uint8_t * y = m_DHKeysPair->GetPublicKey ();
memcpy (m_Establisher->phase2.pubKey, y, 256); memcpy (m_Establisher->phase2.pubKey, y, 256);
uint8_t xy[512]; uint8_t xy[512];
@ -183,11 +196,7 @@ namespace transport
memcpy (m_Establisher->phase2.encrypted.timestamp, &tsB, 4); memcpy (m_Establisher->phase2.encrypted.timestamp, &tsB, 4);
RAND_bytes (m_Establisher->phase2.encrypted.filler, 12); RAND_bytes (m_Establisher->phase2.encrypted.filler, 12);
i2p::crypto::AESKey aesKey;
CreateAESKey (m_Establisher->phase1.pubKey, aesKey);
m_Encryption.SetKey (aesKey);
m_Encryption.SetIV (y + 240); m_Encryption.SetIV (y + 240);
m_Decryption.SetKey (aesKey);
m_Decryption.SetIV (m_Establisher->phase1.HXxorHI + 16); m_Decryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted); m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
@ -232,26 +241,22 @@ namespace transport
{ {
auto s = shared_from_this (); auto s = shared_from_this ();
// create AES key in separate thread // create AES key in separate thread
auto createKey = std::async (std::launch::async, [s] ()->i2p::crypto::AESKey auto keyCreated = std::async (std::launch::async, [s] ()
{ {
i2p::crypto::AESKey aesKey; s->CreateAESKey (s->m_Establisher->phase2.pubKey);
s->CreateAESKey (s->m_Establisher->phase2.pubKey, aesKey);
return std::move (aesKey);
}).share (); // TODO: use move capture in C++ 14 instead shared_future }).share (); // TODO: use move capture in C++ 14 instead shared_future
// let other operations execute while a key gets created // let other operations execute while a key gets created
m_Server.GetService ().post ([s, createKey]() m_Server.GetService ().post ([s, keyCreated]()
{ {
auto aesKey = createKey.get (); // we might wait if no more pending operations keyCreated.get (); // we might wait if no more pending operations
s->HandlePhase2 (aesKey); s->HandlePhase2 ();
}); });
} }
} }
void NTCPSession::HandlePhase2 (const i2p::crypto::AESKey& aesKey) void NTCPSession::HandlePhase2 ()
{ {
m_Decryption.SetKey (aesKey);
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240); m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
m_Encryption.SetKey (aesKey);
m_Encryption.SetIV (m_Establisher->phase1.HXxorHI + 16); m_Encryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
m_Decryption.Decrypt((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted); m_Decryption.Decrypt((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);

4
NTCPSession.h

@ -67,13 +67,13 @@ namespace transport
void SendTimeSyncMessage (); void SendTimeSyncMessage ();
void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; } void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
void CreateAESKey (uint8_t * pubKey, i2p::crypto::AESKey& key); void CreateAESKey (uint8_t * pubKey);
// client // client
void SendPhase3 (); void SendPhase3 ();
void HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandlePhase2 (const i2p::crypto::AESKey& aesKey); void HandlePhase2 ();
void HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA); void HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
void HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA); void HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);

Loading…
Cancel
Save