mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
wip
This commit is contained in:
parent
5a4d681af8
commit
b55f98b813
2 changed files with 172 additions and 110 deletions
|
@ -52,30 +52,35 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE Identity() { memset(reinterpret_cast<void *>(this),0,sizeof(Identity)); }
|
ZT_ALWAYS_INLINE Identity() { memset(reinterpret_cast<void *>(this),0,sizeof(Identity)); }
|
||||||
ZT_ALWAYS_INLINE Identity(const char *str)
|
ZT_ALWAYS_INLINE ~Identity() { Utils::burn(reinterpret_cast<void *>(&this->_priv),sizeof(this->_priv)); }
|
||||||
{
|
|
||||||
if (!fromString(str))
|
/**
|
||||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
|
* Construct identity from string
|
||||||
}
|
*
|
||||||
|
* If the identity is not basically valid (no deep checking is done) the result will
|
||||||
|
* be a null identity.
|
||||||
|
*
|
||||||
|
* @param str Identity in canonical string format
|
||||||
|
*/
|
||||||
|
ZT_ALWAYS_INLINE Identity(const char *str) { fromString(str); }
|
||||||
|
|
||||||
template<unsigned int C>
|
template<unsigned int C>
|
||||||
ZT_ALWAYS_INLINE Identity(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
|
ZT_ALWAYS_INLINE Identity(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE ~Identity() { Utils::burn(reinterpret_cast<void *>(this),sizeof(Identity)); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set identity to NIL value (all zero)
|
* Set identity to NIL value (all zero)
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE void zero() { memset(reinterpret_cast<void *>(this),0,sizeof(Identity)); }
|
ZT_ALWAYS_INLINE void zero() { memset(reinterpret_cast<void *>(this),0,sizeof(Identity)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Identity type
|
* @return Identity type (undefined if identity is null or invalid)
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE Type type() const { return _type; }
|
ZT_ALWAYS_INLINE Type type() const { return _type; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a new identity (address, key pair)
|
* Generate a new identity (address, key pair)
|
||||||
*
|
*
|
||||||
* This is a time consuming operation.
|
* This is a time consuming operation taking up to 5-10 seconds on some slower systems.
|
||||||
*
|
*
|
||||||
* @param t Type of identity to generate
|
* @param t Type of identity to generate
|
||||||
*/
|
*/
|
||||||
|
@ -94,10 +99,12 @@ public:
|
||||||
ZT_ALWAYS_INLINE bool hasPrivate() const { return _hasPrivate; }
|
ZT_ALWAYS_INLINE bool hasPrivate() const { return _hasPrivate; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This generates a SHA384 hash of this identity's keys.
|
||||||
|
*
|
||||||
* @param h Buffer to receive SHA384 of public key(s)
|
* @param h Buffer to receive SHA384 of public key(s)
|
||||||
* @param includePrivate If true, hash private key(s) too
|
* @param includePrivate If true, hash private key(s) as well
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE bool hash(uint8_t h[48],const bool includePrivate) const
|
ZT_ALWAYS_INLINE bool hash(uint8_t h[48],const bool includePrivate = false) const
|
||||||
{
|
{
|
||||||
switch(_type) {
|
switch(_type) {
|
||||||
|
|
||||||
|
@ -142,8 +149,10 @@ public:
|
||||||
|
|
||||||
case P384:
|
case P384:
|
||||||
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
|
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
|
||||||
|
// When signing with P384 we also hash the C25519 public key as an
|
||||||
|
// extra measure to ensure that only this identity can verify.
|
||||||
uint8_t h[48];
|
uint8_t h[48];
|
||||||
SHA384(h,data,len);
|
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||||
ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
|
ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
|
||||||
return ZT_ECC384_SIGNATURE_SIZE;
|
return ZT_ECC384_SIGNATURE_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -165,15 +174,18 @@ public:
|
||||||
ZT_ALWAYS_INLINE bool verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
|
ZT_ALWAYS_INLINE bool verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
|
||||||
{
|
{
|
||||||
switch(_type) {
|
switch(_type) {
|
||||||
|
|
||||||
case C25519:
|
case C25519:
|
||||||
return C25519::verify(_pub.c25519,data,len,sig,siglen);
|
return C25519::verify(_pub.c25519,data,len,sig,siglen);
|
||||||
|
|
||||||
case P384:
|
case P384:
|
||||||
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
||||||
uint8_t h[48];
|
uint8_t h[48];
|
||||||
SHA384(h,data,len);
|
SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||||
return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
|
return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -193,6 +205,7 @@ public:
|
||||||
uint8_t h[64];
|
uint8_t h[64];
|
||||||
if (_hasPrivate) {
|
if (_hasPrivate) {
|
||||||
if (_type == C25519) {
|
if (_type == C25519) {
|
||||||
|
|
||||||
if ((id._type == C25519)||(id._type == P384)) {
|
if ((id._type == C25519)||(id._type == P384)) {
|
||||||
// If we are a C25519 key we can agree with another C25519 key or with only the
|
// If we are a C25519 key we can agree with another C25519 key or with only the
|
||||||
// C25519 portion of a type 1 P-384 key.
|
// C25519 portion of a type 1 P-384 key.
|
||||||
|
@ -201,12 +214,10 @@ public:
|
||||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (_type == P384) {
|
} else if (_type == P384) {
|
||||||
|
|
||||||
if (id._type == P384) {
|
if (id._type == P384) {
|
||||||
// Perform key agreement over both curves for the same reason that C25519 public
|
|
||||||
// keys are included in P-384 signature inputs: to bind the keys together so
|
|
||||||
// that a type 1 identity with the same C25519 public key (and therefore address)
|
|
||||||
// but a different P-384 key will not work.
|
|
||||||
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
C25519::agree(_priv.c25519,id._pub.c25519,rawkey);
|
||||||
ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_SHARED_KEY_LEN);
|
ECC384ECDH(id._pub.p384,_priv.p384,rawkey + ZT_C25519_SHARED_KEY_LEN);
|
||||||
SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE);
|
SHA384(h,rawkey,ZT_C25519_SHARED_KEY_LEN + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||||
|
@ -219,6 +230,7 @@ public:
|
||||||
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
memcpy(key,h,ZT_PEER_SECRET_KEY_LENGTH);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -229,28 +241,6 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE const Address &address() const { return _address; }
|
ZT_ALWAYS_INLINE const Address &address() const { return _address; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to generate an older type identity from a newer type
|
|
||||||
*
|
|
||||||
* @param dest Destination to fill with downgraded identity
|
|
||||||
* @param toType Desired identity type
|
|
||||||
*/
|
|
||||||
ZT_ALWAYS_INLINE bool downgrade(Identity &dest,const Type toType)
|
|
||||||
{
|
|
||||||
if (_type == toType) {
|
|
||||||
return true;
|
|
||||||
} else if ((_type == P384)&&(toType == C25519)) {
|
|
||||||
dest._address = _address;
|
|
||||||
dest._type = C25519;
|
|
||||||
dest._hasPrivate = _hasPrivate;
|
|
||||||
memcpy(dest._pub.c25519,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
|
||||||
if (_hasPrivate)
|
|
||||||
memcpy(dest._priv.c25519,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize this identity (binary)
|
* Serialize this identity (binary)
|
||||||
*
|
*
|
||||||
|
@ -284,7 +274,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
b.append((uint8_t)0);
|
b.append((uint8_t)0);
|
||||||
}
|
}
|
||||||
b.append((uint16_t)0); // size of additional fields
|
b.append((uint16_t)0); // size of additional fields (should have included such a thing in v0!)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -358,7 +348,7 @@ public:
|
||||||
*
|
*
|
||||||
* @param includePrivate If true, include private key (if it exists)
|
* @param includePrivate If true, include private key (if it exists)
|
||||||
* @param buf Buffer to store string
|
* @param buf Buffer to store string
|
||||||
* @return ASCII string representation of identity
|
* @return ASCII string representation of identity (pointer to buf)
|
||||||
*/
|
*/
|
||||||
char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
|
char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
|
||||||
|
|
||||||
|
@ -382,12 +372,9 @@ public:
|
||||||
{
|
{
|
||||||
if ((_address == id._address)&&(_type == id._type)) {
|
if ((_address == id._address)&&(_type == id._type)) {
|
||||||
switch(_type) {
|
switch(_type) {
|
||||||
case C25519:
|
case C25519: return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) == 0);
|
||||||
return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) == 0);
|
// case P384:
|
||||||
case P384:
|
default: return (memcmp(&_pub,&id._pub,sizeof(_pub)) == 0);
|
||||||
return (memcmp(&_pub,&id._pub,sizeof(_pub)) == 0);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -401,10 +388,9 @@ public:
|
||||||
return true;
|
return true;
|
||||||
if (_type == id._type) {
|
if (_type == id._type) {
|
||||||
switch(_type) {
|
switch(_type) {
|
||||||
case C25519:
|
case C25519: return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) < 0);
|
||||||
return (memcmp(_pub.c25519,id._pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) < 0);
|
// case P384:
|
||||||
case P384:
|
default: return (memcmp(&_pub,&id._pub,sizeof(_pub)) < 0);
|
||||||
return (memcmp(&_pub,&id._pub,sizeof(_pub)) < 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
194
node/Packet.hpp
194
node/Packet.hpp
|
@ -424,10 +424,12 @@ public:
|
||||||
* <[8] timestamp for determining latency>
|
* <[8] timestamp for determining latency>
|
||||||
* <[...] binary serialized identity (see Identity)>
|
* <[...] binary serialized identity (see Identity)>
|
||||||
* <[...] physical destination address of packet>
|
* <[...] physical destination address of packet>
|
||||||
* [... begin encrypted section ...]
|
* [... begin encrypted region ...]
|
||||||
* <[2] 16-bit reserved field, always 0>
|
* <[2] 16-bit reserved field, always 0>
|
||||||
* <[2] 16-bit length of locator>
|
* <[2] 16-bit length of locator>
|
||||||
* <[...] locator for this node>
|
* <[...] locator for this node>
|
||||||
|
* <[2] 16-bit length of meta-data dictionary>
|
||||||
|
* <[...] meta-data dictionary>
|
||||||
*
|
*
|
||||||
* HELLO is sent in the clear as it is how peers share their identity
|
* HELLO is sent in the clear as it is how peers share their identity
|
||||||
* public keys.
|
* public keys.
|
||||||
|
@ -441,6 +443,9 @@ public:
|
||||||
* very sensitive, but hiding the locator and other meta-data slightly
|
* very sensitive, but hiding the locator and other meta-data slightly
|
||||||
* improves privacy.
|
* improves privacy.
|
||||||
*
|
*
|
||||||
|
* The 16-bit zero after encryption starts is for backward compatibility
|
||||||
|
* with pre-2.0 nodes.
|
||||||
|
*
|
||||||
* OK payload:
|
* OK payload:
|
||||||
* <[8] HELLO timestamp field echo>
|
* <[8] HELLO timestamp field echo>
|
||||||
* <[1] protocol version>
|
* <[1] protocol version>
|
||||||
|
@ -578,6 +583,20 @@ public:
|
||||||
*/
|
*/
|
||||||
VERB_ECHO = 0x08,
|
VERB_ECHO = 0x08,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Announce interest in multicast group(s):
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[6] multicast Ethernet address>
|
||||||
|
* <[4] multicast additional distinguishing information (ADI)>
|
||||||
|
* [... additional tuples of network/address/adi ...]
|
||||||
|
*
|
||||||
|
* LIKEs may be sent to any peer, though a good implementation should
|
||||||
|
* restrict them to peers on the same network they're for and to network
|
||||||
|
* controllers and root servers. In the current network, root servers
|
||||||
|
* will provide the service of final multicast cache.
|
||||||
|
*/
|
||||||
|
VERB_MULTICAST_LIKE = 0x09,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network credentials push:
|
* Network credentials push:
|
||||||
* [<[...] one or more certificates of membership>]
|
* [<[...] one or more certificates of membership>]
|
||||||
|
@ -682,6 +701,73 @@ public:
|
||||||
*/
|
*/
|
||||||
VERB_NETWORK_CONFIG = 0x0c,
|
VERB_NETWORK_CONFIG = 0x0c,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request endpoints for multicast distribution:
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[1] flags>
|
||||||
|
* <[6] MAC address of multicast group being queried>
|
||||||
|
* <[4] 32-bit ADI for multicast group being queried>
|
||||||
|
* <[4] 32-bit requested max number of multicast peers>
|
||||||
|
*
|
||||||
|
* This message asks a peer for additional known endpoints that have
|
||||||
|
* LIKEd a given multicast group. It's sent when the sender wishes
|
||||||
|
* to send multicast but does not have the desired number of recipient
|
||||||
|
* peers.
|
||||||
|
*
|
||||||
|
* OK response payload: (multiple OKs can be generated)
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[6] MAC address of multicast group being queried>
|
||||||
|
* <[4] 32-bit ADI for multicast group being queried>
|
||||||
|
* <[4] 32-bit total number of known members in this multicast group>
|
||||||
|
* <[2] 16-bit number of members enumerated in this packet>
|
||||||
|
* <[...] series of 5-byte ZeroTier addresses of enumerated members>
|
||||||
|
*
|
||||||
|
* ERROR is not generated; queries that return no response are dropped.
|
||||||
|
*/
|
||||||
|
VERB_MULTICAST_GATHER = 0x0d,
|
||||||
|
|
||||||
|
/** *** DEPRECATED ***
|
||||||
|
* Multicast frame:
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[1] flags>
|
||||||
|
* [<[4] 32-bit implicit gather limit>]
|
||||||
|
* [<[6] source MAC>]
|
||||||
|
* <[6] destination MAC (multicast address)>
|
||||||
|
* <[4] 32-bit multicast ADI (multicast address extension)>
|
||||||
|
* <[2] 16-bit ethertype>
|
||||||
|
* <[...] ethernet payload>
|
||||||
|
*
|
||||||
|
* Flags:
|
||||||
|
* 0x01 - Network certificate of membership attached (DEPRECATED)
|
||||||
|
* 0x02 - Implicit gather limit field is present
|
||||||
|
* 0x04 - Source MAC is specified -- otherwise it's computed from sender
|
||||||
|
* 0x08 - Please replicate (sent to multicast replicators)
|
||||||
|
*
|
||||||
|
* OK and ERROR responses are optional. OK may be generated if there are
|
||||||
|
* implicit gather results or if the recipient wants to send its own
|
||||||
|
* updated certificate of network membership to the sender. ERROR may be
|
||||||
|
* generated if a certificate is needed or if multicasts to this group
|
||||||
|
* are no longer wanted (multicast unsubscribe).
|
||||||
|
*
|
||||||
|
* OK response payload:
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[6] MAC address of multicast group>
|
||||||
|
* <[4] 32-bit ADI for multicast group>
|
||||||
|
* <[1] flags>
|
||||||
|
* [<[...] network certificate of membership (DEPRECATED)>]
|
||||||
|
* [<[...] implicit gather results if flag 0x01 is set>]
|
||||||
|
*
|
||||||
|
* OK flags (same bits as request flags):
|
||||||
|
* 0x01 - OK includes certificate of network membership (DEPRECATED)
|
||||||
|
* 0x02 - OK includes implicit gather results
|
||||||
|
*
|
||||||
|
* ERROR response payload:
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[6] multicast group MAC>
|
||||||
|
* <[4] 32-bit multicast group ADI>
|
||||||
|
*/
|
||||||
|
VERB_MULTICAST_FRAME = 0x0e,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push of potential endpoints for direct communication:
|
* Push of potential endpoints for direct communication:
|
||||||
* <[2] 16-bit number of paths>
|
* <[2] 16-bit number of paths>
|
||||||
|
@ -784,77 +870,67 @@ public:
|
||||||
VERB_REMOTE_TRACE = 0x15,
|
VERB_REMOTE_TRACE = 0x15,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multipurpose VL2 network multicast:
|
* Peer-to-peer propagated multicast packet:
|
||||||
* <[5] start of range of addresses for propagation>
|
* <[128] 1024-bit bloom filter>
|
||||||
* <[5] end of range of addresses for propagation>
|
* <[2] 16-bit perturbation coefficient to minimize bloom collisions>
|
||||||
* <[1] 8-bit propagation depth / hops or 0xff to not propagate>
|
* <[5] 40-bit start of range of recipient addresses>
|
||||||
* <[1] 8-bit length of bloom filter in 256-byte/2048-bit chunks>
|
* <[5] 40-bit end of range of recipient addresses>
|
||||||
* <[...] propagation bloom filter>
|
* [... begin signed portion ...]
|
||||||
* [... start of signed portion ...]
|
* <[1] 8-bit flags>
|
||||||
* <[8] 64-bit timestamp>
|
* <[5] 40-bit ZeroTier address of sender>
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
* <[5] 40-bit address of sender>
|
|
||||||
* <[2] 16-bit length of multicast payload>
|
|
||||||
* [... start multicast payload ...]
|
|
||||||
* <[1] 8-bit payload type>
|
|
||||||
* [... end multicast payload and signed portion ...]
|
|
||||||
* <[2] 16-bit length of signature or 0 if not present>
|
|
||||||
* <[...] signature of signed portion>
|
|
||||||
*
|
|
||||||
* Payload type 0x00: multicast frame:
|
|
||||||
* <[6] MAC address of multicast group>
|
* <[6] MAC address of multicast group>
|
||||||
* <[4] 32-bit ADI of multicast group>
|
* <[4] 32-bit ADI for multicast group>
|
||||||
* <[6] 48-bit source MAC of packet or all 0 if from sender>
|
* <[6] MAC address of sender>
|
||||||
* <[2] 16-bit ethertype>
|
* <[2] 16-bit ethertype>
|
||||||
|
* <[2] 16-bit length of ethernet payload>
|
||||||
* <[...] ethernet payload>
|
* <[...] ethernet payload>
|
||||||
|
* [... end signed portion ...]
|
||||||
|
* <[2] 16-bit length of signature or 0 if unsigned>
|
||||||
|
* [<[...] optional signature of multicast>]
|
||||||
*
|
*
|
||||||
* Payload type 0x01: multicast subscribe:
|
* This packet contains a multicast that is to be peer-to-peer replicated.
|
||||||
* <[2] 16-bit number of multicast group IDs to subscribe>
|
* The range of recipient addresses is a subset of the global list of
|
||||||
* <[...] series of 32-bit multicast group IDs>
|
* subscribers to this multicast group. As the packet is propagated bits
|
||||||
*
|
* in the bloom filter will be set. The sender may attempt to select a
|
||||||
* Payload type 0x02: multicast unsubscribe:
|
* perturbation coefficient to prevent collisions within the selected
|
||||||
* <[2] 16-bit number of multicast group IDs to unsubscribe>
|
* recipient range.
|
||||||
* <[...] series of 32-bit multicast group IDs>
|
|
||||||
*
|
|
||||||
* This is the common packet structure for VL2 network-level multicasts
|
|
||||||
* and is used for multicast frames, multicast group subscribe and
|
|
||||||
* unsubscribe, and could be used in the future for other purposes such
|
|
||||||
* as credential propagation or diagnostics.
|
|
||||||
*
|
|
||||||
* The header contains an address range, bloom filter, and depth/hop
|
|
||||||
* counter. The bloom filter tracks which nodes have seen this multicast,
|
|
||||||
* with bits being set prior to send. The range allows the total set of
|
|
||||||
* subscribers to be partitioned in the case of huge networks that would
|
|
||||||
* saturate the bloom filter or have collisions. The propagation depth
|
|
||||||
* allows propagation to stop at some maximum value, and the value 0xff
|
|
||||||
* can be used to indicate that further propagation is not desired.
|
|
||||||
*
|
|
||||||
* Logic connected to the parsing of the multicast payload will determine
|
|
||||||
* whether or not and to whom this multicast is propagated. Subscribe and
|
|
||||||
* unsubscribe messages are propagated to online nodes up to a maximum
|
|
||||||
* depth, while frames have the added constraint of being propagated only
|
|
||||||
* to nodes that subscribe to the target multicast group.
|
|
||||||
*/
|
*/
|
||||||
VERB_VL2_MULTICAST = 0x16,
|
VERB_MULTICAST = 0x16,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Negotiate a new ephemeral key:
|
* Negotiate a new ephemeral key:
|
||||||
* <[8] first 64 bits of SHA-384 of currently known key for destination>
|
* <[48] SHA384 of ephemeral key we currently have for recipient>
|
||||||
* <[...] ephemeral key for sender>
|
* [<[...] sender's ephemeral key>]
|
||||||
*
|
*
|
||||||
* If the 64-bit hash of the currently known key sent by the sender does
|
* REKEY is used to negotiate ephemeral keys. The first byte is a step
|
||||||
* not match the key the destination is currently using, the destination
|
* number from 0 to 2. Here's a new session initiated by Alice:
|
||||||
* will send its own REKEY after sending OK to ensure that keys are up to
|
|
||||||
* date on both sides. This causes either side sending REKEY to trigger
|
|
||||||
* an automatic two-way handshake. Either side may therefore rekey at
|
|
||||||
* any time, though a rate limit should be in effect to prevent flooding.
|
|
||||||
*
|
*
|
||||||
* OK payload:
|
* Alice: REKEY[0x000...,AliceKey] -> Bob
|
||||||
* <[8] first 64 bits of SHA-384 of received ephemeral key>
|
* Bob: REKEY[SHA384(AliceKey),BobKey] -> Alice
|
||||||
|
* Alice: REKEY[SHA384(BobKey),(omitted)] -> Bob
|
||||||
|
*
|
||||||
|
* REKEY messages will continue until both sides have acknowledged each
|
||||||
|
* others' keys. Either Alice or Bob can send REKEY to negotiate a new
|
||||||
|
* ephemeral key pair at any time.
|
||||||
|
*
|
||||||
|
* OK isn't used because this is an ongoing handshake until both sides
|
||||||
|
* agree on a key. REKEY triggers a REKEY in reply if the hash for the
|
||||||
|
* recipient's ephemeral public key doesn't match the ephemeral key it
|
||||||
|
* wants to use.
|
||||||
*/
|
*/
|
||||||
VERB_REKEY = 0x17
|
VERB_REKEY = 0x17,
|
||||||
|
|
||||||
// TODO: legacy multicast message types must be supported
|
/**
|
||||||
|
* Encapsulate a full ZeroTier packet in another:
|
||||||
|
* <[...] raw encapsulated packet>
|
||||||
|
*
|
||||||
|
* Encapsulation exists to enable secure relaying as opposed to the usual
|
||||||
|
* "dumb" relaying. The latter is faster but secure relaying has roles
|
||||||
|
* where endpoint privacy is desired. Multiply nested ENCAP packets
|
||||||
|
* could allow ZeroTier to act as an onion router.
|
||||||
|
*/
|
||||||
|
VERB_ENCAP = 0x18
|
||||||
|
|
||||||
// protocol max: 0x1f
|
// protocol max: 0x1f
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue