handle SessionConfirmed

pull/1212/head
orignal 6 years ago
parent 5218c8584f
commit 00c71dc26a

@ -98,10 +98,17 @@ namespace transport
MixKey (inputKeyMaterial, m_K);
}
void NTCP2Establisher::KeyDerivationFunction3 (const uint8_t * staticPrivKey)
void NTCP2Establisher::KDF3Alice ()
{
uint8_t inputKeyMaterial[32];
i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), staticPrivKey, inputKeyMaterial, m_Ctx);
i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), i2p::context.GetNTCP2StaticPrivateKey (), inputKeyMaterial, m_Ctx);
MixKey (inputKeyMaterial, m_K);
}
void NTCP2Establisher::KDF3Bob ()
{
uint8_t inputKeyMaterial[32];
i2p::crypto::GetEd25519 ()->ScalarMul (m_RemoteStaticKey, m_EphemeralPrivateKey, inputKeyMaterial, m_Ctx);
MixKey (inputKeyMaterial, m_K);
}
@ -204,7 +211,8 @@ namespace transport
memset (options, 0, 16);
options[1] = 2; // ver
htobe16buf (options + 2, paddingLength); // padLen
htobe16buf (options + 4, i2p::context.GetRouterInfo ().GetBufferLen () + 20); // m3p2Len (RI header + RI + MAC for now) TODO: implement options
m_Establisher->m3p2Len = i2p::context.GetRouterInfo ().GetBufferLen () + 20; // (RI header + RI + MAC for now) TODO: implement options
htobe16buf (options + 4, m_Establisher->m3p2Len);
// 2 bytes reserved
htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA
// 4 bytes reserved
@ -261,6 +269,7 @@ namespace transport
{
uint16_t paddingLen = bufbe16toh (options + 2);
m_SessionRequestBufferLen = paddingLen + 64;
m_Establisher->m3p2Len = bufbe16toh (options + 4);
// TODO: check tsA
if (paddingLen > 0)
boost::asio::async_read (m_Socket, boost::asio::buffer(m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (),
@ -315,7 +324,8 @@ namespace transport
// fill padding
RAND_bytes (m_SessionCreatedBuffer + 56, paddingLen);
// send message
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionCreatedBuffer, paddingLen + 64), boost::asio::transfer_all (),
m_SessionCreatedBufferLen = paddingLen + 64;
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionCreatedBuffer, m_SessionCreatedBufferLen), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionCreatedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
}
@ -403,23 +413,22 @@ namespace transport
memcpy (h + 32, m_SessionConfirmedBuffer, 48);
SHA256 (h, 80, m_Establisher->m_H);
size_t m3p2Len = i2p::context.GetRouterInfo ().GetBufferLen () + 20;
std::vector<uint8_t> buf(m3p2Len - 16);
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
buf[0] = 2; // block
htobe16buf (buf.data () + 1, i2p::context.GetRouterInfo ().GetBufferLen () + 1); // flag + RI
buf[3] = 0; // flag
memcpy (buf.data () + 4, i2p::context.GetRouterInfo ().GetBuffer (), i2p::context.GetRouterInfo ().GetBufferLen ());
m_Establisher->KeyDerivationFunction3 (i2p::context.GetNTCP2StaticPrivateKey ());
m_Establisher->KDF3Alice ();
memset (nonce, 0, 12); // set nonce to 0 again
i2p::crypto::AEADChaCha20Poly1305 (buf.data (), m3p2Len - 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, m_SessionConfirmedBuffer + 48, m3p2Len, true); // encrypt
i2p::crypto::AEADChaCha20Poly1305 (buf.data (), m_Establisher->m3p2Len - 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, m_SessionConfirmedBuffer + 48, m_Establisher->m3p2Len, true); // encrypt
uint8_t tmp[48];
memcpy (tmp, m_SessionConfirmedBuffer, 48);
memcpy (m_SessionConfirmedBuffer + 16, m_Establisher->GetH (), 32); // h || ciphertext
SHA256 (m_SessionConfirmedBuffer + 16, m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
SHA256 (m_SessionConfirmedBuffer + 16, m_Establisher->m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
memcpy (m_SessionConfirmedBuffer, tmp, 48);
// send message
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionConfirmedBuffer, m3p2Len + 48), boost::asio::transfer_all (),
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionConfirmedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
}
@ -427,8 +436,13 @@ namespace transport
{
LogPrint (eLogDebug, "NTCP2: SessionConfirmed sent");
KeyDerivationFunctionDataPhase ();
memcpy (m_ReceiveIV, m_Sipkeysba + 16, 8); //Alice
memcpy (m_SendIV, m_Sipkeysab + 16, 8); //Alice
// Alice
m_SendKey = m_Kab;
m_ReceiveKey = m_Kba;
m_SendSipKey = m_Sipkeysab;
m_ReceiveSipKey = m_Sipkeysba;
memcpy (m_ReceiveIV, m_Sipkeysba + 16, 8);
memcpy (m_SendIV, m_Sipkeysab + 16, 8);
ReceiveLength ();
// TODO: remove
@ -442,8 +456,72 @@ namespace transport
void NTCP2Session::HandleSessionCreatedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
LogPrint (eLogDebug, "NTCP2: SessionCreated sent");
Terminate (); // TODO
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogWarning, "NTCP2: couldn't send SessionCreated message: ", ecode.message ());
Terminate ();
}
else
{
LogPrint (eLogDebug, "NTCP2: SessionCreated sent");
m_SessionConfirmedBuffer = new uint8_t[m_Establisher->m3p2Len + 48];
boost::asio::async_read (m_Socket, boost::asio::buffer(m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionConfirmedReceived , shared_from_this (), std::placeholders::_1, std::placeholders::_2));
}
}
void NTCP2Session::HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if (ecode)
{
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part 1 read error: ", ecode.message ());
Terminate ();
}
else
{
LogPrint (eLogDebug, "NTCP2: SessionConfirmed Part 1 received");
// update AD
uint8_t h[80];
memcpy (h, m_Establisher->GetH (), 32);
memcpy (h + 32, m_SessionCreatedBuffer + 32, 32); // encrypted payload
SHA256 (h, 64, h);
int paddingLength = m_SessionCreatedBufferLen - 64;
if (paddingLength > 0)
{
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, h, 32);
SHA256_Update (&ctx, m_SessionCreatedBuffer + 64, paddingLength);
SHA256_Final (h, &ctx);
}
// part 1
uint8_t nonce[12];
CreateNonce (1, nonce);
i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 48, h, 32, m_Establisher->GetK (), nonce, m_Establisher->m_RemoteStaticKey, 32, false); // decrypt S
// part 2
// update AD again
memcpy (h + 32, m_SessionConfirmedBuffer, 48);
SHA256 (h, 80, m_Establisher->m_H);
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
m_Establisher->KDF3Bob ();
memset (nonce, 0, 12); // set nonce to 0 again
i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m_Establisher->m3p2Len, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, buf.data (), m_Establisher->m3p2Len - 16, false); // decrypt
// TODO: process RI and options
// caclulate new h again for KDF data
memcpy (m_SessionConfirmedBuffer + 16, m_Establisher->GetH (), 32); // h || ciphertext
SHA256 (m_SessionConfirmedBuffer + 16, m_Establisher->m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
KeyDerivationFunctionDataPhase ();
// Bob
m_SendKey = m_Kba;
m_ReceiveKey = m_Kab;
m_SendSipKey = m_Sipkeysba;
m_ReceiveSipKey = m_Sipkeysab;
memcpy (m_ReceiveIV, m_Sipkeysab + 16, 8);
memcpy (m_SendIV, m_Sipkeysba + 16, 8);
ReceiveLength ();
}
}
void NTCP2Session::ClientLogin ()
@ -474,7 +552,7 @@ namespace transport
}
else
{
i2p::crypto::Siphash<8> (m_ReceiveIV, m_ReceiveIV, 8, m_Sipkeysba); // assume Alice TODO:
i2p::crypto::Siphash<8> (m_ReceiveIV, m_ReceiveIV, 8, m_ReceiveSipKey);
m_NextReceivedLen = be16toh (m_NextReceivedLen ^ bufbe16toh(m_ReceiveIV));
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
delete[] m_NextReceivedBuffer;
@ -501,7 +579,7 @@ namespace transport
uint8_t nonce[12];
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
uint8_t * decrypted = new uint8_t[m_NextReceivedLen];
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_Kba, nonce, decrypted, m_NextReceivedLen, false)) // decrypt. assume Alice TODO:
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, decrypted, m_NextReceivedLen, false))
{
LogPrint (eLogInfo, "NTCP2: received message decrypted");
ProcessNextFrame (decrypted, m_NextReceivedLen-16);
@ -540,8 +618,8 @@ namespace transport
uint8_t nonce[12];
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
m_NextSendBuffer = new uint8_t[len + 16 + 2];
i2p::crypto::AEADChaCha20Poly1305 (payload, len, nullptr, 0, m_Kab, nonce, m_NextSendBuffer + 2, len + 16, true); // encrypt. assume Alice TODO:
i2p::crypto::Siphash<8> (m_SendIV, m_SendIV, 8, m_Sipkeysab); // assume Alice TODO:
i2p::crypto::AEADChaCha20Poly1305 (payload, len, nullptr, 0, m_SendKey, nonce, m_NextSendBuffer + 2, len + 16, true);
i2p::crypto::Siphash<8> (m_SendIV, m_SendIV, 8, m_SendSipKey);
htobuf16 (m_NextSendBuffer, bufbe16toh (m_SendIV) ^ htobe16(len + 16));
LogPrint (eLogDebug, "NTCP2: sent length ", len + 16);

@ -33,14 +33,15 @@ namespace transport
void MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived);
void KeyDerivationFunction1 (const uint8_t * rs, const uint8_t * priv, const uint8_t * pub); // for SessionRequest
void KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen); // for SessionCreate
void KeyDerivationFunction3 (const uint8_t * staticPrivKey); // for SessionConfirmed part 2
void KDF3Alice (); // for SessionConfirmed part 2
void KDF3Bob ();
void CreateEphemeralKey ();
BN_CTX * m_Ctx;
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*/;
uint16_t m3p2Len;
};
class NTCP2Server;
@ -76,6 +77,7 @@ namespace transport
void HandleSessionCreatedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
// data
void ReceiveLength ();
@ -98,6 +100,7 @@ namespace transport
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
// data phase
uint8_t m_Kab[33], m_Kba[32], m_Sipkeysab[33], m_Sipkeysba[32];
const uint8_t * m_SendKey, * m_ReceiveKey, * m_SendSipKey, * m_ReceiveSipKey;
uint16_t m_NextReceivedLen;
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
uint8_t m_ReceiveIV[8], m_SendIV[8];

Loading…
Cancel
Save