@@ -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
0 commit comments