diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 8f5eda33..25dc7d8a 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -15,7 +15,8 @@ namespace transport { SSU2Session::SSU2Session (std::shared_ptr in_RemoteRouter, std::shared_ptr addr, bool peerTest): - TransportSession (in_RemoteRouter, SSU2_TERMINATION_TIMEOUT) + TransportSession (in_RemoteRouter, SSU2_TERMINATION_TIMEOUT), + m_Address (addr) { m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState); if (in_RemoteRouter && addr) @@ -28,5 +29,38 @@ namespace transport SSU2Session::~SSU2Session () { } + + void SSU2Session::SendSessionRequest () + { + m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); + m_NoiseState->MixHash (m_EphemeralKeys->GetPublicKey (), 32); + uint8_t sharedSecret[32]; + m_EphemeralKeys->Agree (m_Address->s, sharedSecret); + m_NoiseState->MixKey (sharedSecret); + + uint8_t packet[1200]; // TODO: correct packet size + size_t packetSize = 64; + // fill packet + memcpy (packet + 32, m_EphemeralKeys->GetPublicKey (), 32); // X + // encrypt + CreateHeaderMask (m_Address->i, packet + (packetSize - 24), m_Address->i, packet + (packetSize - 12)); + EncryptHeader (*(i2p::crypto::ChipherBlock *)packet); + uint8_t nonce[12] = {0}; + i2p::crypto::ChaCha20 (packet + 16, 48, m_Address->i, nonce, packet + 16); + i2p::crypto::AEADChaCha20Poly1305 (packet + 64, packetSize - 64, m_NoiseState->m_H, 32, m_NoiseState->m_CK, nonce, packet + 64, packetSize - 48, true); + } + + void SSU2Session::EncryptHeader (i2p::crypto::ChipherBlock& header) + { + header ^= m_HeaderMask; + } + + void SSU2Session::CreateHeaderMask (const uint8_t * kh1, const uint8_t * nonce1, const uint8_t * kh2, const uint8_t * nonce2) + { + // Header Encryption KDF + uint8_t data[8] = {0}; + i2p::crypto::ChaCha20 (data, 8, kh1, nonce1, m_HeaderMask.buf); + i2p::crypto::ChaCha20 (data, 8, kh2, nonce2, m_HeaderMask.buf + 8); + } } } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index ed686333..3c0dc843 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -28,10 +28,19 @@ namespace transport std::shared_ptr addr = nullptr, bool peerTest = false); ~SSU2Session (); + private: + + void SendSessionRequest (); + void EncryptHeader (i2p::crypto::ChipherBlock& header); + void CreateHeaderMask (const uint8_t * kh1, const uint8_t * nonce1, const uint8_t * kh2, const uint8_t * nonce2); + private: std::shared_ptr m_EphemeralKeys; std::unique_ptr m_NoiseState; + std::shared_ptr m_Address; + + i2p::crypto::ChipherBlock m_HeaderMask; }; } }