@ -41,7 +41,7 @@ namespace transport
HMAC ( EVP_sha256 ( ) , tempKey , 32 , m_CK , 33 , derived , & len ) ;
HMAC ( EVP_sha256 ( ) , tempKey , 32 , m_CK , 33 , derived , & len ) ;
}
}
void NTCP2Establisher : : KeyDerivationFunction1 ( const uint8_t * rs , const uint8_t * priv , const uint8_t * pub )
void NTCP2Establisher : : KeyDerivationFunction1 ( const uint8_t * pub , const uint8_t * priv , const uint8_t * rs , const uint8_t * e pub)
{
{
static const uint8_t protocolNameHash [ ] =
static const uint8_t protocolNameHash [ ] =
{
{
@ -60,28 +60,28 @@ namespace transport
SHA256_Update ( & ctx , hh , 32 ) ;
SHA256_Update ( & ctx , hh , 32 ) ;
SHA256_Update ( & ctx , rs , 32 ) ;
SHA256_Update ( & ctx , rs , 32 ) ;
SHA256_Final ( m_H , & ctx ) ;
SHA256_Final ( m_H , & ctx ) ;
// h = SHA256(h || pub)
// h = SHA256(h || e pub)
SHA256_Init ( & ctx ) ;
SHA256_Init ( & ctx ) ;
SHA256_Update ( & ctx , m_H , 32 ) ;
SHA256_Update ( & ctx , m_H , 32 ) ;
SHA256_Update ( & ctx , pub , 32 ) ;
SHA256_Update ( & ctx , e pub, 32 ) ;
SHA256_Final ( m_H , & ctx ) ;
SHA256_Final ( m_H , & ctx ) ;
// x25519 between rs and priv
// x25519 between rs and priv
uint8_t inputKeyMaterial [ 32 ] ;
uint8_t inputKeyMaterial [ 32 ] ;
i2p : : crypto : : GetEd25519 ( ) - > ScalarMul ( rs , priv , inputKeyMaterial , m_Ctx ) ; // rs*priv
i2p : : crypto : : GetEd25519 ( ) - > ScalarMul ( pub , priv , inputKeyMaterial , m_Ctx ) ; // rs*priv
MixKey ( inputKeyMaterial , m_K ) ;
MixKey ( inputKeyMaterial , m_K ) ;
}
}
void NTCP2Establisher : : KDF1Alice ( )
void NTCP2Establisher : : KDF1Alice ( )
{
{
KeyDerivationFunction1 ( m_RemoteStaticKey , GetPriv ( ) , GetPub ( ) ) ;
KeyDerivationFunction1 ( m_RemoteStaticKey , GetPriv ( ) , m_RemoteStaticKey , GetPub ( ) ) ;
}
}
void NTCP2Establisher : : KDF1Bob ( )
void NTCP2Establisher : : KDF1Bob ( )
{
{
KeyDerivationFunction1 ( GetRemotePub ( ) , i2p : : context . GetNTCP2StaticPrivateKey ( ) , GetRemotePub ( ) ) ;
KeyDerivationFunction1 ( GetRemotePub ( ) , i2p : : context . GetNTCP2StaticPrivateKey ( ) , i2p : : context . GetNTCP2StaticPublicKey ( ) , GetRemotePub ( ) ) ;
}
}
void NTCP2Establisher : : KeyDerivationFunction2 ( const uint8_t * sessionRequest , size_t sessionRequestLen )
void NTCP2Establisher : : KeyDerivationFunction2 ( const uint8_t * sessionRequest , size_t sessionRequestLen , const uint8_t * epub )
{
{
SHA256_CTX ctx ;
SHA256_CTX ctx ;
SHA256_Init ( & ctx ) ;
SHA256_Init ( & ctx ) ;
@ -99,7 +99,7 @@ namespace transport
}
}
SHA256_Init ( & ctx ) ;
SHA256_Init ( & ctx ) ;
SHA256_Update ( & ctx , m_H , 32 ) ;
SHA256_Update ( & ctx , m_H , 32 ) ;
SHA256_Update ( & ctx , GetRemotePub ( ) , 32 ) ;
SHA256_Update ( & ctx , epub , 32 ) ;
SHA256_Final ( m_H , & ctx ) ;
SHA256_Final ( m_H , & ctx ) ;
// x25519 between remote pub and priv
// x25519 between remote pub and priv
@ -108,6 +108,16 @@ namespace transport
MixKey ( inputKeyMaterial , m_K ) ;
MixKey ( inputKeyMaterial , m_K ) ;
}
}
void NTCP2Establisher : : KDF2Alice ( const uint8_t * sessionRequest , size_t sessionRequestLen )
{
KeyDerivationFunction2 ( sessionRequest , sessionRequestLen , GetRemotePub ( ) ) ;
}
void NTCP2Establisher : : KDF2Bob ( const uint8_t * sessionRequest , size_t sessionRequestLen )
{
KeyDerivationFunction2 ( sessionRequest , sessionRequestLen , GetPub ( ) ) ;
}
void NTCP2Establisher : : KDF3Alice ( )
void NTCP2Establisher : : KDF3Alice ( )
{
{
uint8_t inputKeyMaterial [ 32 ] ;
uint8_t inputKeyMaterial [ 32 ] ;
@ -137,7 +147,9 @@ namespace transport
m_ReceiveSequenceNumber ( 0 ) , m_SendSequenceNumber ( 0 ) , m_IsSending ( false )
m_ReceiveSequenceNumber ( 0 ) , m_SendSequenceNumber ( 0 ) , m_IsSending ( false )
{
{
m_Establisher . reset ( new NTCP2Establisher ) ;
m_Establisher . reset ( new NTCP2Establisher ) ;
auto addr = in_RemoteRouter - > GetNTCPAddress ( ) ;
if ( in_RemoteRouter ) // Alice
{
auto addr = in_RemoteRouter - > GetNTCP2Address ( ) ;
if ( addr - > ntcp2 )
if ( addr - > ntcp2 )
{
{
memcpy ( m_Establisher - > m_RemoteStaticKey , addr - > ntcp2 - > staticKey , 32 ) ;
memcpy ( m_Establisher - > m_RemoteStaticKey , addr - > ntcp2 - > staticKey , 32 ) ;
@ -146,6 +158,7 @@ namespace transport
else
else
LogPrint ( eLogWarning , " NTCP2: Missing NTCP2 parameters " ) ;
LogPrint ( eLogWarning , " NTCP2: Missing NTCP2 parameters " ) ;
}
}
}
NTCP2Session : : ~ NTCP2Session ( )
NTCP2Session : : ~ NTCP2Session ( )
{
{
@ -331,7 +344,7 @@ namespace transport
encryption . SetIV ( m_Establisher - > m_IV ) ;
encryption . SetIV ( m_Establisher - > m_IV ) ;
encryption . Encrypt ( m_Establisher - > GetPub ( ) , 32 , m_SessionCreatedBuffer ) ; // Y
encryption . Encrypt ( m_Establisher - > GetPub ( ) , 32 , m_SessionCreatedBuffer ) ; // Y
// encryption key for next block (m_K)
// encryption key for next block (m_K)
m_Establisher - > KeyDerivationFunction2 ( m_SessionRequestBuffer , m_SessionRequestBufferLen ) ;
m_Establisher - > KDF2Bob ( m_SessionRequestBuffer , m_SessionRequestBufferLen ) ;
auto paddingLen = rand ( ) % ( 287 - 64 ) ;
auto paddingLen = rand ( ) % ( 287 - 64 ) ;
uint8_t options [ 16 ] ;
uint8_t options [ 16 ] ;
memset ( options , 0 , 16 ) ;
memset ( options , 0 , 16 ) ;
@ -342,7 +355,7 @@ namespace transport
memset ( nonce , 0 , 12 ) ; // set nonce to zero
memset ( nonce , 0 , 12 ) ; // set nonce to zero
i2p : : crypto : : AEADChaCha20Poly1305 ( options , 16 , m_Establisher - > GetH ( ) , 32 , m_Establisher - > GetK ( ) , nonce , m_SessionCreatedBuffer + 32 , 32 , true ) ; // encrypt
i2p : : crypto : : AEADChaCha20Poly1305 ( options , 16 , m_Establisher - > GetH ( ) , 32 , m_Establisher - > GetK ( ) , nonce , m_SessionCreatedBuffer + 32 , 32 , true ) ; // encrypt
// fill padding
// fill padding
RAND_bytes ( m_SessionCreatedBuffer + 5 6, paddingLen ) ;
RAND_bytes ( m_SessionCreatedBuffer + 64 , paddingLen ) ;
// send message
// send message
m_SessionCreatedBufferLen = paddingLen + 64 ;
m_SessionCreatedBufferLen = paddingLen + 64 ;
boost : : asio : : async_write ( m_Socket , boost : : asio : : buffer ( m_SessionCreatedBuffer , m_SessionCreatedBufferLen ) , boost : : asio : : transfer_all ( ) ,
boost : : asio : : async_write ( m_Socket , boost : : asio : : buffer ( m_SessionCreatedBuffer , m_SessionCreatedBufferLen ) , boost : : asio : : transfer_all ( ) ,
@ -366,7 +379,7 @@ namespace transport
decryption . SetIV ( m_Establisher - > m_IV ) ;
decryption . SetIV ( m_Establisher - > m_IV ) ;
decryption . Decrypt ( m_SessionCreatedBuffer , 32 , m_Establisher - > GetRemotePub ( ) ) ;
decryption . Decrypt ( m_SessionCreatedBuffer , 32 , m_Establisher - > GetRemotePub ( ) ) ;
// decryption key for next block (m_K)
// decryption key for next block (m_K)
m_Establisher - > KeyDerivationFunction2 ( m_SessionRequestBuffer , m_SessionRequestBufferLen ) ;
m_Establisher - > KDF2Alice ( m_SessionRequestBuffer , m_SessionRequestBufferLen ) ;
// decrypt and verify MAC
// decrypt and verify MAC
uint8_t payload [ 16 ] ;
uint8_t payload [ 16 ] ;
uint8_t nonce [ 12 ] ;
uint8_t nonce [ 12 ] ;
@ -386,7 +399,7 @@ namespace transport
}
}
else
else
{
{
LogPrint ( eLogWarning , " NTCP2: SessionCreated MAC verification failed " ) ;
LogPrint ( eLogWarning , " NTCP2: SessionCreated AEAD verification failed " ) ;
Terminate ( ) ;
Terminate ( ) ;
}
}
}
}
@ -492,12 +505,12 @@ namespace transport
{
{
if ( ecode )
if ( ecode )
{
{
LogPrint ( eLogWarning , " NTCP2: SessionConfirmed Part 1 read error: " , ecode . message ( ) ) ;
LogPrint ( eLogWarning , " NTCP2: SessionConfirmed Part1 read error: " , ecode . message ( ) ) ;
Terminate ( ) ;
Terminate ( ) ;
}
}
else
else
{
{
LogPrint ( eLogDebug , " NTCP2: SessionConfirmed Part 1 received " ) ;
LogPrint ( eLogDebug , " NTCP2: SessionConfirmed Part1 received " ) ;
// update AD
// update AD
uint8_t h [ 80 ] ;
uint8_t h [ 80 ] ;
memcpy ( h , m_Establisher - > GetH ( ) , 32 ) ;
memcpy ( h , m_Establisher - > GetH ( ) , 32 ) ;
@ -515,7 +528,8 @@ namespace transport
// part 1
// part 1
uint8_t nonce [ 12 ] ;
uint8_t nonce [ 12 ] ;
CreateNonce ( 1 , nonce ) ;
CreateNonce ( 1 , nonce ) ;
i2p : : crypto : : AEADChaCha20Poly1305 ( m_SessionConfirmedBuffer , 48 , h , 32 , m_Establisher - > GetK ( ) , nonce , m_Establisher - > m_RemoteStaticKey , 32 , false ) ; // decrypt S
if ( i2p : : crypto : : AEADChaCha20Poly1305 ( m_SessionConfirmedBuffer , 32 , h , 32 , m_Establisher - > GetK ( ) , nonce , m_Establisher - > m_RemoteStaticKey , 32 , false ) ) // decrypt S
{
// part 2
// part 2
// update AD again
// update AD again
memcpy ( h + 32 , m_SessionConfirmedBuffer , 48 ) ;
memcpy ( h + 32 , m_SessionConfirmedBuffer , 48 ) ;
@ -524,7 +538,8 @@ namespace transport
std : : vector < uint8_t > buf ( m_Establisher - > m3p2Len - 16 ) ; // -MAC
std : : vector < uint8_t > buf ( m_Establisher - > m3p2Len - 16 ) ; // -MAC
m_Establisher - > KDF3Bob ( ) ;
m_Establisher - > KDF3Bob ( ) ;
memset ( nonce , 0 , 12 ) ; // set nonce to 0 again
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
if ( i2p : : crypto : : AEADChaCha20Poly1305 ( m_SessionConfirmedBuffer + 48 , m_Establisher - > m3p2Len - 16 , m_Establisher - > GetH ( ) , 32 , m_Establisher - > GetK ( ) , nonce , buf . data ( ) , m_Establisher - > m3p2Len - 16 , false ) ) // decrypt
{
// process RI
// process RI
if ( buf [ 0 ] = = eNTCP2BlkRouterInfo )
if ( buf [ 0 ] = = eNTCP2BlkRouterInfo )
{
{
@ -554,6 +569,18 @@ namespace transport
Established ( ) ;
Established ( ) ;
ReceiveLength ( ) ;
ReceiveLength ( ) ;
}
}
else
{
LogPrint ( eLogWarning , " NTCP2: SessionConfirmed Part2 AEAD verification failed " ) ;
Terminate ( ) ;
}
}
else
{
LogPrint ( eLogWarning , " NTCP2: SessionConfirmed Part1 AEAD verification failed " ) ;
Terminate ( ) ;
}
}
}
}
void NTCP2Session : : ClientLogin ( )
void NTCP2Session : : ClientLogin ( )
@ -794,7 +821,7 @@ namespace transport
continue ;
continue ;
}
}
LogPrint ( eLogInfo , " NTC2 P: Start listening TCP port " , address - > port ) ;
LogPrint ( eLogInfo , " NTCP2 : Start listening TCP port " , address - > port ) ;
auto conn = std : : make_shared < NTCP2Session > ( * this ) ;
auto conn = std : : make_shared < NTCP2Session > ( * this ) ;
m_NTCP2Acceptor - > async_accept ( conn - > GetSocket ( ) , std : : bind ( & NTCP2Server : : HandleAccept , this , conn , std : : placeholders : : _1 ) ) ;
m_NTCP2Acceptor - > async_accept ( conn - > GetSocket ( ) , std : : bind ( & NTCP2Server : : HandleAccept , this , conn , std : : placeholders : : _1 ) ) ;
}
}