Adam Ierymenko 5 years ago
parent
commit
5a29f9ba2d
7 changed files with 90 additions and 60 deletions
  1. 1 0
      node/CMakeLists.txt
  2. 35 0
      node/Capability.cpp
  3. 14 29
      node/Capability.hpp
  4. 5 5
      node/Credential.hpp
  5. 2 2
      node/Identity.cpp
  6. 27 17
      node/Packet.cpp
  7. 6 7
      node/Packet.hpp

+ 1 - 0
node/CMakeLists.txt

@@ -51,6 +51,7 @@ set(core_src
 	AES.cpp
 	Buf.cpp
 	C25519.cpp
+	Capability.cpp
 	Credential.cpp
 	ECC384.cpp
 	Endpoint.cpp

+ 35 - 0
node/Capability.cpp

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c)2013-2020 ZeroTier, Inc.
+ *
+ * Use of this software is governed by the Business Source License included
+ * in the LICENSE.TXT file in the project's root directory.
+ *
+ * Change Date: 2024-01-01
+ *
+ * On the date above, in accordance with the Business Source License, use
+ * of this software will be governed by version 2.0 of the Apache License.
+ */
+/****/
+
+#include "Capability.hpp"
+
+namespace ZeroTier {
+
+bool Capability::sign(const Identity &from,const Address &to)
+{
+	try {
+		for(unsigned int i=0;((i<_maxCustodyChainLength)&&(i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH));++i) {
+			if (!(_custody[i].to)) {
+				Buffer<(sizeof(Capability) * 2)> tmp;
+				this->serialize(tmp,true);
+				_custody[i].to = to;
+				_custody[i].from = from.address();
+				_custody[i].signatureLength = from.sign(tmp.data(),tmp.size(),_custody[i].signature,sizeof(_custody[i].signature));
+				return true;
+			}
+		}
+	} catch ( ... ) {}
+	return false;
+}
+
+} // namespace ZeroTier

+ 14 - 29
node/Capability.hpp

@@ -58,9 +58,9 @@ class Capability : public Credential
 	friend class Credential;
 
 public:
-	static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_CAPABILITY; }
+	static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_CAPABILITY; }
 
-	inline Capability() :
+	ZT_ALWAYS_INLINE Capability() :
 		_nwid(0),
 		_ts(0),
 		_id(0),
@@ -79,7 +79,7 @@ public:
 	 * @param rules Network flow rules for this capability
 	 * @param ruleCount Number of flow rules
 	 */
-	inline Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) :
+	ZT_ALWAYS_INLINE Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) :
 		_nwid(nwid),
 		_ts(ts),
 		_id(id),
@@ -93,32 +93,32 @@ public:
 	/**
 	 * @return Rules -- see ruleCount() for size of array
 	 */
-	inline const ZT_VirtualNetworkRule *rules() const { return _rules; }
+	ZT_ALWAYS_INLINE const ZT_VirtualNetworkRule *rules() const { return _rules; }
 
 	/**
 	 * @return Number of rules in rules()
 	 */
-	inline unsigned int ruleCount() const { return _ruleCount; }
+	ZT_ALWAYS_INLINE unsigned int ruleCount() const { return _ruleCount; }
 
 	/**
 	 * @return ID and evaluation order of this capability in network
 	 */
-	inline uint32_t id() const { return _id; }
+	ZT_ALWAYS_INLINE uint32_t id() const { return _id; }
 
 	/**
 	 * @return Network ID for which this capability was issued
 	 */
-	inline uint64_t networkId() const { return _nwid; }
+	ZT_ALWAYS_INLINE uint64_t networkId() const { return _nwid; }
 
 	/**
 	 * @return Timestamp
 	 */
-	inline int64_t timestamp() const { return _ts; }
+	ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; }
 
 	/**
 	 * @return Last 'to' address in chain of custody
 	 */
-	inline Address issuedTo() const
+	ZT_ALWAYS_INLINE Address issuedTo() const
 	{
 		Address i2;
 		for(unsigned int i=0;i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++i) {
@@ -142,29 +142,14 @@ public:
 	 * @param to Recipient of this signature
 	 * @return True if signature successful and chain of custody appended
 	 */
-	inline bool sign(const Identity &from,const Address &to)
-	{
-		try {
-			for(unsigned int i=0;((i<_maxCustodyChainLength)&&(i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH));++i) {
-				if (!(_custody[i].to)) {
-					Buffer<(sizeof(Capability) * 2)> tmp;
-					this->serialize(tmp,true);
-					_custody[i].to = to;
-					_custody[i].from = from.address();
-					_custody[i].signatureLength = from.sign(tmp.data(),tmp.size(),_custody[i].signature,sizeof(_custody[i].signature));
-					return true;
-				}
-			}
-		} catch ( ... ) {}
-		return false;
-	}
+	bool sign(const Identity &from,const Address &to);
 
 	/**
 	 * Verify this capability's chain of custody and signatures
 	 *
 	 * @param RR Runtime environment to provide for peer lookup, etc.
 	 */
-	inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
+	ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
 
 	template<unsigned int C>
 	static inline void serializeRules(Buffer<C> &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount)
@@ -459,10 +444,10 @@ public:
 	}
 
 	// Provides natural sort order by ID
-	inline bool operator<(const Capability &c) const { return (_id < c._id); }
+	ZT_ALWAYS_INLINE bool operator<(const Capability &c) const { return (_id < c._id); }
 
-	inline bool operator==(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) == 0); }
-	inline bool operator!=(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) != 0); }
+	ZT_ALWAYS_INLINE bool operator==(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) == 0); }
+	ZT_ALWAYS_INLINE bool operator!=(const Capability &c) const { return (memcmp(this,&c,sizeof(Capability)) != 0); }
 
 private:
 	uint64_t _nwid;

