Various little things...

This commit is contained in:
Adam Ierymenko 2020-02-18 06:33:31 -08:00
parent a0ac4a744e
commit 8c8a3c58ec
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
7 changed files with 94 additions and 76 deletions

View file

@ -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.

View file

@ -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];

View file

@ -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
{

View file

@ -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;

View file

@ -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);

View file

@ -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));
}

View file

@ -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)