Skip to content

Commit 00c71dc

Browse files
committed
handle SessionConfirmed
1 parent 5218c85 commit 00c71dc

File tree

2 files changed

+101
-20
lines changed

2 files changed

+101
-20
lines changed

libi2pd/NTCP2.cpp

Lines changed: 96 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,17 @@ namespace transport
9898
MixKey (inputKeyMaterial, m_K);
9999
}
100100

101-
void NTCP2Establisher::KeyDerivationFunction3 (const uint8_t * staticPrivKey)
101+
void NTCP2Establisher::KDF3Alice ()
102102
{
103103
uint8_t inputKeyMaterial[32];
104-
i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), staticPrivKey, inputKeyMaterial, m_Ctx);
104+
i2p::crypto::GetEd25519 ()->ScalarMul (GetRemotePub (), i2p::context.GetNTCP2StaticPrivateKey (), inputKeyMaterial, m_Ctx);
105+
MixKey (inputKeyMaterial, m_K);
106+
}
107+
108+
void NTCP2Establisher::KDF3Bob ()
109+
{
110+
uint8_t inputKeyMaterial[32];
111+
i2p::crypto::GetEd25519 ()->ScalarMul (m_RemoteStaticKey, m_EphemeralPrivateKey, inputKeyMaterial, m_Ctx);
105112
MixKey (inputKeyMaterial, m_K);
106113
}
107114