+ 5 - 5
node/Credential.hpp

@@ -64,11 +64,11 @@ public:
 	};
 
 protected:
-	VerifyResult _verify(const RuntimeEnvironment *const RR,void *tPtr,const CertificateOfMembership &credential) const;
-	VerifyResult _verify(const RuntimeEnvironment *const RR,void *tPtr,const Revocation &credential) const;
-	VerifyResult _verify(const RuntimeEnvironment *const RR,void *tPtr,const Tag &credential) const;
-	VerifyResult _verify(const RuntimeEnvironment *const RR,void *tPtr,const CertificateOfOwnership &credential) const;
-	VerifyResult _verify(const RuntimeEnvironment *const RR,void *tPtr,const Capability &credential) const;
+	VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const CertificateOfMembership &credential) const;
+	VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const Revocation &credential) const;
+	VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const Tag &credential) const;
+	VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const CertificateOfOwnership &credential) const;
+	VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const Capability &credential) const;
 };
 
 } // namespace ZeroTier

+ 2 - 2
node/Identity.cpp

@@ -264,7 +264,7 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
 			}
 			*p = (char)0;
 			return buf;
-		} break;
+		}
 
 		case P384: {
 			char *p = buf;
@@ -284,7 +284,7 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
 			}
 			*p = (char)0;
 			return buf;
-		}	break;
+		}
 
 	}
 	return nullptr;

+ 27 - 17
node/Packet.cpp

@@ -18,9 +18,16 @@
 #include "Mutex.hpp"
 #include "LZ4.hpp"
 
+#if (defined(_MSC_VER) || defined(__GNUC__) || defined(__clang)) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
+#define ZT_PACKET_USE_ATOMIC_INTRINSICS
+#endif
+#ifndef ZT_PACKET_USE_ATOMIC_INTRINSICS
+#include <atomic>
+#endif
+
 namespace ZeroTier {
 
-const unsigned char Packet::ZERO_KEY[32] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+const uint8_t Packet::ZERO_KEY[32] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
 
 void Packet::armor(const void *key,bool encryptPayload)
 {
@@ -116,24 +123,27 @@ bool Packet::uncompress()
 	return true;
 }
 
+static unsigned long long s_initPacketID()
+{
+	unsigned long long tmp = 0;
+	Utils::getSecureRandom(&tmp,sizeof(tmp));
+	tmp >>= 31U;
+	tmp |= (((uint64_t)time(nullptr)) & 0xffffffffULL) << 33U;
+	return tmp;
+}
+#ifdef ZT_PACKET_USE_ATOMIC_INTRINSICS
+static unsigned long long s_packetIdCtr = s_initPacketID();
+#else
+static std::atomic<unsigned long long> s_packetIdCtr(s_initPacketID());
+#endif
+
 uint64_t Packet::nextPacketId()
 {
-	// The packet ID which is also the packet's nonce/IV can be sequential but
-	// it should never repeat. This scheme minimizes the chance of nonce
-	// repetition if (as will usually be the case) the clock is relatively
-	// accurate.
-
-	static uint64_t ctr = 0;
-	static Mutex lock;
-	lock.lock();
-	while (ctr == 0) {
-		Utils::getSecureRandom(&ctr,sizeof(ctr));
-		ctr >>= 32;
-		ctr |= (((uint64_t)time(nullptr)) & 0xffffffffULL) << 32;
-	}
-	const uint64_t i = ctr++;
-	lock.unlock();
-	return i;
+#ifdef ZT_PACKET_USE_ATOMIC_INTRINSICS
+	return __sync_add_and_fetch(&s_packetIdCtr,1ULL);
+#else
+	return ++s_packetIdCtr;
+#endif
 }
 
 } // namespace ZeroTier

+ 6 - 7
node/Packet.hpp

@@ -1174,8 +1174,7 @@ public:
 	bool uncompress();
 
 private:
-	static const unsigned char ZERO_KEY[32];
-
+	static const uint8_t ZERO_KEY[32];
 	static uint64_t nextPacketId();
 
 	/**
@@ -1189,9 +1188,9 @@ private:
 	 * @param in Input key (32 bytes)
 	 * @param out Output buffer (32 bytes)
 	 */
-	inline void _salsa20MangleKey(const unsigned char *in,unsigned char *out) const
+	ZT_ALWAYS_INLINE void _salsa20MangleKey(const uint8_t *in,uint8_t *out) const
 	{
-		const unsigned char *d = (const unsigned char *)data();
+		const uint8_t *const d = (const unsigned char *)data();
 
 		// IV and source/destination addresses. Using the addresses divides the
 		// key space into two halves-- A->B and B->A (since order will change).
@@ -1201,12 +1200,12 @@ private:
 		// Flags, but with hop count masked off. Hop count is altered by forwarding
 		// nodes. It's one of the only parts of a packet modifiable by people
 		// without the key.
-		out[18] = in[18] ^ (d[ZT_PACKET_IDX_FLAGS] & 0xf8);
+		out[18] = in[18] ^ (d[ZT_PACKET_IDX_FLAGS] & 0xf8U);
 
 		// Raw packet size in bytes -- thus each packet size defines a new
 		// key space.
-		out[19] = in[19] ^ (unsigned char)(size() & 0xff);
-		out[20] = in[20] ^ (unsigned char)((size() >> 8) & 0xff); // little endian
+		out[19] = in[19] ^ (uint8_t)size();
+		out[20] = in[20] ^ (uint8_t)(size() >> 8U); // little endian
 
 		// Rest of raw key is used unchanged
 		for(unsigned int i=21;i<32;++i)