From 8c8a3c58eca1b8af0c559396a547a64d97da40e9 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 18 Feb 2020 06:33:31 -0800 Subject: [PATCH] Various little things... --- node/Endpoint.cpp | 18 ++++++++++ node/Endpoint.hpp | 5 +++ node/Identity.hpp | 3 -- node/SHA512.cpp | 83 +++++++++++++++++++++++++++-------------------- node/SHA512.hpp | 33 +------------------ node/Topology.cpp | 4 +-- node/VL1.cpp | 24 +++++++++++--- 7 files changed, 94 insertions(+), 76 deletions(-) diff --git a/node/Endpoint.cpp b/node/Endpoint.cpp index 664e1debd..1a9d8b414 100644 --- a/node/Endpoint.cpp +++ b/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(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. diff --git a/node/Endpoint.hpp b/node/Endpoint.hpp index d08872105..4cf7f12b9 100644 --- a/node/Endpoint.hpp +++ b/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]; diff --git a/node/Identity.hpp b/node/Identity.hpp index 6f0d0bf64..289a44096 100644 --- a/node/Identity.hpp +++ b/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 { diff --git a/node/SHA512.cpp b/node/SHA512.cpp index d60f9af5f..0d91fbe54 100644 --- a/node/SHA512.cpp +++ b/node/SHA512.cpp @@ -3,8 +3,6 @@ #include "SHA512.hpp" #include "Utils.hpp" -#include -#include #include #include #include @@ -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(key); + const uint64_t k1 = Utils::loadAsIsEndian(key + 8); + const uint64_t k2 = Utils::loadAsIsEndian(key + 16); + const uint64_t k3 = Utils::loadAsIsEndian(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(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(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; diff --git a/node/SHA512.hpp b/node/SHA512.hpp index 6b3636de1..29335e378 100644 --- a/node/SHA512.hpp +++ b/node/SHA512.hpp @@ -18,10 +18,6 @@ #ifdef __APPLE__ #include -#else -#ifdef ZT_USE_LIBCRYPTO -#include -#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(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(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(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); diff --git a/node/Topology.cpp b/node/Topology.cpp index babb21e55..8941f64de 100644 --- a/node/Topology.cpp +++ b/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 &p = _peers[id.address()]; if (!p) { p.set(new Peer(RR)); - p->init(_myIdentity,id); + p->init(id); if (bootstrap) p->setBootstrap(Endpoint(bootstrap)); } diff --git a/node/VL1.cpp b/node/VL1.cpp index df0e1a7c0..46c04f1d0 100644 --- a/node/VL1.cpp +++ b/node/VL1.cpp @@ -676,6 +676,13 @@ bool VL1::_ERROR(void *tPtr,const SharedPtr &path,const SharedPtr &p return false; } Protocol::ERROR::Header &eh = pkt.as(); + + 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,const Shared InetAddress a; Endpoint ep; for(unsigned int pi=0;pi &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,const Shared a.set(addrBytes,addrLen,addrPort); } else if (addrLen) { if (ep.unmarshal(reinterpret_cast(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,const Shared bool VL1::_USER_MESSAGE(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize) { + // TODO } bool VL1::_ENCAP(void *tPtr,const SharedPtr &path,const SharedPtr &peer,Buf &pkt,int packetSize)