Browse Source

Various little things...

Adam Ierymenko 5 years ago
parent
commit
8c8a3c58ec
7 changed files with 94 additions and 76 deletions
  1. 18 0
      node/Endpoint.cpp
  2. 5 0
      node/Endpoint.hpp
  3. 0 3
      node/Identity.hpp
  4. 48 35
      node/SHA512.cpp
  5. 1 32
      node/SHA512.hpp
  6. 2 2
      node/Topology.cpp
  7. 20 4
      node/VL1.cpp

+ 18 - 0
node/Endpoint.cpp

@@ -26,6 +26,7 @@ bool Endpoint::operator==(const Endpoint &ep) const
 			case ZEROTIER:    return ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) == 0));
 			case URL:         return (strcmp(_v.url,ep._v.url) == 0);
 			case ETHERNET:    return (_v.eth == ep._v.eth);
+			case WEBRTC:      return ((_v.webrtc.offerLen == ep._v.webrtc.offerLen)&&(memcmp(_v.webrtc.offer,ep._v.webrtc.offer,_v.webrtc.offerLen) == 0));
 		}
 	}
 	return false;
@@ -47,6 +48,11 @@ bool Endpoint::operator<(const Endpoint &ep) const
 			case ZEROTIER: return (_v.zt.a < ep._v.zt.a) ? true : ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) < 0));
 			case URL:      return (strcmp(_v.url,ep._v.url) < 0);
 			case ETHERNET: return (_v.eth < ep._v.eth);
+			case WEBRTC:
+				if (_v.webrtc.offerLen < ep._v.webrtc.offerLen)
+					return true;
+				else if (_v.webrtc.offerLen == ep._v.webrtc.offerLen)
+					return memcmp(_v.webrtc.offer,ep._v.webrtc.offer,_v.webrtc.offerLen) < 0;
 			default:       return false;
 		}
 	}
@@ -102,6 +108,10 @@ int Endpoint::marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept
 			data[11] = (uint8_t)(_v.eth >> 8U);
 			data[12] = (uint8_t)_v.eth;
 			return 13;
+		case WEBRTC:
+			Utils::storeBigEndian(data + 7,(uint16_t)_v.webrtc.offerLen);
+			memcpy(data + 9,_v.webrtc.offer,_v.webrtc.offerLen);
+			return 9 + _v.webrtc.offerLen;
 		default:
 			data[0] = (uint8_t)NIL;
 			return 7;
@@ -173,6 +183,14 @@ int Endpoint::unmarshal(const uint8_t *restrict data,const int len) noexcept
 			_v.eth |= ((uint64_t)data[11]) << 8U;
 			_v.eth |= (uint64_t)data[12];
 			return 13;
+  	case WEBRTC:
+  		if (len < 9)
+  			return -1;
+  		_v.webrtc.offerLen = Utils::loadBigEndian<uint16_t>(data + 7);
+  		if ((len < (9 + _v.webrtc.offerLen))||(_v.webrtc.offerLen > ZT_ENDPOINT_MAX_NAME_SIZE))
+  			return -1;
+  		memcpy(_v.webrtc.offer,data + 9,_v.webrtc.offerLen);
+  		return 9 + _v.webrtc.offerLen;
 		default:
 			// Unrecognized endpoint types not yet specified must start with a byte
 			// length size so that older versions of ZeroTier can skip them.

+ 5 - 0
node/Endpoint.hpp

@@ -48,6 +48,7 @@ public:
 		ZEROTIER =     4,   // ZeroTier Address (for relaying and meshy behavior)
 		URL =          5,   // URL for http/https/ws/etc. (not implemented yet)
 		ETHERNET =     6,   // 48-bit LAN-local Ethernet address
+		WEBRTC =       7,   // WebRTC data channels
 		UNRECOGNIZED = 255  // Unrecognized endpoint type encountered in stream
 	};
 
@@ -152,6 +153,10 @@ private:
 			uint16_t port;
 			char name[ZT_ENDPOINT_MAX_NAME_SIZE];
 		} dns;