@@ -204,7 +211,8 @@ namespace transport
204211
memset (options, 0, 16);
205212
options[1] = 2; // ver
206213
htobe16buf (options + 2, paddingLength); // padLen
207-
htobe16buf (options + 4, i2p::context.GetRouterInfo ().GetBufferLen () + 20); // m3p2Len (RI header + RI + MAC for now) TODO: implement options
214+
m_Establisher->m3p2Len = i2p::context.GetRouterInfo ().GetBufferLen () + 20; // (RI header + RI + MAC for now) TODO: implement options
215+
htobe16buf (options + 4, m_Establisher->m3p2Len);
208216
// 2 bytes reserved
209217
htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA
210218
// 4 bytes reserved
@@ -261,6 +269,7 @@ namespace transport
261269
{
262270
uint16_t paddingLen = bufbe16toh (options + 2);
263271
m_SessionRequestBufferLen = paddingLen + 64;
272+
m_Establisher->m3p2Len = bufbe16toh (options + 4);
264273
// TODO: check tsA
265274
if (paddingLen > 0)
266275
boost::asio::async_read (m_Socket, boost::asio::buffer(m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (),
@@ -315,7 +324,8 @@ namespace transport
315324
// fill padding
316325
RAND_bytes (m_SessionCreatedBuffer + 56, paddingLen);
317326
// send message
318-
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionCreatedBuffer, paddingLen + 64), boost::asio::transfer_all (),
327+
m_SessionCreatedBufferLen = paddingLen + 64;
328+
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionCreatedBuffer, m_SessionCreatedBufferLen), boost::asio::transfer_all (),
319329
std::bind(&NTCP2Session::HandleSessionCreatedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
320330
}
321331

@@ -403,32 +413,36 @@ namespace transport
403413
memcpy (h + 32, m_SessionConfirmedBuffer, 48);
404414
SHA256 (h, 80, m_Establisher->m_H);
405415

406-
size_t m3p2Len = i2p::context.GetRouterInfo ().GetBufferLen () + 20;
407-
std::vector<uint8_t> buf(m3p2Len - 16);
416+
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
408417
buf[0] = 2; // block
409418
htobe16buf (buf.data () + 1, i2p::context.GetRouterInfo ().GetBufferLen () + 1); // flag + RI
410419
buf[3] = 0; // flag
411420
memcpy (buf.data () + 4, i2p::context.GetRouterInfo ().GetBuffer (), i2p::context.GetRouterInfo ().GetBufferLen ());
412-
m_Establisher->KeyDerivationFunction3 (i2p::context.GetNTCP2StaticPrivateKey ());
421+
m_Establisher->KDF3Alice ();
413422
memset (nonce, 0, 12); // set nonce to 0 again
414-
i2p::crypto::AEADChaCha20Poly1305 (buf.data (), m3p2Len - 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, m_SessionConfirmedBuffer + 48, m3p2Len, true); // encrypt
423+
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
415424
uint8_t tmp[48];
416425
memcpy (tmp, m_SessionConfirmedBuffer, 48);
417426
memcpy (m_SessionConfirmedBuffer + 16, m_Establisher->GetH (), 32); // h || ciphertext
418-
SHA256 (m_SessionConfirmedBuffer + 16, m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
427+
SHA256 (m_SessionConfirmedBuffer + 16, m_Establisher->m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
419428
memcpy (m_SessionConfirmedBuffer, tmp, 48);
420429

421430
// send message
422-
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionConfirmedBuffer, m3p2Len + 48), boost::asio::transfer_all (),
431+
boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (),
423432
std::bind(&NTCP2Session::HandleSessionConfirmedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
424433
}
425434

426435
void NTCP2Session::HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
427436
{
428437
LogPrint (eLogDebug, "NTCP2: SessionConfirmed sent");
429438
KeyDerivationFunctionDataPhase ();
430-
memcpy (m_ReceiveIV, m_Sipkeysba + 16, 8); //Alice
431-
memcpy (m_SendIV, m_Sipkeysab + 16, 8); //Alice
439+
// Alice
440+
m_SendKey = m_Kab;
441+
m_ReceiveKey = m_Kba;
442+
m_SendSipKey = m_Sipkeysab;
443+
m_ReceiveSipKey = m_Sipkeysba;
444+
memcpy (m_ReceiveIV, m_Sipkeysba + 16, 8);
445+
memcpy (m_SendIV, m_Sipkeysab + 16, 8);
432446
ReceiveLength ();
433447

434448
// TODO: remove
@@ -442,8 +456,72 @@ namespace transport
442456

443457
void NTCP2Session::HandleSessionCreatedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
444458
{
445-
LogPrint (eLogDebug, "NTCP2: SessionCreated sent");
446-
Terminate (); // TODO
459+
(void) bytes_transferred;
460+
if (ecode)
461+
{
462+
LogPrint (eLogWarning, "NTCP2: couldn't send SessionCreated message: ", ecode.message ());
463+
Terminate ();
464+
}
465+
else
466+
{
467+
LogPrint (eLogDebug, "NTCP2: SessionCreated sent");
468+
m_SessionConfirmedBuffer = new uint8_t[m_Establisher->m3p2Len + 48];
469+
boost::asio::async_read (m_Socket, boost::asio::buffer(m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (),
470+
std::bind(&NTCP2Session::HandleSessionConfirmedReceived , shared_from_this (), std::placeholders::_1, std::placeholders::_2));
471+
}
472+
}
473+
474+
void NTCP2Session::HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
475+
{
476+
if (ecode)
477+
{
478+
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part 1 read error: ", ecode.message ());
479+
Terminate ();
480+
}
481+
else
482+
{
483+
LogPrint (eLogDebug, "NTCP2: SessionConfirmed Part 1 received");
484+
// update AD
485+
uint8_t h[80];
486+
memcpy (h, m_Establisher->GetH (), 32);
487+
memcpy (h + 32, m_SessionCreatedBuffer + 32, 32); // encrypted payload
488+
SHA256 (h, 64, h);
489+
int paddingLength = m_SessionCreatedBufferLen - 64;
490+
if (paddingLength > 0)
491+
{
492+
SHA256_CTX ctx;
493+
SHA256_Init (&ctx);
494+
SHA256_Update (&ctx, h, 32);
495+
SHA256_Update (&ctx, m_SessionCreatedBuffer + 64, paddingLength);
496+
SHA256_Final (h, &ctx);
497+
}
498+
// part 1
499+
uint8_t nonce[12];
500+
CreateNonce (1, nonce);
501+
i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 48, h, 32, m_Establisher->GetK (), nonce, m_Establisher->m_RemoteStaticKey, 32, false); // decrypt S
502+
// part 2
503+
// update AD again
504+
memcpy (h + 32, m_SessionConfirmedBuffer, 48);
505+
SHA256 (h, 80, m_Establisher->m_H);
506+
507+
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
508+
m_Establisher->KDF3Bob ();
509+
memset (nonce, 0, 12); // set nonce to 0 again
510+
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
511+
// TODO: process RI and options
512+
// caclulate new h again for KDF data
513+
memcpy (m_SessionConfirmedBuffer + 16, m_Establisher->GetH (), 32); // h || ciphertext
514+
SHA256 (m_SessionConfirmedBuffer + 16, m_Establisher->m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
515+
KeyDerivationFunctionDataPhase ();
516+
// Bob
517+
m_SendKey = m_Kba;
518+
m_ReceiveKey = m_Kab;
519+
m_SendSipKey = m_Sipkeysba;
520+
m_ReceiveSipKey = m_Sipkeysab;
521+
memcpy (m_ReceiveIV, m_Sipkeysab + 16, 8);
522+
memcpy (m_SendIV, m_Sipkeysba + 16, 8);
523+
ReceiveLength ();
524+
}
447525
}
448526

449527
void NTCP2Session::ClientLogin ()
@@ -474,7 +552,7 @@ namespace transport
474552
}
475553
else
476554
{
477-
i2p::crypto::Siphash<8> (m_ReceiveIV, m_ReceiveIV, 8, m_Sipkeysba); // assume Alice TODO:
555+
i2p::crypto::Siphash<8> (m_ReceiveIV, m_ReceiveIV, 8, m_ReceiveSipKey);
478556
m_NextReceivedLen = be16toh (m_NextReceivedLen ^ bufbe16toh(m_ReceiveIV));
479557
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
480558
delete[] m_NextReceivedBuffer;
@@ -501,7 +579,7 @@ namespace transport
501579
uint8_t nonce[12];
502580
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
503581
uint8_t * decrypted = new uint8_t[m_NextReceivedLen];
504-
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_Kba, nonce, decrypted, m_NextReceivedLen, false)) // decrypt. assume Alice TODO:
582+
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, decrypted, m_NextReceivedLen, false))
505583
{
506584
LogPrint (eLogInfo, "NTCP2: received message decrypted");
507585
ProcessNextFrame (decrypted, m_NextReceivedLen-16);
@@ -540,8 +618,8 @@ namespace transport
540618
uint8_t nonce[12];
541619
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
542620
m_NextSendBuffer = new uint8_t[len + 16 + 2];
543-
i2p::crypto::AEADChaCha20Poly1305 (payload, len, nullptr, 0, m_Kab, nonce, m_NextSendBuffer + 2, len + 16, true); // encrypt. assume Alice TODO:
544-
i2p::crypto::Siphash<8> (m_SendIV, m_SendIV, 8, m_Sipkeysab); // assume Alice TODO:
621+
i2p::crypto::AEADChaCha20Poly1305 (payload, len, nullptr, 0, m_SendKey, nonce, m_NextSendBuffer + 2, len + 16, true);
622+
i2p::crypto::Siphash<8> (m_SendIV, m_SendIV, 8, m_SendSipKey);
545623
htobuf16 (m_NextSendBuffer, bufbe16toh (m_SendIV) ^ htobe16(len + 16));
546624
LogPrint (eLogDebug, "NTCP2: sent length ", len + 16);
547625

libi2pd/NTCP2.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ namespace transport
3333
void MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived);
3434
void KeyDerivationFunction1 (const uint8_t * rs, const uint8_t * priv, const uint8_t * pub); // for SessionRequest
3535
void KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen); // for SessionCreate
36-
void KeyDerivationFunction3 (const uint8_t * staticPrivKey); // for SessionConfirmed part 2
36+
void KDF3Alice (); // for SessionConfirmed part 2
37+
void KDF3Bob ();
3738
void CreateEphemeralKey ();
3839

3940

4041
BN_CTX * m_Ctx;
4142
uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], m_RemoteEphemeralPublicKey[32]; // x25519
4243
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/;
43-
44+
uint16_t m3p2Len;
4445
};
4546

4647
class NTCP2Server;
@@ -76,6 +77,7 @@ namespace transport
7677
void HandleSessionCreatedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
7778
void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
7879
void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
80+
void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
7981

8082
// data
8183
void ReceiveLength ();
@@ -98,6 +100,7 @@ namespace transport
98100
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
99101
// data phase
100102
uint8_t m_Kab[33], m_Kba[32], m_Sipkeysab[33], m_Sipkeysba[32];
103+
const uint8_t * m_SendKey, * m_ReceiveKey, * m_SendSipKey, * m_ReceiveSipKey;
101104
uint16_t m_NextReceivedLen;
102105
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
103106
uint8_t m_ReceiveIV[8], m_SendIV[8];

0 commit comments

Comments
 (0)