2013-11-24 18:10:27 -05:00
# ifndef LEASE_SET_H__
# define LEASE_SET_H__
# include <inttypes.h>
2013-11-29 07:52:09 -05:00
# include <string.h>
2014-01-01 18:19:03 -05:00
# include <vector>
2016-05-29 16:35:57 -04:00
# include <set>
2016-02-09 10:46:27 -05:00
# include <memory>
2013-12-19 22:05:45 -05:00
# include "Identity.h"
2016-09-03 11:46:47 -04:00
# include "Timestamp.h"
2019-02-06 13:36:03 -05:00
# include "I2PEndian.h"
2013-11-24 18:10:27 -05:00
namespace i2p
{
2014-07-29 13:44:54 -04:00
namespace tunnel
{
2018-01-06 11:48:51 +08:00
class InboundTunnel ;
2014-07-29 13:44:54 -04:00
}
2013-11-24 18:10:27 -05:00
namespace data
2018-01-06 11:48:51 +08:00
{
2016-02-28 21:43:18 -05:00
const int LEASE_ENDDATE_THRESHOLD = 51000 ; // in milliseconds
2013-11-24 18:10:27 -05:00
struct Lease
{
2015-03-23 12:55:42 -04:00
IdentHash tunnelGateway ;
2013-11-24 18:10:27 -05:00
uint32_t tunnelID ;
2016-02-09 15:27:23 -05:00
uint64_t endDate ; // 0 means invalid
2016-09-03 11:46:47 -04:00
bool isUpdated ; // trasient
/* return true if this lease expires within t millisecond + fudge factor */
bool ExpiresWithin ( const uint64_t t , const uint64_t fudge = 1000 ) const {
auto expire = i2p : : util : : GetMillisecondsSinceEpoch ( ) ;
if ( fudge ) expire + = rand ( ) % fudge ;
2017-04-09 08:52:42 -04:00
if ( endDate < expire ) return true ;
return ( endDate - expire ) < t ;
2016-09-03 11:46:47 -04:00
}
2018-01-06 11:48:51 +08:00
} ;
2016-02-09 15:27:23 -05:00
struct LeaseCmp
{
bool operator ( ) ( std : : shared_ptr < const Lease > l1 , std : : shared_ptr < const Lease > l2 ) const
2018-01-06 12:01:44 +08:00
{
2016-02-09 15:27:23 -05:00
if ( l1 - > tunnelID ! = l2 - > tunnelID )
2018-01-06 11:48:51 +08:00
return l1 - > tunnelID < l2 - > tunnelID ;
2016-02-09 15:27:23 -05:00
else
2018-01-06 11:48:51 +08:00
return l1 - > tunnelGateway < l2 - > tunnelGateway ;
2016-02-09 15:27:23 -05:00
} ;
2018-01-06 11:48:51 +08:00
} ;
2013-11-24 18:10:27 -05:00
2016-08-27 13:17:34 -04:00
typedef std : : function < bool ( const Lease & l ) > LeaseInspectFunc ;
2018-01-06 11:48:51 +08:00
2016-05-25 14:17:34 -04:00
const size_t MAX_LS_BUFFER_SIZE = 3072 ;
const size_t LEASE_SIZE = 44 ; // 32 + 4 + 8
2019-01-10 11:52:34 -05:00
const size_t LEASE2_SIZE = 40 ; // 32 + 4 + 4
2018-01-06 11:48:51 +08:00
const uint8_t MAX_NUM_LEASES = 16 ;
2019-01-02 14:19:10 -05:00
const uint8_t NETDB_STORE_TYPE_LEASESET = 1 ;
2013-11-24 18:10:27 -05:00
class LeaseSet : public RoutingDestination
{
public :
2016-02-07 19:45:06 -05:00
LeaseSet ( const uint8_t * buf , size_t len , bool storeLeases = true ) ;
2019-01-14 13:49:27 -05:00
virtual ~ LeaseSet ( ) { delete [ ] m_EncryptionKey ; delete [ ] m_Buffer ; } ;
2019-01-16 19:00:17 -05:00
virtual void Update ( const uint8_t * buf , size_t len , bool verifySignature = true ) ;
2016-02-16 22:57:38 -05:00
bool IsNewer ( const uint8_t * buf , size_t len ) const ;
2018-01-06 11:48:51 +08:00
void PopulateLeases ( ) ; // from buffer
2014-10-03 15:08:41 -04:00
2014-07-29 14:31:55 -04:00
const uint8_t * GetBuffer ( ) const { return m_Buffer ; } ;
2018-01-06 11:48:51 +08:00
size_t GetBufferLen ( ) const { return m_BufferLen ; } ;
2015-04-08 10:34:16 -04:00
bool IsValid ( ) const { return m_IsValid ; } ;
2016-02-10 22:51:08 -05:00
const std : : vector < std : : shared_ptr < const Lease > > GetNonExpiredLeases ( bool withThreshold = true ) const ;
2016-08-27 13:17:34 -04:00
const std : : vector < std : : shared_ptr < const Lease > > GetNonExpiredLeasesExcluding ( LeaseInspectFunc exclude , bool withThreshold = true ) const ;
2014-01-14 20:57:33 -05:00
bool HasExpiredLeases ( ) const ;
2016-02-07 19:45:06 -05:00
bool IsExpired ( ) const ;
2016-02-09 22:42:01 -05:00
bool IsEmpty ( ) const { return m_Leases . empty ( ) ; } ;
2016-02-07 19:45:06 -05:00
uint64_t GetExpirationTime ( ) const { return m_ExpirationTime ; } ;
2016-09-03 11:46:47 -04:00
bool ExpiresSoon ( const uint64_t dlt = 1000 * 5 , const uint64_t fudge = 0 ) const ;
2018-01-06 11:48:51 +08:00
bool operator = = ( const LeaseSet & other ) const
{ return m_BufferLen = = other . m_BufferLen & & ! memcmp ( m_Buffer , other . m_Buffer , m_BufferLen ) ; } ;
2019-01-02 14:19:10 -05:00
virtual uint8_t GetStoreType ( ) const { return NETDB_STORE_TYPE_LEASESET ; } ;
2019-02-26 16:20:24 -05:00
virtual uint32_t GetPublishedTimestamp ( ) const { return 0 ; } ; // should be set for LeaseSet2 only
2019-02-06 13:36:03 -05:00
virtual std : : shared_ptr < const i2p : : crypto : : Verifier > GetTransientVerifier ( ) const { return nullptr ; } ;
2016-02-09 10:46:27 -05:00
// implements RoutingDestination
2017-11-02 14:50:57 -04:00
std : : shared_ptr < const IdentityEx > GetIdentity ( ) const { return m_Identity ; } ;
2017-11-07 20:30:05 -05:00
void Encrypt ( const uint8_t * data , uint8_t * encrypted , BN_CTX * ctx ) const ;
2013-11-26 20:59:25 -05:00
bool IsDestination ( ) const { return true ; } ;
2014-07-21 20:14:11 -04:00
2018-12-21 15:00:03 -05:00
protected :
2019-01-09 12:47:47 -05:00
void UpdateLeasesBegin ( ) ;
void UpdateLeasesEnd ( ) ;
2019-01-02 15:40:48 -05:00
void UpdateLease ( const Lease & lease , uint64_t ts ) ;
2018-12-21 15:00:03 -05:00
// called from LeaseSet2
2019-01-09 12:47:47 -05:00
LeaseSet ( bool storeLeases ) ;
2018-12-21 15:00:03 -05:00
void SetBuffer ( const uint8_t * buf , size_t len ) ;
void SetIdentity ( std : : shared_ptr < const IdentityEx > identity ) { m_Identity = identity ; } ;
void SetExpirationTime ( uint64_t t ) { m_ExpirationTime = t ; } ;
void SetIsValid ( bool isValid ) { m_IsValid = isValid ; } ;
2019-01-09 12:47:47 -05:00
bool IsStoreLeases ( ) const { return m_StoreLeases ; } ;
2018-12-21 15:00:03 -05:00
2014-07-21 20:14:11 -04:00
private :
2018-01-25 10:09:34 -05:00
void ReadFromBuffer ( bool readIdentity = true , bool verifySignature = true ) ;
2019-01-14 13:49:27 -05:00
virtual uint64_t ExtractTimestamp ( const uint8_t * buf , size_t len ) const ; // returns max expiration time
2018-01-06 11:48:51 +08:00
2013-11-24 18:10:27 -05:00
private :
2016-02-07 19:45:06 -05:00
bool m_IsValid , m_StoreLeases ; // we don't need to store leases for floodfill
2016-02-09 15:27:23 -05:00
std : : set < std : : shared_ptr < Lease > , LeaseCmp > m_Leases ;
2016-02-07 19:45:06 -05:00
uint64_t m_ExpirationTime ; // in milliseconds
2015-11-03 09:15:49 -05:00
std : : shared_ptr < const IdentityEx > m_Identity ;
2019-01-14 13:49:27 -05:00
uint8_t * m_EncryptionKey ;
2015-04-08 09:39:02 -04:00
uint8_t * m_Buffer ;
2014-07-29 13:44:54 -04:00
size_t m_BufferLen ;
2018-01-06 11:48:51 +08:00
} ;
2016-05-25 14:17:34 -04:00
2018-01-24 10:16:51 -05:00
/**
validate lease set buffer signature and extract expiration timestamp
@ returns true if the leaseset is well formed and signature is valid
*/
bool LeaseSetBufferValidate ( const uint8_t * ptr , size_t sz , uint64_t & expires ) ;
2019-01-02 14:19:10 -05:00
const uint8_t NETDB_STORE_TYPE_STANDARD_LEASESET2 = 3 ;
2019-01-08 11:26:50 -05:00
const uint8_t NETDB_STORE_TYPE_ENCRYPTED_LEASESET2 = 5 ;
2019-01-02 14:19:10 -05:00
const uint8_t NETDB_STORE_TYPE_META_LEASESET2 = 7 ;
2019-02-12 14:56:39 -05:00
const uint16_t LEASESET2_FLAG_OFFLINE_KEYS = 0x0001 ;
2019-03-22 15:32:13 -04:00
class BlindedPublicKey // for encrypted LS2
{
public :
BlindedPublicKey ( std : : shared_ptr < const IdentityEx > identity , SigningKeyType blindedKeyType = i2p : : data : : SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519 ) ;
2019-03-22 16:04:47 -04:00
BlindedPublicKey ( const std : : string & b33 ) ; // from b33 without .b32.i2p
2019-03-22 15:32:13 -04:00
const uint8_t * GetPublicKey ( ) const { return m_PublicKey . data ( ) ; } ;
size_t GetPublicKeyLen ( ) const { return m_PublicKey . size ( ) ; } ;
SigningKeyType GetSigType ( ) const { return m_SigType ; } ;
SigningKeyType GetBlindedSigType ( ) const { return m_BlindedSigType ; } ;
private :
std : : vector < uint8_t > m_PublicKey ;
i2p : : data : : SigningKeyType m_SigType , m_BlindedSigType ;
} ;
2019-02-12 14:56:39 -05:00
2018-12-21 15:00:03 -05:00
class LeaseSet2 : public LeaseSet
{
public :
2019-01-09 12:47:47 -05:00
LeaseSet2 ( uint8_t storeType , const uint8_t * buf , size_t len , bool storeLeases = true ) ;
2019-03-22 15:32:13 -04:00
LeaseSet2 ( const uint8_t * buf , size_t len , std : : shared_ptr < const BlindedPublicKey > key ) ; // store type 5, called from local netdb only
2018-12-26 15:27:32 -05:00
uint8_t GetStoreType ( ) const { return m_StoreType ; } ;
2019-02-26 16:20:24 -05:00
uint32_t GetPublishedTimestamp ( ) const { return m_PublishedTimestamp ; } ;
2019-02-06 13:36:03 -05:00
std : : shared_ptr < const i2p : : crypto : : Verifier > GetTransientVerifier ( ) const { return m_TransientVerifier ; } ;
2019-01-16 19:00:17 -05:00
void Update ( const uint8_t * buf , size_t len , bool verifySignature ) ;
2019-02-06 13:36:03 -05:00
2019-03-22 15:32:13 -04:00
static void CalculateStoreHash ( std : : shared_ptr < const BlindedPublicKey > key , i2p : : data : : IdentHash & hash ) ;
2019-03-06 16:08:04 -05:00
2019-01-09 12:47:47 -05:00
// implements RoutingDestination
void Encrypt ( const uint8_t * data , uint8_t * encrypted , BN_CTX * ctx ) const ;
2018-12-26 15:27:32 -05:00
private :
2019-02-01 12:55:13 -05:00
void ReadFromBuffer ( const uint8_t * buf , size_t len , bool readIdentity = true , bool verifySignature = true ) ;
2019-03-22 15:32:13 -04:00
void ReadFromBufferEncrypted ( const uint8_t * buf , size_t len , std : : shared_ptr < const BlindedPublicKey > key ) ;
2019-01-02 14:19:10 -05:00
size_t ReadStandardLS2TypeSpecificPart ( const uint8_t * buf , size_t len ) ;
size_t ReadMetaLS2TypeSpecificPart ( const uint8_t * buf , size_t len ) ;
2018-12-21 15:00:03 -05:00
2019-01-08 11:26:50 -05:00
template < typename Verifier >
bool VerifySignature ( Verifier & verifier , const uint8_t * buf , size_t len , size_t signatureOffset ) ;
2019-01-14 13:49:27 -05:00
uint64_t ExtractTimestamp ( const uint8_t * buf , size_t len ) const ;
2019-02-27 15:52:47 -05:00
// for encrypted LS
2019-03-05 15:51:24 -05:00
static void H ( const std : : string & p , const std : : vector < std : : pair < const uint8_t * , size_t > > & bufs , uint8_t * hash ) ;
2019-03-22 15:32:13 -04:00
static void BlindPublicKey ( std : : shared_ptr < const BlindedPublicKey > key , const char * date , uint8_t * blindedKey ) ; // blinded key 32 bytes, date is 8 chars "YYYYMMDD"
2019-02-27 15:52:47 -05:00
2018-12-21 15:00:03 -05:00
private :
2018-12-26 15:27:32 -05:00
uint8_t m_StoreType ;
2019-02-27 15:52:47 -05:00
uint32_t m_PublishedTimestamp = 0 ;
2019-02-06 13:36:03 -05:00
std : : shared_ptr < i2p : : crypto : : Verifier > m_TransientVerifier ;
2019-01-09 12:47:47 -05:00
std : : shared_ptr < i2p : : crypto : : CryptoKeyEncryptor > m_Encryptor ; // for standardLS2
2018-12-21 15:00:03 -05:00
} ;
2019-02-06 13:36:03 -05:00
// also called from Streaming.cpp
template < typename Verifier >
std : : shared_ptr < i2p : : crypto : : Verifier > ProcessOfflineSignature ( const Verifier & verifier , const uint8_t * buf , size_t len , size_t & offset )
{
if ( offset + 6 > = len ) return nullptr ;
const uint8_t * signedData = buf + offset ;
uint32_t expiresTimestamp = bufbe32toh ( buf + offset ) ; offset + = 4 ; // expires timestamp
if ( expiresTimestamp < i2p : : util : : GetSecondsSinceEpoch ( ) ) return nullptr ;
uint16_t keyType = bufbe16toh ( buf + offset ) ; offset + = 2 ;
std : : shared_ptr < i2p : : crypto : : Verifier > transientVerifier ( i2p : : data : : IdentityEx : : CreateVerifier ( keyType ) ) ;
if ( ! transientVerifier ) return nullptr ;
auto keyLen = transientVerifier - > GetPublicKeyLen ( ) ;
if ( offset + keyLen > = len ) return nullptr ;
transientVerifier - > SetPublicKey ( buf + offset ) ; offset + = keyLen ;
if ( offset + verifier - > GetSignatureLen ( ) > = len ) return nullptr ;
if ( ! verifier - > Verify ( signedData , keyLen + 6 , buf + offset ) ) return nullptr ;
offset + = verifier - > GetSignatureLen ( ) ;
return transientVerifier ;
}
//------------------------------------------------------------------------------------
2016-05-25 14:17:34 -04:00
class LocalLeaseSet
{
public :
LocalLeaseSet ( std : : shared_ptr < const IdentityEx > identity , const uint8_t * encryptionPublicKey , std : : vector < std : : shared_ptr < i2p : : tunnel : : InboundTunnel > > tunnels ) ;
2016-05-30 12:56:42 -04:00
LocalLeaseSet ( std : : shared_ptr < const IdentityEx > identity , const uint8_t * buf , size_t len ) ;
2019-01-10 11:52:34 -05:00
virtual ~ LocalLeaseSet ( ) { delete [ ] m_Buffer ; } ;
2016-05-25 14:17:34 -04:00
2019-01-10 11:52:34 -05:00
virtual uint8_t * GetBuffer ( ) const { return m_Buffer ; } ;
uint8_t * GetSignature ( ) { return GetBuffer ( ) + GetBufferLen ( ) - GetSignatureLen ( ) ; } ;
virtual size_t GetBufferLen ( ) const { return m_BufferLen ; } ;
2016-05-25 14:17:34 -04:00
size_t GetSignatureLen ( ) const { return m_Identity - > GetSignatureLen ( ) ; } ;
2018-01-06 11:48:51 +08:00
uint8_t * GetLeases ( ) { return m_Leases ; } ;
2016-05-25 14:17:34 -04:00
const IdentHash & GetIdentHash ( ) const { return m_Identity - > GetIdentHash ( ) ; } ;
2016-05-25 15:10:28 -04:00
bool IsExpired ( ) const ;
2016-05-30 12:56:42 -04:00
uint64_t GetExpirationTime ( ) const { return m_ExpirationTime ; } ;
void SetExpirationTime ( uint64_t expirationTime ) { m_ExpirationTime = expirationTime ; } ;
2018-01-06 11:48:51 +08:00
bool operator = = ( const LeaseSet & other ) const
2019-01-10 11:52:34 -05:00
{ return GetBufferLen ( ) = = other . GetBufferLen ( ) & & ! memcmp ( GetBuffer ( ) , other . GetBuffer ( ) , GetBufferLen ( ) ) ; } ;
2016-05-25 15:10:28 -04:00
2019-01-09 14:51:47 -05:00
virtual uint8_t GetStoreType ( ) const { return NETDB_STORE_TYPE_LEASESET ; } ;
2016-05-25 14:17:34 -04:00
private :
2018-01-06 11:48:51 +08:00
2016-05-25 15:10:28 -04:00
uint64_t m_ExpirationTime ; // in milliseconds
2016-05-25 14:17:34 -04:00
std : : shared_ptr < const IdentityEx > m_Identity ;
2016-05-29 16:35:57 -04:00
uint8_t * m_Buffer , * m_Leases ;
2016-05-25 14:17:34 -04:00
size_t m_BufferLen ;
2018-01-06 11:48:51 +08:00
} ;
2019-01-09 14:51:47 -05:00
class LocalLeaseSet2 : public LocalLeaseSet
{
public :
2019-02-12 14:56:39 -05:00
LocalLeaseSet2 ( uint8_t storeType , const i2p : : data : : PrivateKeys & keys ,
2019-01-09 14:51:47 -05:00
uint16_t keyType , uint16_t keyLen , const uint8_t * encryptionPublicKey ,
std : : vector < std : : shared_ptr < i2p : : tunnel : : InboundTunnel > > tunnels ) ;
2019-01-29 11:30:31 -05:00
LocalLeaseSet2 ( uint8_t storeType , std : : shared_ptr < const IdentityEx > identity , const uint8_t * buf , size_t len ) ;
2019-01-10 11:52:34 -05:00
virtual ~ LocalLeaseSet2 ( ) { delete [ ] m_Buffer ; } ;
uint8_t * GetBuffer ( ) const { return m_Buffer + 1 ; } ;
size_t GetBufferLen ( ) const { return m_BufferLen ; } ;
2019-01-09 14:51:47 -05:00
2019-01-10 11:52:34 -05:00
uint8_t GetStoreType ( ) const { return m_Buffer [ 0 ] ; } ;
2019-01-09 14:51:47 -05:00
private :
2019-01-10 11:52:34 -05:00
uint8_t * m_Buffer ; // 1 byte store type + actual buffer
size_t m_BufferLen ;
2019-01-09 14:51:47 -05:00
} ;
2018-01-06 11:48:51 +08:00
}
}
2013-11-24 18:10:27 -05:00
# endif