mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 20:43:44 +02:00
Minor future proofing and cleanup in CertificateOfMembership, improve comments in a few places.
This commit is contained in:
parent
6b49148d4e
commit
a8db4a8d2d
9 changed files with 74 additions and 48 deletions
|
@ -17,15 +17,15 @@ namespace ZeroTier {
|
||||||
|
|
||||||
CertificateOfMembership::CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
|
CertificateOfMembership::CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
|
||||||
{
|
{
|
||||||
_qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP;
|
_qualifiers[COM_RESERVED_ID_TIMESTAMP].id = COM_RESERVED_ID_TIMESTAMP;
|
||||||
_qualifiers[0].value = timestamp;
|
_qualifiers[COM_RESERVED_ID_TIMESTAMP].value = timestamp;
|
||||||
_qualifiers[0].maxDelta = timestampMaxDelta;
|
_qualifiers[COM_RESERVED_ID_TIMESTAMP].maxDelta = timestampMaxDelta;
|
||||||
_qualifiers[1].id = COM_RESERVED_ID_NETWORK_ID;
|
_qualifiers[COM_RESERVED_ID_NETWORK_ID].id = COM_RESERVED_ID_NETWORK_ID;
|
||||||
_qualifiers[1].value = nwid;
|
_qualifiers[COM_RESERVED_ID_NETWORK_ID].value = nwid;
|
||||||
_qualifiers[1].maxDelta = 0;
|
_qualifiers[COM_RESERVED_ID_NETWORK_ID].maxDelta = 0;
|
||||||
_qualifiers[2].id = COM_RESERVED_ID_ISSUED_TO;
|
_qualifiers[COM_RESERVED_ID_ISSUED_TO].id = COM_RESERVED_ID_ISSUED_TO;
|
||||||
_qualifiers[2].value = issuedTo.toInt();
|
_qualifiers[COM_RESERVED_ID_ISSUED_TO].value = issuedTo.toInt();
|
||||||
_qualifiers[2].maxDelta = 0xffffffffffffffffULL;
|
_qualifiers[COM_RESERVED_ID_ISSUED_TO].maxDelta = 0xffffffffffffffffULL;
|
||||||
_qualifierCount = 3;
|
_qualifierCount = 3;
|
||||||
_signatureLength = 0;
|
_signatureLength = 0;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ bool CertificateOfMembership::sign(const Identity &with)
|
||||||
|
|
||||||
int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX]) const noexcept
|
int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX]) const noexcept
|
||||||
{
|
{
|
||||||
data[0] = 1;
|
data[0] = 1; // 96-byte signature length; a v2 is supported in unmarshal code where signature is length prefixed
|
||||||
Utils::storeBigEndian<uint16_t>(data + 1,(uint16_t)_qualifierCount);
|
Utils::storeBigEndian<uint16_t>(data + 1,(uint16_t)_qualifierCount);
|
||||||
int p = 3;
|
int p = 3;
|
||||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||||
|
@ -117,10 +117,6 @@ int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MAR
|
||||||
}
|
}
|
||||||
_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
|
_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
|
||||||
if ((_signedBy)&&(_signatureLength == 96)) {
|
if ((_signedBy)&&(_signatureLength == 96)) {
|
||||||
// UGLY: Ed25519 signatures in ZT are 96 bytes (64 + 32 bytes of hash).
|
|
||||||
// P-384 signatures are also 96 bytes, praise the horned one. That means
|
|
||||||
// we don't need to include a length. If we ever do we will need a new
|
|
||||||
// serialized object version, but only for those with length != 96.
|
|
||||||
memcpy(data + p,_signature,96); p += 96;
|
memcpy(data + p,_signature,96); p += 96;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
|
@ -128,7 +124,7 @@ int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MAR
|
||||||
|
|
||||||
int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept
|
int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept
|
||||||
{
|
{
|
||||||
if ((len < 3)||(data[0] != 1))
|
if ((len < 3)||(data[0] == 0))
|
||||||
return -1;
|
return -1;
|
||||||
unsigned int numq = Utils::loadBigEndian<uint16_t>(data + 1);
|
unsigned int numq = Utils::loadBigEndian<uint16_t>(data + 1);
|
||||||
if (numq > ZT_NETWORK_COM_MAX_QUALIFIERS)
|
if (numq > ZT_NETWORK_COM_MAX_QUALIFIERS)
|
||||||
|
@ -146,9 +142,19 @@ int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept
|
||||||
return -1;
|
return -1;
|
||||||
_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH;
|
_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH;
|
||||||
if (_signedBy) {
|
if (_signedBy) {
|
||||||
if ((p + 96) > len)
|
|
||||||
return -1;
|
|
||||||
_signatureLength = 96;
|
_signatureLength = 96;
|
||||||
|
if (data[0] > 1) {
|
||||||
|
// If the version byte is >1, signatures come prefixed by a length. This is the
|
||||||
|
// way it should have been in the first place. Version byte 1 indicates 96 byte
|
||||||
|
// signatures and is backward compatible with <2.x nodes.
|
||||||
|
if ((p + 2) >= len)
|
||||||
|
return -1;
|
||||||
|
_signatureLength = Utils::loadBigEndian<uint16_t>(data + p); p += 2;
|
||||||
|
if (_signatureLength == 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((p + _signatureLength) > len)
|
||||||
|
return -1;
|
||||||
memcpy(_signature,data + p,96);
|
memcpy(_signature,data + p,96);
|
||||||
p += 96;
|
p += 96;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,8 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE int64_t timestamp() const noexcept
|
ZT_ALWAYS_INLINE int64_t timestamp() const noexcept
|
||||||
{
|
{
|
||||||
|
if (_qualifiers[COM_RESERVED_ID_TIMESTAMP].id == COM_RESERVED_ID_TIMESTAMP)
|
||||||
|
return (int64_t)_qualifiers[0].value;
|
||||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||||
if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP)
|
if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP)
|
||||||
return (int64_t)_qualifiers[i].value;
|
return (int64_t)_qualifiers[i].value;
|
||||||
|
@ -141,6 +143,8 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE Address issuedTo() const noexcept
|
ZT_ALWAYS_INLINE Address issuedTo() const noexcept
|
||||||
{
|
{
|
||||||
|
if (_qualifiers[COM_RESERVED_ID_ISSUED_TO].id == COM_RESERVED_ID_ISSUED_TO)
|
||||||
|
return Address(_qualifiers[2].value);
|
||||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||||
if (_qualifiers[i].id == COM_RESERVED_ID_ISSUED_TO)
|
if (_qualifiers[i].id == COM_RESERVED_ID_ISSUED_TO)
|
||||||
return Address(_qualifiers[i].value);
|
return Address(_qualifiers[i].value);
|
||||||
|
@ -153,6 +157,8 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE uint64_t networkId() const noexcept
|
ZT_ALWAYS_INLINE uint64_t networkId() const noexcept
|
||||||
{
|
{
|
||||||
|
if (_qualifiers[COM_RESERVED_ID_NETWORK_ID].id == COM_RESERVED_ID_NETWORK_ID)
|
||||||
|
return _qualifiers[COM_RESERVED_ID_NETWORK_ID].value;
|
||||||
for(unsigned int i=0;i<_qualifierCount;++i) {
|
for(unsigned int i=0;i<_qualifierCount;++i) {
|
||||||
if (_qualifiers[i].id == COM_RESERVED_ID_NETWORK_ID)
|
if (_qualifiers[i].id == COM_RESERVED_ID_NETWORK_ID)
|
||||||
return _qualifiers[i].value;
|
return _qualifiers[i].value;
|
||||||
|
|
12
node/FCV.hpp
12
node/FCV.hpp
|
@ -242,7 +242,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE bool operator==(const FCV &v) const
|
ZT_ALWAYS_INLINE bool operator==(const FCV &v) const noexcept
|
||||||
{
|
{
|
||||||
if (_s == v._s) {
|
if (_s == v._s) {
|
||||||
for(unsigned int i=0;i<_s;++i) {
|
for(unsigned int i=0;i<_s;++i) {
|
||||||
|
@ -253,11 +253,11 @@ public:
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ZT_ALWAYS_INLINE bool operator!=(const FCV &v) const { return (!(*this == v)); }
|
ZT_ALWAYS_INLINE bool operator!=(const FCV &v) const noexcept { return (!(*this == v)); }
|
||||||
ZT_ALWAYS_INLINE bool operator<(const FCV &v) const { return std::lexicographical_compare(begin(),end(),v.begin(),v.end()); }
|
ZT_ALWAYS_INLINE bool operator<(const FCV &v) const noexcept { return std::lexicographical_compare(begin(),end(),v.begin(),v.end()); }
|
||||||
ZT_ALWAYS_INLINE bool operator>(const FCV &v) const { return (v < *this); }
|
ZT_ALWAYS_INLINE bool operator>(const FCV &v) const noexcept { return (v < *this); }
|
||||||
ZT_ALWAYS_INLINE bool operator<=(const FCV &v) const { return !(v < *this); }
|
ZT_ALWAYS_INLINE bool operator<=(const FCV &v) const noexcept { return !(v < *this); }
|
||||||
ZT_ALWAYS_INLINE bool operator>=(const FCV &v) const { return !(*this < v); }
|
ZT_ALWAYS_INLINE bool operator>=(const FCV &v) const noexcept { return !(*this < v); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int _s;
|
unsigned int _s;
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "SelfAwareness.hpp"
|
#include "SelfAwareness.hpp"
|
||||||
#include "Network.hpp"
|
#include "Network.hpp"
|
||||||
#include "Trace.hpp"
|
#include "Trace.hpp"
|
||||||
#include "ScopedPtr.hpp"
|
|
||||||
#include "Locator.hpp"
|
#include "Locator.hpp"
|
||||||
#include "Protocol.hpp"
|
#include "Protocol.hpp"
|
||||||
#include "Expect.hpp"
|
#include "Expect.hpp"
|
||||||
|
@ -112,6 +111,8 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
|
||||||
stateObjectPut(tPtr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
|
stateObjectPut(tPtr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RR->identity.hashWithPrivate(RR->localCacheSymmetricKey);
|
||||||
|
|
||||||
// This constructs all the components of the ZeroTier core within a single contiguous memory container,
|
// This constructs all the components of the ZeroTier core within a single contiguous memory container,
|
||||||
// which reduces memory fragmentation and may improve cache locality.
|
// which reduces memory fragmentation and may improve cache locality.
|
||||||
_objects = new _NodeObjects(RR,tPtr);
|
_objects = new _NodeObjects(RR,tPtr);
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
namespace Protocol {
|
namespace Protocol {
|
||||||
|
|
||||||
|
// The counter used to assign packet IDs / cryptographic nonces.
|
||||||
|
std::atomic<uint64_t> _s_packetIdCtr((uint64_t)time(nullptr) << 32U);
|
||||||
|
|
||||||
uint64_t createProbe(const Identity &sender,const Identity &recipient,const uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) noexcept
|
uint64_t createProbe(const Identity &sender,const Identity &recipient,const uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) noexcept
|
||||||
{
|
{
|
||||||
uint8_t tmp[ZT_IDENTITY_HASH_SIZE + ZT_IDENTITY_HASH_SIZE];
|
uint8_t tmp[ZT_IDENTITY_HASH_SIZE + ZT_IDENTITY_HASH_SIZE];
|
||||||
|
@ -37,8 +40,6 @@ uint64_t createProbe(const Identity &sender,const Identity &recipient,const uint
|
||||||
return hash[0];
|
return hash[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::atomic<uint64_t> _s_packetIdCtr((uint64_t)time(nullptr) << 32U);
|
|
||||||
|
|
||||||
void armor(Buf &pkt,int packetSize,const uint8_t key[ZT_PEER_SECRET_KEY_LENGTH],uint8_t cipherSuite) noexcept
|
void armor(Buf &pkt,int packetSize,const uint8_t key[ZT_PEER_SECRET_KEY_LENGTH],uint8_t cipherSuite) noexcept
|
||||||
{
|
{
|
||||||
Protocol::Header &ph = pkt.as<Protocol::Header>();
|
Protocol::Header &ph = pkt.as<Protocol::Header>();
|
||||||
|
|
|
@ -30,12 +30,16 @@ class Trace;
|
||||||
class Expect;
|
class Expect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds global state for an instance of ZeroTier::Node
|
* ZeroTier::Node execution context
|
||||||
|
*
|
||||||
|
* This just holds pointers and various other information used by all the
|
||||||
|
* various moving parts of a node. It's stored or passed as 'RR' to give it
|
||||||
|
* a common name througout the code.
|
||||||
*/
|
*/
|
||||||
class RuntimeEnvironment
|
class RuntimeEnvironment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZT_ALWAYS_INLINE RuntimeEnvironment(Node *n) :
|
ZT_ALWAYS_INLINE RuntimeEnvironment(Node *n) noexcept :
|
||||||
node(n),
|
node(n),
|
||||||
localNetworkController(nullptr),
|
localNetworkController(nullptr),
|
||||||
rtmem(nullptr),
|
rtmem(nullptr),
|
||||||
|
@ -53,6 +57,7 @@ public:
|
||||||
ZT_ALWAYS_INLINE ~RuntimeEnvironment()
|
ZT_ALWAYS_INLINE ~RuntimeEnvironment()
|
||||||
{
|
{
|
||||||
Utils::burn(secretIdentityStr,sizeof(secretIdentityStr));
|
Utils::burn(secretIdentityStr,sizeof(secretIdentityStr));
|
||||||
|
Utils::burn(localCacheSymmetricKey,sizeof(localCacheSymmetricKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node instance that owns this RuntimeEnvironment
|
// Node instance that owns this RuntimeEnvironment
|
||||||
|
@ -64,12 +69,6 @@ public:
|
||||||
// Memory actually occupied by Trace, Switch, etc.
|
// Memory actually occupied by Trace, Switch, etc.
|
||||||
void *rtmem;
|
void *rtmem;
|
||||||
|
|
||||||
/* Order matters a bit here. These are constructed in this order
|
|
||||||
* and then deleted in the opposite order on Node exit. The order ensures
|
|
||||||
* that things that are needed are there before they're needed.
|
|
||||||
*
|
|
||||||
* These are constant and never null after startup unless indicated. */
|
|
||||||
|
|
||||||
Trace *t;
|
Trace *t;
|
||||||
Expect *expect;
|
Expect *expect;
|
||||||
VL2 *vl2;
|
VL2 *vl2;
|
||||||
|
@ -81,6 +80,10 @@ public:
|
||||||
Identity identity;
|
Identity identity;
|
||||||
char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
||||||
char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
||||||
|
|
||||||
|
// A hash of this node identity's public and private keys that is used as
|
||||||
|
// a secret key to encrypt locally cached sensitive information.
|
||||||
|
uint8_t localCacheSymmetricKey[ZT_IDENTITY_HASH_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -1198,7 +1198,7 @@ int main(int argc,char **argv)
|
||||||
ok &= ZTT_crypto() == nullptr;
|
ok &= ZTT_crypto() == nullptr;
|
||||||
ok &= ZTT_benchmarkCrypto() == nullptr;
|
ok &= ZTT_benchmarkCrypto() == nullptr;
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
ZT_T_PRINTF(ZT_EOL_S "At least one error occurred!" ZT_EOL_S);
|
ZT_T_PRINTF(ZT_EOL_S "*** AT LEAST ONE TEST FAILED! ***" ZT_EOL_S);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
34
node/Tests.h
34
node/Tests.h
|
@ -18,20 +18,24 @@
|
||||||
* To build these ensure that ZT_ENABLE_TESTS is defined during build time.
|
* To build these ensure that ZT_ENABLE_TESTS is defined during build time.
|
||||||
* Otherwise they are omitted.
|
* Otherwise they are omitted.
|
||||||
*
|
*
|
||||||
|
* The macro ZT_STANDALONE_TESTS will also build a main() function for these
|
||||||
|
* tests for creating a stand-alone test executable. It will return zero if
|
||||||
|
* all tests pass and non-zero if at least one test fails.
|
||||||
|
*
|
||||||
* These symbols are defined extern "C" so tests can be called from regular
|
* These symbols are defined extern "C" so tests can be called from regular
|
||||||
* C code, which is important for use via CGo or in plain C projects.
|
* C code, which is important for use via CGo or in plain C projects.
|
||||||
*
|
*
|
||||||
* The ZT_T_PRINTF macro defaults to printf() but if it's defined at compile
|
* The ZT_T_PRINTF macro defaults to printf() but if it's defined at compile
|
||||||
* time (also must be set while building Tests.cpp) it can specify another
|
* time (it must be set while building Tests.cpp) it can specify another
|
||||||
* function to use for output. Defining it to a no-op can be used to disable
|
* function to use for output. Defining it to a no-op can be used to disable
|
||||||
* output.
|
* output.
|
||||||
*
|
*
|
||||||
* Each test function returns NULL if the tests succeeds or an error message
|
* Each test function returns NULL if the tests succeeds or an error message
|
||||||
* on test failure.
|
* on test failure.
|
||||||
*
|
*
|
||||||
* Only the fuzzing test functions are thread-safe. Other test functions
|
* Be aware that fuzzing tests can and will crash the program if a serious
|
||||||
* should not be called concurrently. It's okay to call different tests from
|
* error is discovered. This is the point. It's also beneficial to run these
|
||||||
* different threads, but not the same test.
|
* in "valgrind" or a similar tool to detect marginal bad behvaior.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZT_TESTS_HPP
|
#ifndef ZT_TESTS_HPP
|
||||||
|
@ -52,20 +56,24 @@ extern "C" {
|
||||||
#define ZT_T_PRINTF(fmt,...) printf((fmt),##__VA_ARGS__),fflush(stdout)
|
#define ZT_T_PRINTF(fmt,...) printf((fmt),##__VA_ARGS__),fflush(stdout)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Basic self-tests ---------------------------------------------------------------------------------------------------
|
/**
|
||||||
|
* Test platform, compiler behavior, utility functions, and core classes
|
||||||
|
*/
|
||||||
const char *ZTT_general();
|
const char *ZTT_general();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test crypto using test vectors and simple scenarios
|
||||||
|
*
|
||||||
|
* This is not an absolutely exhaustive test, just a sanity check to make sure
|
||||||
|
* crypto routines are basically working.
|
||||||
|
*/
|
||||||
const char *ZTT_crypto();
|
const char *ZTT_crypto();
|
||||||
|
|
||||||
// Benchmarks ---------------------------------------------------------------------------------------------------------
|
/**
|
||||||
|
* Run benchmarks of cryptographic routines and common constructions
|
||||||
|
*/
|
||||||
const char *ZTT_benchmarkCrypto();
|
const char *ZTT_benchmarkCrypto();
|
||||||
|
|
||||||
// Fuzzing ------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -327,6 +327,7 @@ public:
|
||||||
void saveAll(void *tPtr);
|
void saveAll(void *tPtr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Load cached peer and set 'peer' to it, if one is found.
|
||||||
void _loadCached(void *tPtr,const Address &zta,SharedPtr<Peer> &peer);
|
void _loadCached(void *tPtr,const Address &zta,SharedPtr<Peer> &peer);
|
||||||
|
|
||||||
// This is a secure random integer created at startup to salt the calculation of path hash map keys
|
// This is a secure random integer created at startup to salt the calculation of path hash map keys
|
||||||
|
|
Loading…
Add table
Reference in a new issue