2022-06-05 23:33:36 +00:00
/*
* Copyright ( c ) 2022 , The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
# ifndef SSU2_SESSION_H__
# define SSU2_SESSION_H__
# include <memory>
# include <functional>
# include <map>
# include <set>
# include <list>
# include <boost/asio.hpp>
# include "Crypto.h"
# include "RouterInfo.h"
2022-07-06 16:41:51 +00:00
# include "RouterContext.h"
2022-06-05 23:33:36 +00:00
# include "TransportSession.h"
namespace i2p
{
namespace transport
{
const int SSU2_CONNECT_TIMEOUT = 5 ; // 5 seconds
const int SSU2_TERMINATION_TIMEOUT = 330 ; // 5.5 minutes
2022-07-13 16:45:20 +00:00
const int SSU2_CLOCK_SKEW = 60 ; // in seconds
2022-08-08 23:57:48 +00:00
const int SSU2_CLOCK_THRESHOLD = 15 ; // in seconds, if more we should adjust
2022-06-17 02:37:33 +00:00
const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9 ; // for Retry message, in seconds
const int SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT = 52 * 60 ; // for next token block, in seconds
2022-06-19 12:52:47 +00:00
const int SSU2_TOKEN_EXPIRATION_THRESHOLD = 2 ; // in seconds
2022-06-05 23:33:36 +00:00
const int SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT = 10 ; // in seconds
const int SSU2_PEER_TEST_EXPIRATION_TIMEOUT = 60 ; // 60 seconds
2022-07-09 21:05:23 +00:00
const size_t SSU2_MAX_PACKET_SIZE = 1500 ;
2022-07-15 00:12:27 +00:00
const size_t SSU2_MIN_PACKET_SIZE = 1280 ;
2022-07-29 22:45:02 +00:00
const int SSU2_HANDSHAKE_RESEND_INTERVAL = 1000 ; // in millseconds
2022-07-28 23:30:08 +00:00
const int SSU2_RESEND_INTERVAL = 300 ; // in milliseconds
2022-06-05 23:33:36 +00:00
const int SSU2_MAX_NUM_RESENDS = 5 ;
const int SSU2_INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30 ; // in seconds
2022-07-29 22:45:02 +00:00
const size_t SSU2_MIN_WINDOW_SIZE = 16 ; // in packets
const size_t SSU2_MAX_WINDOW_SIZE = 256 ; // in packets
const size_t SSU2_MIN_RTO = 100 ; // in milliseconds
const size_t SSU2_MAX_RTO = 2500 ; // in milliseconds
2022-07-31 13:45:18 +00:00
const float SSU2_kAPPA = 1.8 ;
2022-07-29 22:45:02 +00:00
const size_t SSU2_MAX_OUTGOING_QUEUE_SIZE = 500 ; // in messages
2022-06-11 14:15:27 +00:00
const int SSU2_MAX_NUM_ACK_RANGES = 32 ; // to send
2022-08-03 20:06:07 +00:00
const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64 ;
2022-06-05 23:33:36 +00:00
2022-09-01 22:40:54 +00:00
// flags
2022-10-09 17:24:43 +00:00
const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01 ;
2022-06-05 23:33:36 +00:00
enum SSU2MessageType
{
eSSU2SessionRequest = 0 ,
eSSU2SessionCreated = 1 ,
eSSU2SessionConfirmed = 2 ,
eSSU2Data = 6 ,
eSSU2PeerTest = 7 ,
eSSU2Retry = 9 ,
eSSU2TokenRequest = 10 ,
eSSU2HolePunch = 11
} ;
enum SSU2BlockType
{
eSSU2BlkDateTime = 0 ,
eSSU2BlkOptions , // 1
eSSU2BlkRouterInfo , // 2
eSSU2BlkI2NPMessage , // 3
eSSU2BlkFirstFragment , // 4
eSSU2BlkFollowOnFragment , // 5
eSSU2BlkTermination , // 6
eSSU2BlkRelayRequest , // 7
eSSU2BlkRelayResponse , // 8
eSSU2BlkRelayIntro , // 9
eSSU2BlkPeerTest , // 10
eSSU2BlkNextNonce , // 11
eSSU2BlkAck , // 12
eSSU2BlkAddress , // 13
eSSU2BlkIntroKey , // 14
eSSU2BlkRelayTagRequest , // 15
eSSU2BlkRelayTag , // 16
eSSU2BlkNewToken , // 17
eSSU2BlkPathChallenge , // 18
eSSU2BlkPathResponse , // 19
eSSU2BlkFirstPacketNumber , // 20
eSSU2BlkPadding = 254
} ;
enum SSU2SessionState
{
eSSU2SessionStateUnknown ,
2022-06-22 17:58:22 +00:00
eSSU2SessionStateTokenReceived ,
2022-06-24 17:07:02 +00:00
eSSU2SessionStateSessionRequestSent ,
2022-07-13 16:45:20 +00:00
eSSU2SessionStateSessionRequestReceived ,
2022-06-24 17:07:02 +00:00
eSSU2SessionStateSessionCreatedSent ,
2022-08-08 23:57:48 +00:00
eSSU2SessionStateSessionCreatedReceived ,
2022-06-25 02:06:30 +00:00
eSSU2SessionStateSessionConfirmedSent ,
2022-06-05 23:33:36 +00:00
eSSU2SessionStateEstablished ,
2022-07-08 23:06:09 +00:00
eSSU2SessionStateClosing ,
2022-06-05 23:33:36 +00:00
eSSU2SessionStateTerminated ,
2022-06-21 16:09:58 +00:00
eSSU2SessionStateFailed ,
eSSU2SessionStateIntroduced ,
eSSU2SessionStatePeerTest ,
2022-08-25 22:48:26 +00:00
eSSU2SessionStatePeerTestReceived , // 5 before 4
eSSU2SessionStateTokenRequestReceived
2022-06-05 23:33:36 +00:00
} ;
enum SSU2PeerTestCode
{
eSSU2PeerTestCodeAccept = 0 ,
eSSU2PeerTestCodeBobReasonUnspecified = 1 ,
eSSU2PeerTestCodeBobNoCharlieAvailable = 2 ,
eSSU2PeerTestCodeBobLimitExceeded = 3 ,
eSSU2PeerTestCodeBobSignatureFailure = 4 ,
eSSU2PeerTestCodeCharlieReasonUnspecified = 64 ,
eSSU2PeerTestCodeCharlieUnsupportedAddress = 65 ,
eSSU2PeerTestCodeCharlieLimitExceeded = 66 ,
eSSU2PeerTestCodeCharlieSignatureFailure = 67 ,
eSSU2PeerTestCodeCharlieAliceIsAlreadyConnected = 68 ,
eSSU2PeerTestCodeCharlieAliceIsBanned = 69 ,
eSSU2PeerTestCodeCharlieAliceIsUnknown = 70 ,
eSSU2PeerTestCodeUnspecified = 128
2022-10-09 17:24:43 +00:00
} ;
2022-06-05 23:33:36 +00:00
2022-06-17 23:55:58 +00:00
enum SSU2RelayResponseCode
{
eSSU2RelayResponseCodeAccept = 0 ,
2022-06-21 19:45:35 +00:00
eSSU2RelayResponseCodeBobRelayTagNotFound = 5 ,
2022-06-21 20:20:39 +00:00
eSSU2RelayResponseCodeCharlieUnsupportedAddress = 65 ,
2022-06-21 19:45:35 +00:00
eSSU2RelayResponseCodeCharlieSignatureFailure = 67 ,
eSSU2RelayResponseCodeCharlieAliceIsUnknown = 70
2022-10-09 17:24:43 +00:00
} ;
2022-07-09 21:05:23 +00:00
enum SSU2TerminationReason
{
eSSU2TerminationReasonNormalClose = 0 ,
eSSU2TerminationReasonTerminationReceived = 1 ,
eSSU2TerminationReasonIdleTimeout = 2 ,
eSSU2TerminationReasonRouterShutdown = 3 ,
eSSU2TerminationReasonDataPhaseAEADFailure = 4 ,
eSSU2TerminationReasonIncompatibleOptions = 5 ,
eSSU2TerminationReasonTncompatibleSignatureType = 6 ,
eSSU2TerminationReasonClockSkew = 7 ,
eSSU2TerminationPaddingViolation = 8 ,
eSSU2TerminationReasonAEADFramingError = 9 ,
eSSU2TerminationReasonPayloadFormatError = 10 ,
eSSU2TerminationReasonSessionRequestError = 11 ,
eSSU2TerminationReasonSessionCreatedError = 12 ,
eSSU2TerminationReasonSessionConfirmedError = 13 ,
eSSU2TerminationReasonTimeout = 14 ,
eSSU2TerminationReasonRouterInfoSignatureVerificationFail = 15 ,
eSSU2TerminationReasonInvalidS = 16 ,
eSSU2TerminationReasonBanned = 17 ,
eSSU2TerminationReasonBadToken = 18 ,
eSSU2TerminationReasonConnectionLimits = 19 ,
eSSU2TerminationReasonIncompatibleVersion = 20 ,
2022-08-02 17:35:18 +00:00
eSSU2TerminationReasonWrongNetID = 21 ,
eSSU2TerminationReasonReplacedByNewSession = 22
2022-10-09 17:24:43 +00:00
} ;
2022-06-05 23:33:36 +00:00
struct SSU2IncompleteMessage
{
struct Fragment
{
2022-07-15 00:12:27 +00:00
uint8_t buf [ SSU2_MAX_PACKET_SIZE ] ;
2022-06-05 23:33:36 +00:00
size_t len ;
bool isLast ;
} ;
std : : shared_ptr < I2NPMessage > msg ;
int nextFragmentNum ;
uint32_t lastFragmentInsertTime ; // in seconds
std : : map < int , std : : shared_ptr < Fragment > > outOfSequenceFragments ;
2022-08-03 20:06:07 +00:00
void AttachNextFragment ( const uint8_t * fragment , size_t fragmentSize ) ;
2022-06-05 23:33:36 +00:00
} ;
2022-08-04 22:13:44 +00:00
struct SSU2SentPacket
{
uint8_t payload [ SSU2_MAX_PACKET_SIZE ] ;
size_t payloadSize = 0 ;
uint64_t sendTime ; // in milliseconds
int numResends = 0 ;
} ;
2022-10-09 17:24:43 +00:00
2022-06-05 23:33:36 +00:00
// RouterInfo flags
const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01 ;
const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02 ;
class SSU2Server ;
class SSU2Session : public TransportSession , public std : : enable_shared_from_this < SSU2Session >
{
union Header
{
uint64_t ll [ 2 ] ;
uint8_t buf [ 16 ] ;
struct
{
uint64_t connID ;
uint32_t packetNum ;
uint8_t type ;
uint8_t flags [ 3 ] ;
} h ;
} ;
2022-07-12 16:17:58 +00:00
struct HandshakePacket
2022-06-05 23:33:36 +00:00
{
Header header ;
2022-06-25 02:06:30 +00:00
uint8_t headerX [ 48 ] ; // part1 for SessionConfirmed
2022-07-12 16:17:58 +00:00
uint8_t payload [ SSU2_MAX_PACKET_SIZE * 2 ] ;
size_t payloadSize = 0 ;
2022-07-29 19:24:24 +00:00
uint64_t sendTime = 0 ; // in milliseconds
2022-07-16 20:08:55 +00:00
bool isSecondFragment = false ; // for SessionConfirmed
2022-06-05 23:33:36 +00:00
} ;
typedef std : : function < void ( ) > OnEstablished ;
public :
SSU2Session ( SSU2Server & server , std : : shared_ptr < const i2p : : data : : RouterInfo > in_RemoteRouter = nullptr ,
std : : shared_ptr < const i2p : : data : : RouterInfo : : Address > addr = nullptr ) ;
~ SSU2Session ( ) ;
void SetRemoteEndpoint ( const boost : : asio : : ip : : udp : : endpoint & ep ) { m_RemoteEndpoint = ep ; } ;
const boost : : asio : : ip : : udp : : endpoint & GetRemoteEndpoint ( ) const { return m_RemoteEndpoint ; } ;
2022-06-09 22:04:37 +00:00
i2p : : data : : RouterInfo : : CompatibleTransports GetRemoteTransports ( ) const { return m_RemoteTransports ; } ;
2022-06-12 01:26:23 +00:00
std : : shared_ptr < const i2p : : data : : RouterInfo : : Address > GetAddress ( ) const { return m_Address ; } ;
2022-06-05 23:33:36 +00:00
void SetOnEstablished ( OnEstablished e ) { m_OnEstablished = e ; } ;
2022-06-22 15:59:29 +00:00
OnEstablished GetOnEstablished ( ) const { return m_OnEstablished ; } ;
2022-06-05 23:33:36 +00:00
void Connect ( ) ;
bool Introduce ( std : : shared_ptr < SSU2Session > session , uint32_t relayTag ) ;
2022-06-19 20:40:03 +00:00
void WaitForIntroduction ( ) ;
2022-06-06 21:28:39 +00:00
void SendPeerTest ( ) ; // Alice, Data message
2022-07-10 21:13:25 +00:00
void SendKeepAlive ( ) ;
2022-07-09 21:05:23 +00:00
void RequestTermination ( SSU2TerminationReason reason ) ;
2022-06-05 23:33:36 +00:00
void CleanUp ( uint64_t ts ) ;
void FlushData ( ) ;
void Done ( ) override ;
2022-06-13 18:02:36 +00:00
void SendLocalRouterInfo ( bool update ) override ;
2022-06-05 23:33:36 +00:00
void SendI2NPMessages ( const std : : vector < std : : shared_ptr < I2NPMessage > > & msgs ) override ;
2022-06-17 22:45:37 +00:00
uint32_t GetRelayTag ( ) const override { return m_RelayTag ; } ;
2022-09-03 19:38:52 +00:00
size_t Resend ( uint64_t ts ) ; // return number or resent packets
2022-06-05 23:33:36 +00:00
bool IsEstablished ( ) const { return m_State = = eSSU2SessionStateEstablished ; } ;
uint64_t GetConnID ( ) const { return m_SourceConnID ; } ;
SSU2SessionState GetState ( ) const { return m_State ; } ;
void SetState ( SSU2SessionState state ) { m_State = state ; } ;
bool ProcessFirstIncomingMessage ( uint64_t connID , uint8_t * buf , size_t len ) ;
bool ProcessSessionCreated ( uint8_t * buf , size_t len ) ;
bool ProcessSessionConfirmed ( uint8_t * buf , size_t len ) ;
bool ProcessRetry ( uint8_t * buf , size_t len ) ;
bool ProcessHolePunch ( uint8_t * buf , size_t len ) ;
bool ProcessPeerTest ( uint8_t * buf , size_t len ) ;
2022-09-07 23:11:33 +00:00
void ProcessData ( uint8_t * buf , size_t len , const boost : : asio : : ip : : udp : : endpoint & from ) ;
2022-06-05 23:33:36 +00:00
private :
2022-07-26 23:56:30 +00:00
void Terminate ( ) ;
2022-06-05 23:33:36 +00:00
void Established ( ) ;
2022-06-19 20:40:03 +00:00
void ScheduleConnectTimer ( ) ;
void HandleConnectTimer ( const boost : : system : : error_code & ecode ) ;
2022-06-05 23:33:36 +00:00
void PostI2NPMessages ( std : : vector < std : : shared_ptr < I2NPMessage > > msgs ) ;
2022-07-26 17:00:41 +00:00
bool SendQueue ( ) ; // returns true if ack block was sent
bool SendFragmentedMessage ( std : : shared_ptr < I2NPMessage > msg ) ;
2022-07-19 20:09:16 +00:00
void ResendHandshakePacket ( ) ;
2022-08-08 17:08:12 +00:00
void ConnectAfterIntroduction ( ) ;
2022-10-09 17:24:43 +00:00
2022-06-05 23:33:36 +00:00
void ProcessSessionRequest ( Header & header , uint8_t * buf , size_t len ) ;
void ProcessTokenRequest ( Header & header , uint8_t * buf , size_t len ) ;
void SendSessionRequest ( uint64_t token = 0 ) ;
void SendSessionCreated ( const uint8_t * X ) ;
void SendSessionConfirmed ( const uint8_t * Y ) ;
void KDFDataPhase ( uint8_t * keydata_ab , uint8_t * keydata_ba ) ;
void SendTokenRequest ( ) ;
void SendRetry ( ) ;
2022-09-01 22:40:54 +00:00
uint32_t SendData ( const uint8_t * buf , size_t len , uint8_t flags = 0 ) ; // returns packet num
2022-06-05 23:33:36 +00:00
void SendQuickAck ( ) ;
void SendTermination ( ) ;
2022-07-01 00:00:18 +00:00
void SendHolePunch ( uint32_t nonce , const boost : : asio : : ip : : udp : : endpoint & ep , const uint8_t * introKey , uint64_t token ) ;
2022-10-09 17:24:43 +00:00
void SendPeerTest ( uint8_t msg , const uint8_t * signedData , size_t signedDataLen , const uint8_t * introKey ) ; // PeerTest message
2022-08-02 17:35:18 +00:00
void SendPathResponse ( const uint8_t * data , size_t len ) ;
2022-09-07 23:11:33 +00:00
void SendPathChallenge ( ) ;
2022-10-09 17:24:43 +00:00
2022-06-05 23:33:36 +00:00
void HandlePayload ( const uint8_t * buf , size_t len ) ;
2022-08-08 23:57:48 +00:00
void HandleDateTime ( const uint8_t * buf , size_t len ) ;
2022-06-05 23:33:36 +00:00
void HandleAck ( const uint8_t * buf , size_t len ) ;
2022-07-29 19:24:24 +00:00
void HandleAckRange ( uint32_t firstPacketNum , uint32_t lastPacketNum , uint64_t ts ) ;
2022-08-03 00:02:55 +00:00
void HandleAddress ( const uint8_t * buf , size_t len ) ;
2022-06-05 23:33:36 +00:00
bool ExtractEndpoint ( const uint8_t * buf , size_t size , boost : : asio : : ip : : udp : : endpoint & ep ) ;
size_t CreateEndpoint ( uint8_t * buf , size_t len , const boost : : asio : : ip : : udp : : endpoint & ep ) ;
std : : shared_ptr < const i2p : : data : : RouterInfo : : Address > FindLocalAddress ( ) const ;
2022-07-13 23:35:18 +00:00
void AdjustMaxPayloadSize ( ) ;
2022-07-06 16:41:51 +00:00
RouterStatus GetRouterStatus ( ) const ;
void SetRouterStatus ( RouterStatus status ) const ;
2022-06-05 23:33:36 +00:00
std : : shared_ptr < const i2p : : data : : RouterInfo > ExtractRouterInfo ( const uint8_t * buf , size_t size ) ;
void CreateNonce ( uint64_t seqn , uint8_t * nonce ) ;
bool UpdateReceivePacketNum ( uint32_t packetNum ) ; // for Ack, returns false if duplicate
void HandleFirstFragment ( const uint8_t * buf , size_t len ) ;
void HandleFollowOnFragment ( const uint8_t * buf , size_t len ) ;
bool ConcatOutOfSequenceFragments ( std : : shared_ptr < SSU2IncompleteMessage > m ) ; // true if message complete
void HandleRelayRequest ( const uint8_t * buf , size_t len ) ;
void HandleRelayIntro ( const uint8_t * buf , size_t len ) ;
void HandleRelayResponse ( const uint8_t * buf , size_t len ) ;
void HandlePeerTest ( const uint8_t * buf , size_t len ) ;
size_t CreateAddressBlock ( uint8_t * buf , size_t len , const boost : : asio : : ip : : udp : : endpoint & ep ) ;
size_t CreateRouterInfoBlock ( uint8_t * buf , size_t len , std : : shared_ptr < const i2p : : data : : RouterInfo > r ) ;
size_t CreateAckBlock ( uint8_t * buf , size_t len ) ;
size_t CreatePaddingBlock ( uint8_t * buf , size_t len , size_t minSize = 0 ) ;
size_t CreateI2NPBlock ( uint8_t * buf , size_t len , std : : shared_ptr < I2NPMessage > & & msg ) ;
size_t CreateFirstFragmentBlock ( uint8_t * buf , size_t len , std : : shared_ptr < I2NPMessage > msg ) ;
size_t CreateFollowOnFragmentBlock ( uint8_t * buf , size_t len , std : : shared_ptr < I2NPMessage > msg , uint8_t & fragmentNum , uint32_t msgID ) ;
size_t CreateRelayIntroBlock ( uint8_t * buf , size_t len , const uint8_t * introData , size_t introDataLen ) ;
2022-10-09 17:24:43 +00:00
size_t CreateRelayResponseBlock ( uint8_t * buf , size_t len , SSU2RelayResponseCode code , uint32_t nonce , uint64_t token , bool v4 ) ;
2022-06-05 23:33:36 +00:00
size_t CreatePeerTestBlock ( uint8_t * buf , size_t len , uint8_t msg , SSU2PeerTestCode code , const uint8_t * routerHash , const uint8_t * signedData , size_t signedDataLen ) ;
size_t CreatePeerTestBlock ( uint8_t * buf , size_t len , uint32_t nonce ) ; // Alice
2022-07-09 21:05:23 +00:00
size_t CreateTerminationBlock ( uint8_t * buf , size_t len ) ;
2022-06-05 23:33:36 +00:00
private :
SSU2Server & m_Server ;
std : : shared_ptr < i2p : : crypto : : X25519Keys > m_EphemeralKeys ;
std : : unique_ptr < i2p : : crypto : : NoiseSymmetricState > m_NoiseState ;
2022-07-12 23:04:03 +00:00
std : : unique_ptr < HandshakePacket > m_SessionConfirmedFragment ; // for Bob if applicable or second fragment for Alice
std : : unique_ptr < HandshakePacket > m_SentHandshakePacket ; // SessionRequest, SessionCreated or SessionConfirmed
2022-06-05 23:33:36 +00:00
std : : shared_ptr < const i2p : : data : : RouterInfo : : Address > m_Address ;
boost : : asio : : ip : : udp : : endpoint m_RemoteEndpoint ;
2022-06-09 22:04:37 +00:00
i2p : : data : : RouterInfo : : CompatibleTransports m_RemoteTransports ; // for peer tests
2022-06-05 23:33:36 +00:00
uint64_t m_DestConnID , m_SourceConnID ;
SSU2SessionState m_State ;
uint8_t m_KeyDataSend [ 64 ] , m_KeyDataReceive [ 64 ] ;
uint32_t m_SendPacketNum , m_ReceivePacketNum ;
std : : set < uint32_t > m_OutOfSequencePackets ; // packet nums > receive packet num
2022-08-04 22:13:44 +00:00
std : : map < uint32_t , std : : shared_ptr < SSU2SentPacket > > m_SentPackets ; // packetNum -> packet
2022-06-05 23:33:36 +00:00
std : : map < uint32_t , std : : shared_ptr < SSU2IncompleteMessage > > m_IncompleteMessages ; // I2NP
std : : map < uint32_t , std : : pair < std : : shared_ptr < SSU2Session > , uint64_t > > m_RelaySessions ; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice
std : : map < uint32_t , std : : pair < std : : shared_ptr < SSU2Session > , uint64_t > > m_PeerTests ; // same as for relay sessions
std : : list < std : : shared_ptr < I2NPMessage > > m_SendQueue ;
i2p : : I2NPMessagesHandler m_Handler ;
bool m_IsDataReceived ;
2022-07-29 19:24:24 +00:00
size_t m_WindowSize , m_RTT , m_RTO ;
2022-06-05 23:33:36 +00:00
uint32_t m_RelayTag ; // between Bob and Charlie
OnEstablished m_OnEstablished ; // callback from Established
2022-06-19 20:40:03 +00:00
boost : : asio : : deadline_timer m_ConnectTimer ;
2022-07-09 21:05:23 +00:00
SSU2TerminationReason m_TerminationReason ;
2022-07-13 23:35:18 +00:00
size_t m_MaxPayloadSize ;
2022-09-14 23:08:14 +00:00
std : : unique_ptr < i2p : : data : : IdentHash > m_PathChallenge ;
2022-06-05 23:33:36 +00:00
} ;
inline uint64_t CreateHeaderMask ( const uint8_t * kh , const uint8_t * nonce )
{
uint64_t data = 0 ;
i2p : : crypto : : ChaCha20 ( ( uint8_t * ) & data , 8 , kh , nonce , ( uint8_t * ) & data ) ;
return data ;
}
}
}
# endif