+		struct {
+			uint16_t offerLen;
+			uint8_t offer[ZT_ENDPOINT_MAX_NAME_SIZE];
+		} webrtc;
 		struct {
 			uint64_t a;
 			uint8_t idh[ZT_IDENTITY_HASH_SIZE];

+ 0 - 3
node/Identity.hpp

@@ -46,9 +46,6 @@ namespace ZeroTier {
  * Type 1 identities also use a simpler mechanism to rate limit identity generation (as
  * a defense in depth against intentional collision) that makes local identity validation
  * faster, allowing full identity validation on all unmarshal() operations.
- *
- * The default is still type 0, but this may change in future versions once 1.x is no
- * longer common in the wild.
  */
 class Identity : public TriviallyCopyable
 {

+ 48 - 35
node/SHA512.cpp

@@ -3,8 +3,6 @@
 #include "SHA512.hpp"
 #include "Utils.hpp"
 
-#include <utility>
-#include <algorithm>
 #include <cstdint>
 #include <cstdlib>
 #include <cstring>
@@ -68,7 +66,7 @@ static const uint64_t K[80] = {
 #define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
 #define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
 
-static inline void sha512_compress(sha512_state *const md,uint8_t *const buf)
+static void sha512_compress(sha512_state *const md,uint8_t *const buf)
 {
 	uint64_t S[8], W[80], t0, t1;
 	int i;
@@ -101,7 +99,7 @@ static inline void sha512_compress(sha512_state *const md,uint8_t *const buf)
 		md->state[i] = md->state[i] + S[i];
 }
 
-static inline void sha384_init(sha512_state *const md)
+static ZT_ALWAYS_INLINE void sha384_init(sha512_state *const md)
 {
 	md->curlen = 0;
 	md->length = 0;
@@ -115,7 +113,7 @@ static inline void sha384_init(sha512_state *const md)
 	md->state[7] = 0x47b5481dbefa4fa4ULL;
 }
 
-static inline void sha512_init(sha512_state *const md)
+static ZT_ALWAYS_INLINE void sha512_init(sha512_state *const md)
 {
 	md->curlen = 0;
 	md->length = 0;
@@ -129,7 +127,7 @@ static inline void sha512_init(sha512_state *const md)
 	md->state[7] = 0x5be0cd19137e2179ULL;
 }
 
-static inline void sha512_process(sha512_state *const md,const uint8_t *in,unsigned long inlen)
+static ZT_ALWAYS_INLINE void sha512_process(sha512_state *const md,const uint8_t *in,unsigned long inlen)
 {
 	while (inlen > 0) {
 		if (md->curlen == 0 && inlen >= 128) {
@@ -152,7 +150,7 @@ static inline void sha512_process(sha512_state *const md,const uint8_t *in,unsig
 	}
 }
 
-static inline void sha512_done(sha512_state *const md,uint8_t *out)
+static ZT_ALWAYS_INLINE void sha512_done(sha512_state *const md,uint8_t *out)
 {
 	int i;
 
@@ -217,31 +215,49 @@ void HMACSHA384(const uint8_t key[32],const void *msg,const unsigned int msglen,
 	uint64_t kInPadded[16]; // input padded key
 	uint64_t outer[22]; // output padded key | H(input padded key | msg)
 
-#ifdef ZT_NO_UNALIGNED_ACCESS
-	for(int i=0;i<32;++i) ((uint8_t *)kInPadded)[i] = key[i] ^ 0x36;
-	for(int i=4;i<16;++i) kInPadded[i] = 0x3636363636363636ULL;
-	for(int i=0;i<32;++i) ((uint8_t *)outer)[i] = key[i] ^ 0x5c;
-	for(int i=4;i<16;++i) outer[i] = 0x5c5c5c5c5c5c5c5cULL;
-#else
-	{
-		const uint64_t k0 = ((const uint64_t *)key)[0];
-		const uint64_t k1 = ((const uint64_t *)key)[1];
-		const uint64_t k2 = ((const uint64_t *)key)[2];
-		const uint64_t k3 = ((const uint64_t *)key)[3];
-		kInPadded[0] = k0 ^ 0x3636363636363636ULL;
-		kInPadded[1] = k1 ^ 0x3636363636363636ULL;
-		kInPadded[2] = k2 ^ 0x3636363636363636ULL;
-		kInPadded[3] = k3 ^ 0x3636363636363636ULL;
-		for(int i=4;i<16;++i) kInPadded[i] = 0x3636363636363636ULL;
-		outer[0] = k0 ^ 0x5c5c5c5c5c5c5c5cULL;
-		outer[1] = k1 ^ 0x5c5c5c5c5c5c5c5cULL;
-		outer[2] = k2 ^ 0x5c5c5c5c5c5c5c5cULL;
-		outer[3] = k3 ^ 0x5c5c5c5c5c5c5c5cULL;
-		for(int i=4;i<16;++i) outer[i] = 0x5c5c5c5c5c5c5c5cULL;
-	}
-#endif
+	const uint64_t k0 = Utils::loadAsIsEndian<uint64_t>(key);
+	const uint64_t k1 = Utils::loadAsIsEndian<uint64_t>(key + 8);
+	const uint64_t k2 = Utils::loadAsIsEndian<uint64_t>(key + 16);
+	const uint64_t k3 = Utils::loadAsIsEndian<uint64_t>(key + 24);
+
+	const uint64_t ipad = 0x3636363636363636ULL;
+	kInPadded[0] = k0 ^ ipad;
+	kInPadded[1] = k1 ^ ipad;
+	kInPadded[2] = k2 ^ ipad;
+	kInPadded[3] = k3 ^ ipad;
+	kInPadded[4] = ipad;
+	kInPadded[5] = ipad;
+	kInPadded[6] = ipad;
+	kInPadded[7] = ipad;
+	kInPadded[8] = ipad;
+	kInPadded[9] = ipad;
+	kInPadded[10] = ipad;
+	kInPadded[11] = ipad;
+	kInPadded[12] = ipad;
+	kInPadded[13] = ipad;
+	kInPadded[14] = ipad;
+	kInPadded[15] = ipad;
+
+	const uint64_t opad = 0x5c5c5c5c5c5c5c5cULL;
+	outer[0] = k0 ^ opad;
+	outer[1] = k1 ^ opad;
+	outer[2] = k2 ^ opad;
+	outer[3] = k3 ^ opad;
+	outer[4] = opad;
+	outer[5] = opad;
+	outer[6] = opad;
+	outer[7] = opad;
+	outer[8] = opad;
+	outer[9] = opad;
+	outer[10] = opad;
+	outer[11] = opad;
+	outer[12] = opad;
+	outer[13] = opad;
+	outer[14] = opad;
+	outer[15] = opad;
+
+	SHA384(reinterpret_cast<uint8_t *>(outer) + 128,kInPadded,128,msg,msglen); // H(input padded key | msg)
 
-	SHA384(((uint8_t *)outer) + 128,kInPadded,128,msg,msglen); // H(input padded key | msg)
 	SHA384(mac,outer,176); // H(output padded key | H(input padded key | msg))
 }
 
@@ -249,10 +265,7 @@ void KBKDFHMACSHA384(const uint8_t key[32],const char label,const char context,c
 {
 	uint8_t kbkdfMsg[13];
 	uint8_t kbuf[48];
-	kbkdfMsg[0] = (uint8_t)(iter >> 24U);
-	kbkdfMsg[1] = (uint8_t)(iter >> 16U);
-	kbkdfMsg[2] = (uint8_t)(iter >> 8U);
-	kbkdfMsg[3] = (uint8_t)iter;
+	Utils::storeBigEndian<uint32_t>(kbkdfMsg,(uint32_t)iter);
 	kbkdfMsg[4] = (uint8_t)'Z';
 	kbkdfMsg[5] = (uint8_t)'T'; // preface our labels with something ZT-specific
 	kbkdfMsg[6] = (uint8_t)label;

+ 1 - 32
node/SHA512.hpp

@@ -18,10 +18,6 @@
 
 #ifdef __APPLE__
 #include <CommonCrypto/CommonDigest.h>
-#else
-#ifdef ZT_USE_LIBCRYPTO
-#include <openssl/sha.h>
-#endif
 #endif
 
 #define ZT_SHA512_DIGEST_LEN 64
@@ -34,6 +30,7 @@
 
 namespace ZeroTier {
 
+// SHA384 and SHA512 are actually in the standard libraries on MacOS and iOS
 #ifdef __APPLE__
 #define ZT_HAVE_NATIVE_SHA512 1
 static ZT_ALWAYS_INLINE void SHA512(void *digest,const void *data,unsigned int len)
@@ -60,34 +57,6 @@ static ZT_ALWAYS_INLINE void SHA384(void *digest,const void *data0,unsigned int
 }
 #endif
 
-#ifndef ZT_HAVE_NATIVE_SHA512
-#ifdef ZT_USE_LIBCRYPTO
-#define ZT_HAVE_NATIVE_SHA512 1
-static ZT_ALWAYS_INLINE void SHA512(void *digest,const void *data,unsigned int len)
-{
-	SHA512_CTX ctx;
-	SHA512_Init(&ctx);
-	SHA512_Update(&ctx,data,len);
-	SHA512_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
-}
-static ZT_ALWAYS_INLINE void SHA384(void *digest,const void *data,unsigned int len)
-{
-	SHA512_CTX ctx;
-	SHA384_Init(&ctx);
-	SHA384_Update(&ctx,data,len);
-	SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
-}
-static ZT_ALWAYS_INLINE void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
-{
-	SHA512_CTX ctx;
-	SHA384_Init(&ctx);
-	SHA384_Update(&ctx,data0,len0);
-	SHA384_Update(&ctx,data1,len1);
-	SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
-}
-#endif
-#endif
-
 #ifndef ZT_HAVE_NATIVE_SHA512
 void SHA512(void *digest,const void *data,unsigned int len);
 void SHA384(void *digest,const void *data,unsigned int len);

+ 2 - 2
node/Topology.cpp

@@ -62,7 +62,7 @@ Topology::Topology(const RuntimeEnvironment *renv,const Identity &myId,void *tPt
 		_loadCached(tPtr,r->address(),p);
 		if ((!p)||(p->identity() != *r)) {
 			p.set(new Peer(RR));
-			p->init(myId,*r);
+			p->init(*r);
 		}
 		_rootPeers.push_back(p);
 	}
@@ -147,7 +147,7 @@ void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstra
 		SharedPtr<Peer> &p = _peers[id.address()];
 		if (!p) {
 			p.set(new Peer(RR));
-			p->init(_myIdentity,id);
+			p->init(id);
 			if (bootstrap)
 				p->setBootstrap(Endpoint(bootstrap));
 		}

+ 20 - 4
node/VL1.cpp

@@ -676,6 +676,13 @@ bool VL1::_ERROR(void *tPtr,const SharedPtr<Path> &path,const SharedPtr<Peer> &p
 		return false;
 	}
 	Protocol::ERROR::Header &eh = pkt.as<Protocol::ERROR::Header>();
+
+	const int64_t now = RR->node->now();
+	if (!RR->expect->expecting(eh.inRePacketId,now)) {
+		RR->t->incomingPacketDropped(tPtr,0x4c1f1ff7,0,0,identityFromPeerPtr(peer),path->address(),0,Protocol::VERB_OK,ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED);
+		return false;
+	}
+
 	switch(eh.error) {
 
 		//case Protocol::ERROR_INVALID_REQUEST:
@@ -881,7 +888,7 @@ bool VL1::_PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr<Path> &path,const Shared
 	InetAddress a;
 	Endpoint ep;
 	for(unsigned int pi=0;pi<numPaths;++pi) {
-		/*const uint8_t flags = pkt.rI8(ptr);*/ ++ptr;
+		/*const uint8_t flags = pkt.rI8(ptr);*/ ++ptr; // flags are not presently used
 		ptr += pkt.rI16(ptr); // extended attributes size, currently always 0
 		const unsigned int addrType = pkt.rI8(ptr);
 		const unsigned int addrRecordLen = pkt.rI8(ptr);
@@ -908,6 +915,7 @@ bool VL1::_PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr<Path> &path,const Shared
 				addrLen = 16;
 				addrPort = pkt.rI16(ptr);
 				break;
+			default: break;
 		}
 
 		if (Buf::readOverflow(ptr,packetSize)) {
@@ -919,11 +927,18 @@ bool VL1::_PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr<Path> &path,const Shared
 			a.set(addrBytes,addrLen,addrPort);
 		} else if (addrLen) {
 			if (ep.unmarshal(reinterpret_cast<const uint8_t *>(addrBytes),(int)addrLen) <= 0) {
-				RR->t->incomingPacketDropped(tPtr,0xbad0f00d,pdp.h.packetId,0,peer->identity(),path->address(),Protocol::packetHops(pdp.h),Protocol::VERB_PUSH_DIRECT_PATHS,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
+				RR->t->incomingPacketDropped(tPtr,0x00e0f00d,pdp.h.packetId,0,peer->identity(),path->address(),Protocol::packetHops(pdp.h),Protocol::VERB_PUSH_DIRECT_PATHS,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
 				return false;
 			}
-			if ((ep.type() == Endpoint::INETADDR_V4)||(ep.type() == Endpoint::INETADDR_V6))
-				a = ep.inetAddr();
+
+			switch(ep.type()) {
+				case Endpoint::INETADDR_V4:
+				case Endpoint::INETADDR_V6:
+					a = ep.inetAddr();
+					break;
+				default: // other types are not supported yet
+					break;
+			}
 		}
 
 		if (a) {
@@ -937,6 +952,7 @@ bool VL1::_PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr<Path> &path,const Shared
 
 bool VL1::_USER_MESSAGE(void *tPtr,const SharedPtr<Path> &path,const SharedPtr<Peer> &peer,Buf &pkt,int packetSize)
 {
+	// TODO
 }
 
 bool VL1::_ENCAP(void *tPtr,const SharedPtr<Path> &path,const SharedPtr<Peer> &peer,Buf &pkt,int packetSize)