diff --git a/attic/MTUDPSocket.hpp b/attic/MTUDPSocket.hpp
deleted file mode 100644
index 365bbf9cd..000000000
--- a/attic/MTUDPSocket.hpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * --
- *
- * You can be released from the requirements of the license by purchasing
- * a commercial license. Buying such a license is mandatory as soon as you
- * develop commercial closed-source software that incorporates or links
- * directly against ZeroTier software without disclosing the source code
- * of your own application.
- */
-
-#ifndef ZT_MTUDPSOCKET_HPP
-#define ZT_MTUDPSOCKET_HPP
-
-#ifndef __WINDOWS__
-
-#include "../node/Constants.hpp"
-#include "../include/ZeroTierOne.h"
-#include "../osdep/OSUtils.hpp"
-#include "../osdep/Thread.hpp"
-
-#include
-#include
-#include
-#include
-
-namespace ZeroTier {
-
-/**
- * MTUDPSocket is a multithreaded UDP socket using multiple binds and SO_REUSEPORT
- *
- * On Mac and Linux this is the most efficient way to implement a multithreaded UDP
- * I/O path. On Windows it's probably not necessary to optimize this much. If it ever
- * is, we will have to implement a version of this the Windows way.
- */
-class MTUDPSocket
-{
-public:
- inline MTUDPSocket(ZT_Node *n,volatile int64_t *dptr,const struct sockaddr *bindAddr)
- {
- const int ncores = std::max(1,(int)sysconf(_SC_NPROCESSORS_CONF));
- for(int t=0;tsa_family,SOCK_DGRAM,0);
- if (s < 0) {
- for(auto i=_sockets.begin();i!=_sockets.end();++i)
- close(*i);
- throw std::runtime_error("unable to allocate socket");
- }
-
- int f = 131072;
- setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char *)&f,sizeof(f));
- f = 131072;
- setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char *)&f,sizeof(f));
-
- if (bindAddr->sa_family == AF_INET6) {
- f = 1; setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&f,sizeof(f));
-#ifdef IPV6_MTU_DISCOVER
- f = 0; setsockopt(s,IPPROTO_IPV6,IPV6_MTU_DISCOVER,&f,sizeof(f));
-#endif
-#ifdef IPV6_DONTFRAG
- f = 0; setsockopt(s,IPPROTO_IPV6,IPV6_DONTFRAG,&f,sizeof(f));
-#endif
- }
- f = 1; setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(void *)&f,sizeof(f));
- f = 1; setsockopt(s,SOL_SOCKET,SO_REUSEPORT,(void *)&f,sizeof(f));
- f = 1; setsockopt(s,SOL_SOCKET,SO_BROADCAST,(void *)&f,sizeof(f));
-#ifdef IP_DONTFRAG
- f = 0; setsockopt(s,IPPROTO_IP,IP_DONTFRAG,&f,sizeof(f));
-#endif
-#ifdef IP_MTU_DISCOVER
- f = 0; setsockopt(s,IPPROTO_IP,IP_MTU_DISCOVER,&f,sizeof(f));
-#endif
-#ifdef SO_NO_CHECK
- if (bindAddr->sa_family == AF_INET) {
- f = 1; setsockopt(s,SOL_SOCKET,SO_NO_CHECK,(void *)&f,sizeof(f));
- }
-#endif
-
- if (bind(s,bindAddr,(bindAddr->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))) {
- for(auto i=_sockets.begin();i!=_sockets.end();++i)
- close(*i);
- throw std::runtime_error("unable to bind to address");
- }
-
- _sockets.push_back(s);
- }
-
- for(auto s=_sockets.begin();s!=_sockets.end();++s) {
- try {
- new MTUDPThread(n,dptr,*s);
- } catch ( ... ) {
- for(auto i=_sockets.begin();i!=_sockets.end();++i)
- close(*i);
- throw;
- }
- }
- }
-
- inline ~MTUDPSocket()
- {
- for(auto i=_sockets.begin();i!=_sockets.end();++i)
- close(*i);
- }
-
-private:
- class MTUDPThread
- {
- public:
- inline MTUDPThread(ZT_Node *n,volatile int64_t *dptr,int s) :
- node(n),
- deadlinePtr(dptr),
- sock(s),
- thread(Thread::start(this))
- {
- }
-
- inline void threadMain()
- {
- struct sockaddr_storage from;
- for(;;) {
- socklen_t fromLen = sizeof(from);
- const int nr = recvfrom(this->sock,this->buf,sizeof(this->buf),0,(struct sockaddr *)&from,&fromLen);
- if (nr > 0) {
- ZT_Node_processWirePacket(this->node,nullptr,OSUtils::now(),(int64_t)this->sock,&from,this->buf,(unsigned int)nr,this->deadlinePtr);
- } else {
- close(this->sock);
- break;
- }
- }
- delete this; // closing the socket causes this to exit and delete itself
- }
-
- ZT_Node *const node;
- volatile int64_t *const deadlinePtr;
- const int sock;
- Thread thread;
- char buf[10000];
- };
-
- std::vector _sockets;
-};
-
-} // namespace ZeroTier
-
-#endif // !__WINDOWS__
-
-#endif
diff --git a/attic/world/README.md b/attic/world/README.md
deleted file mode 100644
index dda4920ae..000000000
--- a/attic/world/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-World Definitions and Generator Code
-======
-
-This little bit of code is used to generate world updates. Ordinary users probably will never need this unless they want to test or experiment.
-
-See mkworld.cpp for documentation. To build from this directory use 'source ./build.sh'.
-
diff --git a/attic/world/build.sh b/attic/world/build.sh
deleted file mode 100755
index aeb3b87fa..000000000
--- a/attic/world/build.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-c++ -std=c++11 -I../.. -I.. -O -o mkworld ../../node/C25519.cpp ../../node/Salsa20.cpp ../../node/SHA512.cpp ../../node/Identity.cpp ../../node/Utils.cpp ../../node/InetAddress.cpp ../../osdep/OSUtils.cpp mkworld.cpp -lm
diff --git a/attic/world/mkworld.cpp b/attic/world/mkworld.cpp
deleted file mode 100644
index b8cb027b4..000000000
--- a/attic/world/mkworld.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-/*
- * This utility makes the World from the configuration specified below.
- * It probably won't be much use to anyone outside ZeroTier, Inc. except
- * for testing and experimentation purposes.
- *
- * If you want to make your own World you must edit this file.
- *
- * When run, it expects two files in the current directory:
- *
- * previous.c25519 - key pair to sign this world (key from previous world)
- * current.c25519 - key pair whose public key should be embedded in this world
- *
- * If these files do not exist, they are both created with the same key pair
- * and a self-signed initial World is born.
- */
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace ZeroTier;
-
-int main(int argc,char **argv)
-{
- std::string previous,current;
- if ((!OSUtils::readFile("previous.c25519",previous))||(!OSUtils::readFile("current.c25519",current))) {
- C25519::Pair np(C25519::generate());
- previous = std::string();
- previous.append((const char *)np.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
- previous.append((const char *)np.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
- current = previous;
- OSUtils::writeFile("previous.c25519",previous);
- OSUtils::writeFile("current.c25519",current);
- fprintf(stderr,"INFO: created initial world keys: previous.c25519 and current.c25519 (both initially the same)" ZT_EOL_S);
- }
-
- if ((previous.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))||(current.length() != (ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_PRIVATE_KEY_LEN))) {
- fprintf(stderr,"FATAL: previous.c25519 or current.c25519 empty or invalid" ZT_EOL_S);
- return 1;
- }
- C25519::Pair previousKP;
- memcpy(previousKP.pub.data,previous.data(),ZT_C25519_PUBLIC_KEY_LEN);
- memcpy(previousKP.priv.data,previous.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN);
- C25519::Pair currentKP;
- memcpy(currentKP.pub.data,current.data(),ZT_C25519_PUBLIC_KEY_LEN);
- memcpy(currentKP.priv.data,current.data() + ZT_C25519_PUBLIC_KEY_LEN,ZT_C25519_PRIVATE_KEY_LEN);
-
- // =========================================================================
- // EDIT BELOW HERE
-
- std::vector roots;
-
- const uint64_t id = ZT_WORLD_ID_EARTH;
- const uint64_t ts = 1562631342273ULL; // July 8th, 2019
-
- roots.push_back(World::Root());
- roots.back().identity = Identity("3a46f1bf30:0:76e66fab33e28549a62ee2064d1843273c2c300ba45c3f20bef02dbad225723bb59a9bb4b13535730961aeecf5a163ace477cceb0727025b99ac14a5166a09a3");
- roots.back().stableEndpoints.push_back(InetAddress("185.180.13.82/9993"));
- roots.back().stableEndpoints.push_back(InetAddress("2a02:6ea0:c815::/9993"));
-
- // Alice
- roots.push_back(World::Root());
- roots.back().identity = Identity("9d219039f3:0:01f0922a98e3b34ebcbff333269dc265d7a020aab69d72be4d4acc9c8c9294785771256cd1d942a90d1bd1d2dca3ea84ef7d85afe6611fb43ff0b74126d90a6e");
- roots.back().stableEndpoints.push_back(InetAddress("188.166.94.177/9993")); // Amsterdam
- roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:2:d0::7d:1/9993")); // Amsterdam
- roots.back().stableEndpoints.push_back(InetAddress("154.66.197.33/9993")); // Johannesburg
- roots.back().stableEndpoints.push_back(InetAddress("2c0f:f850:154:197::33/9993")); // Johannesburg
- roots.back().stableEndpoints.push_back(InetAddress("159.203.97.171/9993")); // New York
- roots.back().stableEndpoints.push_back(InetAddress("2604:a880:800:a1::54:6001/9993")); // New York
- roots.back().stableEndpoints.push_back(InetAddress("131.255.6.16/9993")); // Buenos Aires
- roots.back().stableEndpoints.push_back(InetAddress("2803:eb80:0:e::2/9993")); // Buenos Aires
- roots.back().stableEndpoints.push_back(InetAddress("107.170.197.14/9993")); // San Francisco
- roots.back().stableEndpoints.push_back(InetAddress("2604:a880:1:20::200:e001/9993")); // San Francisco
- roots.back().stableEndpoints.push_back(InetAddress("128.199.197.217/9993")); // Singapore
- roots.back().stableEndpoints.push_back(InetAddress("2400:6180:0:d0::b7:4001/9993")); // Singapore
-
- // Bob
- roots.push_back(World::Root());
- roots.back().identity = Identity("8841408a2e:0:bb1d31f2c323e264e9e64172c1a74f77899555ed10751cd56e86405cde118d02dffe555d462ccf6a85b5631c12350c8d5dc409ba10b9025d0f445cf449d92b1c");
- roots.back().stableEndpoints.push_back(InetAddress("45.32.198.130/9993")); // Dallas
- roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6400:81c3:5400:00ff:fe18:1d61/9993")); // Dallas
- roots.back().stableEndpoints.push_back(InetAddress("46.101.160.249/9993")); // Frankfurt
- roots.back().stableEndpoints.push_back(InetAddress("2a03:b0c0:3:d0::6a:3001/9993")); // Frankfurt
- roots.back().stableEndpoints.push_back(InetAddress("107.191.46.210/9993")); // Paris
- roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:6800:83a4::64/9993")); // Paris
- roots.back().stableEndpoints.push_back(InetAddress("45.32.246.179/9993")); // Sydney
- roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:5800:8bf8:5400:ff:fe15:b39a/9993")); // Sydney
- roots.back().stableEndpoints.push_back(InetAddress("45.32.248.87/9993")); // Tokyo
- roots.back().stableEndpoints.push_back(InetAddress("2001:19f0:7000:9bc9:5400:00ff:fe15:c4f5/9993")); // Tokyo
- roots.back().stableEndpoints.push_back(InetAddress("159.203.2.154/9993")); // Toronto
- roots.back().stableEndpoints.push_back(InetAddress("2604:a880:cad:d0::26:7001/9993")); // Toronto
-
- // END WORLD DEFINITION
- // =========================================================================
-
- fprintf(stderr,"INFO: generating and signing id==%llu ts==%llu" ZT_EOL_S,(unsigned long long)id,(unsigned long long)ts);
-
- World nw = World::make(World::TYPE_PLANET,id,ts,currentKP.pub,roots,previousKP);
-
- Buffer outtmp;
- nw.serialize(outtmp,false);
- World testw;
- testw.deserialize(outtmp,0);
- if (testw != nw) {
- fprintf(stderr,"FATAL: serialization test failed!" ZT_EOL_S);
- return 1;
- }
-
- OSUtils::writeFile("world.bin",std::string((const char *)outtmp.data(),outtmp.size()));
- fprintf(stderr,"INFO: world.bin written with %u bytes of binary world data." ZT_EOL_S,outtmp.size());
-
- fprintf(stdout,ZT_EOL_S);
- fprintf(stdout,"#define ZT_DEFAULT_WORLD_LENGTH %u" ZT_EOL_S,outtmp.size());
- fprintf(stdout,"static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {");
- for(unsigned int i=0;i 0)
- fprintf(stdout,",");
- fprintf(stdout,"0x%.2x",(unsigned int)d[i]);
- }
- fprintf(stdout,"};" ZT_EOL_S);
-
- return 0;
-}
diff --git a/attic/world/world.bin b/attic/world/world.bin
deleted file mode 100644
index fff7e2a99..000000000
Binary files a/attic/world/world.bin and /dev/null differ
diff --git a/attic/world/world.c b/attic/world/world.c
deleted file mode 100644
index ecf30e6f0..000000000
--- a/attic/world/world.c
+++ /dev/null
@@ -1,3 +0,0 @@
-
-#define ZT_DEFAULT_WORLD_LENGTH 732
-static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x6b,0xd4,0x16,0x08,0xc1,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0x16,0x93,0xf4,0xe5,0xbd,0x20,0xda,0x10,0xad,0xc7,0x05,0xf4,0x99,0xfe,0x04,0x08,0x9b,0xe0,0x9e,0x77,0x1d,0x9f,0x47,0x16,0xaa,0x92,0x4f,0x10,0x16,0x3d,0xc7,0xec,0xd3,0x90,0x9e,0xd1,0x74,0xfc,0xb3,0xb5,0x07,0x9c,0x4d,0x95,0xc5,0x17,0x8b,0x3d,0x0b,0x60,0x76,0xe8,0x51,0xbb,0xb6,0x3d,0x74,0xb5,0x21,0x83,0x7b,0x95,0x1d,0x02,0x9b,0xcd,0xaf,0x5c,0x3e,0x96,0xdf,0x37,0x2c,0x56,0x6d,0xfa,0x75,0x0f,0xda,0x55,0x85,0x13,0xf4,0x76,0x1a,0x66,0x4d,0x3b,0x8d,0xcf,0x12,0xc9,0x34,0xb9,0x0d,0x61,0x03,0x3a,0x46,0xf1,0xbf,0x30,0x00,0x76,0xe6,0x6f,0xab,0x33,0xe2,0x85,0x49,0xa6,0x2e,0xe2,0x06,0x4d,0x18,0x43,0x27,0x3c,0x2c,0x30,0x0b,0xa4,0x5c,0x3f,0x20,0xbe,0xf0,0x2d,0xba,0xd2,0x25,0x72,0x3b,0xb5,0x9a,0x9b,0xb4,0xb1,0x35,0x35,0x73,0x09,0x61,0xae,0xec,0xf5,0xa1,0x63,0xac,0xe4,0x77,0xcc,0xeb,0x07,0x27,0x02,0x5b,0x99,0xac,0x14,0xa5,0x16,0x6a,0x09,0xa3,0x00,0x02,0x04,0xb9,0xb4,0x0d,0x52,0x27,0x09,0x06,0x2a,0x02,0x6e,0xa0,0xc8,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x09,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x7d,0x00,0x01,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x54,0x60,0x01,0x27,0x09,0x04,0x83,0xff,0x06,0x10,0x27,0x09,0x06,0x28,0x03,0xeb,0x80,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0xe0,0x01,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb7,0x40,0x01,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x6a,0x30,0x01,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x26,0x70,0x01,0x27,0x09};
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index 746009898..2f1c2214c 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -1393,24 +1393,6 @@ enum ZT_StateObjectType
*/
ZT_STATE_OBJECT_IDENTITY_SECRET = 2,
- /**
- * The planet (there is only one per... well... planet!)
- *
- * Object ID: world ID of planet, or 0 if unknown (first query)
- * Canonical path: /planet
- * Persistence: recommended
- */
- ZT_STATE_OBJECT_PLANET = 3,
-
- /**
- * A moon (federated root set)
- *
- * Object ID: world ID of moon
- * Canonical path: /moons.d/.moon (16-digit hex ID)
- * Persistence: required if moon memberships should persist
- */
- ZT_STATE_OBJECT_MOON = 4,
-
/**
* Peer and related state
*
@@ -1847,32 +1829,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tpt
*/
ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
-/**
- * Add or update a moon
- *
- * Moons are persisted in the data store in moons.d/, so this can persist
- * across invocations if the contents of moon.d are scanned and orbit is
- * called for each on startup.
- *
- * @param node Node instance
- * @param tptr Thread pointer to pass to functions/callbacks resulting from this call
- * @param moonWorldId Moon's world ID
- * @param moonSeed If non-zero, the ZeroTier address of any member of the moon to query for moon definition
- * @param len Length of moonWorld in bytes
- * @return Error if moon was invalid or failed to be added
- */
-ZT_SDK_API enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,uint64_t moonSeed);
-
-/**
- * Remove a moon (does nothing if not present)
- *
- * @param node Node instance
- * @param tptr Thread pointer to pass to functions/callbacks resulting from this call
- * @param moonWorldId World ID of moon to remove
- * @return Error if anything bad happened
- */
-ZT_SDK_API enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId);
-
/**
* Get this node's 40-bit ZeroTier address
*
diff --git a/node/C25519.hpp b/node/C25519.hpp
index c87df9c20..d4a2c9349 100644
--- a/node/C25519.hpp
+++ b/node/C25519.hpp
@@ -98,7 +98,6 @@ public:
* @param keylen Number of key bytes to generate
*/
static void agree(const Private &mine,const Public &their,void *keybuf,unsigned int keylen);
- static inline void agree(const Pair &mine,const Public &their,void *keybuf,unsigned int keylen) { agree(mine.priv,their,keybuf,keylen); }
/**
* Sign a message with a sender's key pair
@@ -120,7 +119,6 @@ public:
* @param signature Buffer to fill with signature -- MUST be 96 bytes in length
*/
static void sign(const Private &myPrivate,const Public &myPublic,const void *msg,unsigned int len,void *signature);
- static inline void sign(const Pair &mine,const void *msg,unsigned int len,void *signature) { sign(mine.priv,mine.pub,msg,len,signature); }
/**
* Sign a message with a sender's key pair
diff --git a/node/Capability.cpp b/node/Capability.cpp
index fdf98baec..3ed7f0b19 100644
--- a/node/Capability.cpp
+++ b/node/Capability.cpp
@@ -34,6 +34,23 @@
namespace ZeroTier {
+bool Capability::sign(const Identity &from,const Address &to)
+{
+ try {
+ for(unsigned int i=0;((i<_maxCustodyChainLength)&&(i 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;
+}
+
int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
try {
@@ -57,7 +74,7 @@ int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
const Identity id(RR->topology->getIdentity(tPtr,_custody[c].from));
if (id) {
- if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature))
+ if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature,_custody[c].signatureLength))
return -1;
} else {
RR->sw->requestWhois(tPtr,RR->node->now(),_custody[c].from);
diff --git a/node/Capability.hpp b/node/Capability.hpp
index 0704c5139..35fe17bac 100644
--- a/node/Capability.hpp
+++ b/node/Capability.hpp
@@ -154,22 +154,7 @@ 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 tmp;
- this->serialize(tmp,true);
- _custody[i].to = to;
- _custody[i].from = from.address();
- _custody[i].signature = from.sign(tmp.data(),tmp.size());
- return true;
- }
- }
- } catch ( ... ) {}
- return false;
- }
+ bool sign(const Identity &from,const Address &to);
/**
* Verify this capability's chain of custody and signatures
@@ -409,9 +394,9 @@ public:
if ((i < _maxCustodyChainLength)&&(i < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)&&(_custody[i].to)) {
_custody[i].to.appendTo(b);
_custody[i].from.appendTo(b);
- b.append((uint8_t)1); // 1 == Ed25519 signature
- b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature
- b.append(_custody[i].signature.data,ZT_C25519_SIGNATURE_LEN);
+ b.append((uint8_t)1);
+ b.append((uint16_t)_custody[i].signatureLength);
+ b.append(_custody[i].signature,_custody[i].signatureLength);
} else {
b.append((unsigned char)0,ZT_ADDRESS_LENGTH); // zero 'to' terminates chain
break;
@@ -454,10 +439,11 @@ public:
_custody[i].to = to;
_custody[i].from.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
if (b[p++] == 1) {
- if (b.template at(p) != ZT_C25519_SIGNATURE_LEN)
+ _custody[i].signatureLength = b.template at(p);
+ if (_custody[i].signatureLength > sizeof(_custody[i].signature))
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
p += 2;
- memcpy(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN;
+ memcpy(_custody[i].signature,b.field(p,_custody[i].signatureLength),_custody[i].signatureLength); p += _custody[i].signatureLength;
} else {
p += 2 + b.template at(p);
}
@@ -489,7 +475,8 @@ private:
struct {
Address to;
Address from;
- C25519::Signature signature;
+ unsigned int signatureLength;
+ uint8_t signature[ZT_SIGNATURE_BUFFER_SIZE];
} _custody[ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH];
};
diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp
index 614c68871..0ec7abfaf 100644
--- a/node/CertificateOfMembership.cpp
+++ b/node/CertificateOfMembership.cpp
@@ -84,7 +84,7 @@ std::string CertificateOfMembership::toString() const
if (_signedBy) {
s.push_back(':');
- s.append(Utils::hex(_signature.data,ZT_C25519_SIGNATURE_LEN,tmp));
+ s.append(Utils::hex(_signature,_signatureLength,tmp));
}
return s;
@@ -92,9 +92,9 @@ std::string CertificateOfMembership::toString() const
void CertificateOfMembership::fromString(const char *s)
{
- _qualifierCount = 0;
_signedBy.zero();
- memset(_signature.data,0,ZT_C25519_SIGNATURE_LEN);
+ _qualifierCount = 0;
+ _signatureLength = 0;
if (!*s)
return;
@@ -145,8 +145,7 @@ void CertificateOfMembership::fromString(const char *s)
colonAt = 0;
while ((s[colonAt])&&(s[colonAt] != ':')) ++colonAt;
if (colonAt) {
- if (Utils::unhex(s,colonAt,_signature.data,ZT_C25519_SIGNATURE_LEN) != ZT_C25519_SIGNATURE_LEN)
- _signedBy.zero();
+ _signatureLength = Utils::unhex(s,colonAt,_signature,sizeof(_signature));
} else {
_signedBy.zero();
}
@@ -208,7 +207,7 @@ bool CertificateOfMembership::sign(const Identity &with)
}
try {
- _signature = with.sign(buf,ptr * sizeof(uint64_t));
+ _signatureLength = with.sign(buf,ptr * sizeof(uint64_t),_signature,sizeof(_signature));
_signedBy = with.address();
return true;
} catch ( ... ) {
@@ -235,7 +234,7 @@ int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) con
buf[ptr++] = Utils::hton(_qualifiers[i].value);
buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
}
- return (id.verify(buf,ptr * sizeof(uint64_t),_signature) ? 0 : -1);
+ return (id.verify(buf,ptr * sizeof(uint64_t),_signature,_signatureLength) ? 0 : -1);
}
} // namespace ZeroTier
diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp
index b2c63f9d0..b4aa51727 100644
--- a/node/CertificateOfMembership.hpp
+++ b/node/CertificateOfMembership.hpp
@@ -113,7 +113,8 @@ public:
* Create an empty certificate of membership
*/
CertificateOfMembership() :
- _qualifierCount(0) {}
+ _qualifierCount(0),
+ _signatureLength(0) {}
/**
* Create from required fields common to all networks
@@ -135,7 +136,7 @@ public:
_qualifiers[2].value = issuedTo.toInt();
_qualifiers[2].maxDelta = 0xffffffffffffffffULL;
_qualifierCount = 3;
- memset(_signature.data,0,ZT_C25519_SIGNATURE_LEN);
+ _signatureLength = 0;
}
/**
@@ -279,8 +280,13 @@ public:
b.append(_qualifiers[i].maxDelta);
}
_signedBy.appendTo(b);
- if (_signedBy)
- b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+ 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.
+ b.append(_signature,96);
+ }
}
template
@@ -288,8 +294,9 @@ public:
{
unsigned int p = startAt;
- _qualifierCount = 0;
_signedBy.zero();
+ _qualifierCount = 0;
+ _signatureLength = 0;
if (b[p++] != 1)
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
@@ -316,8 +323,10 @@ public:
p += ZT_ADDRESS_LENGTH;
if (_signedBy) {
- memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
- p += ZT_C25519_SIGNATURE_LEN;
+ // See "UGLY" comment in serialize()...
+ _signatureLength = 96;
+ memcpy(_signature,b.field(p,96),96);
+ p += 96;
}
return (p - startAt);
@@ -329,13 +338,15 @@ public:
return false;
if (_qualifierCount != c._qualifierCount)
return false;
+ if (_signatureLength != c._signatureLength)
+ return false;
for(unsigned int i=0;i<_qualifierCount;++i) {
const _Qualifier &a = _qualifiers[i];
const _Qualifier &b = c._qualifiers[i];
if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta))
return false;
}
- return (memcmp(_signature.data,c._signature.data,ZT_C25519_SIGNATURE_LEN) == 0);
+ return (memcmp(_signature,c._signature,_signatureLength) == 0);
}
inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }
@@ -352,7 +363,8 @@ private:
Address _signedBy;
_Qualifier _qualifiers[ZT_NETWORK_COM_MAX_QUALIFIERS];
unsigned int _qualifierCount;
- C25519::Signature _signature;
+ unsigned int _signatureLength;
+ uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
};
} // namespace ZeroTier
diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp
index d7266cd29..5a17026ce 100644
--- a/node/CertificateOfOwnership.cpp
+++ b/node/CertificateOfOwnership.cpp
@@ -34,6 +34,32 @@
namespace ZeroTier {
+void CertificateOfOwnership::addThing(const InetAddress &ip)
+{
+ if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
+ if (ip.ss_family == AF_INET) {
+ _thingTypes[_thingCount] = THING_IPV4_ADDRESS;
+ memcpy(_thingValues[_thingCount],&(reinterpret_cast(&ip)->sin_addr.s_addr),4);
+ ++_thingCount;
+ } else if (ip.ss_family == AF_INET6) {
+ _thingTypes[_thingCount] = THING_IPV6_ADDRESS;
+ memcpy(_thingValues[_thingCount],reinterpret_cast(&ip)->sin6_addr.s6_addr,16);
+ ++_thingCount;
+ }
+}
+
+bool CertificateOfOwnership::sign(const Identity &signer)
+{
+ if (signer.hasPrivate()) {
+ Buffer tmp;
+ _signedBy = signer.address();
+ this->serialize(tmp,true);
+ _signatureLength = signer.sign(tmp.data(),tmp.size(),_signature,sizeof(_signature));
+ return true;
+ }
+ return false;
+}
+
int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
@@ -46,7 +72,7 @@ int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) cons
try {
Buffer<(sizeof(CertificateOfOwnership) + 64)> tmp;
this->serialize(tmp,true);
- return (id.verify(tmp.data(),tmp.size(),_signature) ? 0 : -1);
+ return (id.verify(tmp.data(),tmp.size(),_signature,_signatureLength) ? 0 : -1);
} catch ( ... ) {
return -1;
}
diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp
index fdffec3b8..cf984ad8e 100644
--- a/node/CertificateOfOwnership.hpp
+++ b/node/CertificateOfOwnership.hpp
@@ -107,19 +107,7 @@ public:
return this->_owns(THING_MAC_ADDRESS,tmp,6);
}
- inline void addThing(const InetAddress &ip)
- {
- if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
- if (ip.ss_family == AF_INET) {
- _thingTypes[_thingCount] = THING_IPV4_ADDRESS;
- memcpy(_thingValues[_thingCount],&(reinterpret_cast(&ip)->sin_addr.s_addr),4);
- ++_thingCount;
- } else if (ip.ss_family == AF_INET6) {
- _thingTypes[_thingCount] = THING_IPV6_ADDRESS;
- memcpy(_thingValues[_thingCount],reinterpret_cast(&ip)->sin6_addr.s6_addr,16);
- ++_thingCount;
- }
- }
+ void addThing(const InetAddress &ip);
inline void addThing(const MAC &mac)
{
@@ -133,17 +121,7 @@ public:
* @param signer Signing identity, must have private key
* @return True if signature was successful
*/
- inline bool sign(const Identity &signer)
- {
- if (signer.hasPrivate()) {
- Buffer tmp;
- _signedBy = signer.address();
- this->serialize(tmp,true);
- _signature = signer.sign(tmp.data(),tmp.size());
- return true;
- }
- return false;
- }
+ bool sign(const Identity &signer);
/**
* @param RR Runtime environment to allow identity lookup for signedBy
@@ -170,9 +148,9 @@ public:
_issuedTo.appendTo(b);
_signedBy.appendTo(b);
if (!forSign) {
- b.append((uint8_t)1); // 1 == Ed25519
- b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature
- b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+ b.append((uint8_t)1);
+ b.append((uint16_t)_signatureLength); // length of signature
+ b.append(_signature,_signatureLength);
}
b.append((uint16_t)0); // length of additional fields, currently 0
@@ -203,10 +181,11 @@ public:
_issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
if (b[p++] == 1) {
- if (b.template at(p) != ZT_C25519_SIGNATURE_LEN)
+ _signatureLength = b.template at(p);
+ if (_signatureLength > sizeof(_signature))
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
p += 2;
- memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN;
+ memcpy(_signature,b.field(p,_signatureLength),_signatureLength); p += _signatureLength;
} else {
p += 2 + b.template at(p);
}
@@ -236,7 +215,8 @@ private:
uint8_t _thingValues[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS][ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE];
Address _issuedTo;
Address _signedBy;
- C25519::Signature _signature;
+ unsigned int _signatureLength;
+ uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
};
} // namespace ZeroTier
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 98df998d8..3c155b206 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -613,6 +613,11 @@
*/
#define ZT_SUPPORT_OLD_STYLE_NETCONF 1
+/**
+ * Size of a buffer to store either a C25519 or an ECC P-384 signature
+ */
+#define ZT_SIGNATURE_BUFFER_SIZE 96
+
/**
* Desired buffer size for UDP sockets (used in service and osdep but defined here)
*/
diff --git a/node/ECC384.hpp b/node/ECC384.hpp
index 40ce3a145..5097a6030 100644
--- a/node/ECC384.hpp
+++ b/node/ECC384.hpp
@@ -61,12 +61,46 @@
namespace ZeroTier {
+/**
+ * Generate a NIST P-384 key pair
+ *
+ * @param pub Buffer to receive point compressed public key
+ * @param priv Buffer to receiver private key
+ */
void ECC384GenerateKey(uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE]);
+/**
+ * Sign a hash with a NIST P-384 private key
+ *
+ * The hash must be 48 bytes in size and is typically the first 48 bytes
+ * of a SHA512 hash or something similar. Extra bytes of course are ignored.
+ *
+ * @param priv Private key
+ * @param hash 48-byte hash
+ * @param sig Buffer to receive signature
+ */
void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
+/**
+ * Verify a signature
+ *
+ * @param pub Public key
+ * @param hash 48-byte hash (usually first 48 bytes of SHA512(msg))
+ * @param sig Signature to check
+ * @return True if signature is valid
+ */
bool ECC384ECDSAVerify(const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
+/**
+ * Perform ECDH key agreement
+ *
+ * The secret generated here is the raw 48-byte result of ECDH.
+ * It's typically hashed prior to use.
+ *
+ * @param theirPub Remote public key
+ * @param ourPriv Local private key
+ * @param secret Buffer to receive 48-byte secret
+ */
bool ECC384ECDH(const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE],uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE]);
} // namespace ZeroTier
diff --git a/node/Identity.cpp b/node/Identity.cpp
index e914b2701..e23de277a 100644
--- a/node/Identity.cpp
+++ b/node/Identity.cpp
@@ -35,14 +35,16 @@
#include "Salsa20.hpp"
#include "Utils.hpp"
+namespace ZeroTier {
+
+//////////////////////////////////////////////////////////////////////////////
+// This is the memory-hard hash used for type 0 identities' addresses
+
// These can't be changed without a new identity type. They define the
// parameters of the hashcash hashing/searching algorithm.
-
#define ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN 17
#define ZT_IDENTITY_GEN_MEMORY 2097152
-namespace ZeroTier {
-
// A memory-hard composition of SHA-512 and Salsa20 for hashcash hashing
static inline void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *digest,void *genmem)
{
@@ -94,23 +96,39 @@ struct _Identity_generate_cond
char *genmem;
};
-void Identity::generate()
+//////////////////////////////////////////////////////////////////////////////
+
+void Identity::generate(const Type t)
{
- unsigned char digest[64];
- char *genmem = new char[ZT_IDENTITY_GEN_MEMORY];
+ uint8_t digest[64];
+ switch(t) {
+ case C25519: {
+ char *genmem = new char[ZT_IDENTITY_GEN_MEMORY];
- C25519::Pair kp;
- do {
- kp = C25519::generateSatisfying(_Identity_generate_cond(digest,genmem));
- _address.setTo(digest + 59,ZT_ADDRESS_LENGTH); // last 5 bytes are address
- } while (_address.isReserved());
+ C25519::Pair kp;
+ do {
+ kp = C25519::generateSatisfying(_Identity_generate_cond(digest,genmem));
+ _address.setTo(digest + 59,ZT_ADDRESS_LENGTH); // last 5 bytes are address
+ } while (_address.isReserved());
- _publicKey = kp.pub;
- if (!_privateKey)
- _privateKey = new C25519::Private();
- *_privateKey = kp.priv;
+ memcpy(_k.t0.pub.data,kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
+ memcpy(_k.t0.priv.data,kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
+ _type = C25519;
+ _hasPrivate = true;
+
+ delete [] genmem;
+ } break;
- delete [] genmem;
+ case P384: {
+ do {
+ ECC384GenerateKey(_k.t1.pub,_k.t1.priv);
+ SHA512::hash(digest,_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE);
+ _address.setTo(digest + 59,ZT_ADDRESS_LENGTH);
+ } while (_address.isReserved());
+ _type = P384;
+ _hasPrivate = true;
+ } break;
+ }
}
bool Identity::locallyValidate() const
@@ -118,40 +136,70 @@ bool Identity::locallyValidate() const
if (_address.isReserved())
return false;
- unsigned char digest[64];
- char *genmem = new char[ZT_IDENTITY_GEN_MEMORY];
- _computeMemoryHardHash(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
- delete [] genmem;
+ switch(_type) {
+ case C25519: {
+ unsigned char digest[64];
+ char *genmem = new char[ZT_IDENTITY_GEN_MEMORY];
+ _computeMemoryHardHash(_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
+ delete [] genmem;
+ unsigned char addrb[5];
+ _address.copyTo(addrb,5);
+ return (
+ (digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN)&&
+ (digest[59] == addrb[0])&&
+ (digest[60] == addrb[1])&&
+ (digest[61] == addrb[2])&&
+ (digest[62] == addrb[3])&&
+ (digest[63] == addrb[4]));
+ } break;
- unsigned char addrb[5];
- _address.copyTo(addrb,5);
+ case P384: {
+ return true;
+ } break;
+ }
- return (
- (digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN)&&
- (digest[59] == addrb[0])&&
- (digest[60] == addrb[1])&&
- (digest[61] == addrb[2])&&
- (digest[62] == addrb[3])&&
- (digest[63] == addrb[4]));
+ return false;
}
char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
{
- char *p = buf;
- Utils::hex10(_address.toInt(),p);
- p += 10;
- *(p++) = ':';
- *(p++) = '0';
- *(p++) = ':';
- Utils::hex(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,p);
- p += ZT_C25519_PUBLIC_KEY_LEN * 2;
- if ((_privateKey)&&(includePrivate)) {
- *(p++) = ':';
- Utils::hex(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN,p);
- p += ZT_C25519_PRIVATE_KEY_LEN * 2;
+ switch(_type) {
+ case C25519: {
+ char *p = buf;
+ Utils::hex10(_address.toInt(),p);
+ p += 10;
+ *(p++) = ':';
+ *(p++) = '0';
+ *(p++) = ':';
+ Utils::hex(_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN,p);
+ p += ZT_C25519_PUBLIC_KEY_LEN * 2;
+ if ((_hasPrivate)&&(includePrivate)) {
+ *(p++) = ':';
+ Utils::hex(_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN,p);
+ p += ZT_C25519_PRIVATE_KEY_LEN * 2;
+ }
+ *p = (char)0;
+ return buf;
+ }
+
+ case P384: {
+ char *p = buf;
+ Utils::hex10(_address.toInt(),p);
+ p += 10;
+ *(p++) = ':';
+ *(p++) = '1';
+ *(p++) = ':';
+ Utils::hex(_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE,p);
+ p += ZT_ECC384_PUBLIC_KEY_SIZE * 2;
+ if ((_hasPrivate)&&(includePrivate)) {
+ *(p++) = ':';
+ Utils::hex(_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE,p);
+ p += ZT_ECC384_PRIVATE_KEY_SIZE * 2;
+ }
+ *p = (char)0;
+ return buf;
+ } break;
}
- *p = (char)0;
- return buf;
}
bool Identity::fromString(const char *str)
@@ -166,8 +214,7 @@ bool Identity::fromString(const char *str)
return false;
}
- delete _privateKey;
- _privateKey = (C25519::Private *)0;
+ _hasPrivate = false;
int fno = 0;
char *saveptr = (char *)0;
@@ -181,22 +228,49 @@ bool Identity::fromString(const char *str)
}
break;
case 1:
- if ((f[0] != '0')||(f[1])) {
+ if ((f[0] == '0')&&(!f[1])) {
+ _type = C25519;
+ } else if ((f[0] == '1')&&(!f[1])) {
+ _type = P384;
+ } else {
_address.zero();
return false;
}
break;
case 2:
- if (Utils::unhex(f,_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
- _address.zero();
- return false;
+ switch(_type) {
+ case C25519:
+ if (Utils::unhex(f,_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
+ _address.zero();
+ return false;
+ }
+ break;
+ case P384:
+ if (Utils::unhex(f,_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE) != ZT_ECC384_PUBLIC_KEY_SIZE) {
+ _address.zero();
+ return false;
+ }
+ break;
}
break;
case 3:
- _privateKey = new C25519::Private();
- if (Utils::unhex(f,_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
- _address.zero();
- return false;
+ switch(_type) {
+ case C25519:
+ if (Utils::unhex(f,_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
+ _address.zero();
+ return false;
+ } else {
+ _hasPrivate = true;
+ }
+ break;
+ case P384:
+ if (Utils::unhex(f,_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE) != ZT_ECC384_PRIVATE_KEY_SIZE) {
+ _address.zero();
+ return false;
+ } else {
+ _hasPrivate = true;
+ }
+ break;
}
break;
default:
diff --git a/node/Identity.hpp b/node/Identity.hpp
index ee55028cf..4b5396d9b 100644
--- a/node/Identity.hpp
+++ b/node/Identity.hpp
@@ -36,6 +36,7 @@
#include "C25519.hpp"
#include "Buffer.hpp"
#include "SHA512.hpp"
+#include "ECC384.hpp"
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 384
@@ -54,61 +55,45 @@ namespace ZeroTier {
class Identity
{
public:
- Identity() :
- _privateKey((C25519::Private *)0)
+ enum Type
{
- }
+ C25519 = 0, // Curve25519 and Ed25519
+ P384 = 1 // NIST P-384 ECDH and ECDSA
+ };
- Identity(const Identity &id) :
- _address(id._address),
- _publicKey(id._publicKey),
- _privateKey((id._privateKey) ? new C25519::Private(*(id._privateKey)) : (C25519::Private *)0)
- {
- }
+ Identity() { memset(reinterpret_cast(this),0,sizeof(Identity)); }
+ Identity(const Identity &id) { memcpy(reinterpret_cast(this),&id,sizeof(Identity)); }
- Identity(const char *str) :
- _privateKey((C25519::Private *)0)
+ Identity(const char *str)
{
if (!fromString(str))
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
}
template
- Identity(const Buffer &b,unsigned int startAt = 0) :
- _privateKey((C25519::Private *)0)
- {
- deserialize(b,startAt);
- }
+ Identity(const Buffer &b,unsigned int startAt = 0) { deserialize(b,startAt); }
- ~Identity()
- {
- if (_privateKey) {
- Utils::burn(_privateKey,sizeof(C25519::Private));
- delete _privateKey;
- }
- }
+ ~Identity() { Utils::burn(reinterpret_cast(this),sizeof(Identity)); }
inline Identity &operator=(const Identity &id)
{
- _address = id._address;
- _publicKey = id._publicKey;
- if (id._privateKey) {
- if (!_privateKey)
- _privateKey = new C25519::Private();
- *_privateKey = *(id._privateKey);
- } else {
- delete _privateKey;
- _privateKey = (C25519::Private *)0;
- }
+ memcpy(reinterpret_cast(this),&id,sizeof(Identity));
return *this;
}
+ /**
+ * @return Identity type
+ */
+ inline Type type() const { return _type; }
+
/**
* Generate a new identity (address, key pair)
*
* This is a time consuming operation.
+ *
+ * @param t Type of identity to generate
*/
- void generate();
+ void generate(const Type t);
/**
* Check the validity of this identity's pairing of key to address
@@ -120,7 +105,7 @@ public:
/**
* @return True if this identity contains a private key
*/
- inline bool hasPrivate() const { return (_privateKey != (C25519::Private *)0); }
+ inline bool hasPrivate() const { return _hasPrivate; }
/**
* Compute the SHA512 hash of our private key (if we have one)
@@ -130,9 +115,15 @@ public:
*/
inline bool sha512PrivateKey(void *sha) const
{
- if (_privateKey) {
- SHA512::hash(sha,_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN);
- return true;
+ if (_hasPrivate) {
+ switch(_type) {
+ case C25519:
+ SHA512::hash(sha,_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
+ return true;
+ case P384:
+ SHA512::hash(sha,_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE);
+ return true;
+ }
}
return false;
}
@@ -140,14 +131,34 @@ public:
/**
* Sign a message with this identity (private key required)
*
+ * The signature buffer should be large enough for the largest
+ * signature, which is currently 96 bytes.
+ *
* @param data Data to sign
* @param len Length of data
+ * @param sig Buffer to receive signature
+ * @param siglen Length of buffer
+ * @return Number of bytes actually written to sig or 0 on error
*/
- inline C25519::Signature sign(const void *data,unsigned int len) const
+ inline unsigned int sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
{
- if (_privateKey)
- return C25519::sign(*_privateKey,_publicKey,data,len);
- throw ZT_EXCEPTION_PRIVATE_KEY_REQUIRED;
+ uint8_t h[64];
+ if (!_hasPrivate)
+ return 0;
+ switch(_type) {
+ case C25519:
+ if (siglen < ZT_C25519_SIGNATURE_LEN)
+ return 0;
+ C25519::sign(_k.t0.priv,_k.t0.pub,data,len,sig);
+ return ZT_C25519_SIGNATURE_LEN;
+ case P384:
+ if (siglen < ZT_ECC384_SIGNATURE_SIZE)
+ return 0;
+ SHA512::hash(h,data,len);
+ ECC384ECDSASign(_k.t1.priv,h,(uint8_t *)sig);
+ return ZT_ECC384_SIGNATURE_SIZE;
+ }
+ return 0;
}
/**
@@ -159,17 +170,20 @@ public:
* @param siglen Length of signature in bytes
* @return True if signature validates and data integrity checks
*/
- inline bool verify(const void *data,unsigned int len,const void *signature,unsigned int siglen) const { return C25519::verify(_publicKey,data,len,signature,siglen); }
-
- /**
- * Verify a message signature against this identity
- *
- * @param data Data to check
- * @param len Length of data
- * @param signature Signature
- * @return True if signature validates and data integrity checks
- */
- inline bool verify(const void *data,unsigned int len,const C25519::Signature &signature) const { return C25519::verify(_publicKey,data,len,signature); }
+ inline bool verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
+ {
+ uint8_t h[64];
+ switch(_type) {
+ case C25519:
+ return C25519::verify(_k.t0.pub,data,len,sig,siglen);
+ case P384:
+ if (siglen != ZT_ECC384_SIGNATURE_SIZE)
+ return false;
+ SHA512::hash(h,data,len);
+ return ECC384ECDSAVerify(_k.t1.pub,h,(const uint8_t *)sig);
+ }
+ return false;
+ }
/**
* Shortcut method to perform key agreement with another identity
@@ -183,9 +197,26 @@ public:
*/
inline bool agree(const Identity &id,void *key,unsigned int klen) const
{
- if (_privateKey) {
- C25519::agree(*_privateKey,id._publicKey,key,klen);
- return true;
+ uint8_t ecc384RawSecret[ZT_ECC384_SHARED_SECRET_SIZE];
+ uint8_t h[64];
+ if (_hasPrivate) {
+ switch(_type) {
+ case C25519:
+ C25519::agree(_k.t0.priv,id._k.t0.pub,key,klen);
+ return true;
+ case P384:
+ ECC384ECDH(id._k.t1.pub,_k.t1.priv,ecc384RawSecret);
+ SHA512::hash(h,ecc384RawSecret,sizeof(ecc384RawSecret));
+ unsigned int hi = 0;
+ for(unsigned int i=0;i &b,bool includePrivate = false) const
{
_address.appendTo(b);
- b.append((uint8_t)0); // C25519/Ed25519 identity type
- b.append(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN);
- if ((_privateKey)&&(includePrivate)) {
- b.append((unsigned char)ZT_C25519_PRIVATE_KEY_LEN);
- b.append(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN);
- } else b.append((unsigned char)0);
+ switch(_type) {
+ case C25519:
+ b.append((uint8_t)C25519);
+ b.append(_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
+ if ((_hasPrivate)&&(includePrivate)) {
+ b.append((uint8_t)ZT_C25519_PRIVATE_KEY_LEN);
+ b.append(_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
+ } else {
+ b.append((uint8_t)0);
+ }
+ break;
+ case P384:
+ b.append((uint8_t)P384);
+ b.append(_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE);
+ if ((_hasPrivate)&&(includePrivate)) {
+ b.append((uint8_t)ZT_ECC384_PRIVATE_KEY_SIZE);
+ b.append(_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE);
+ } else {
+ b.append((uint8_t)0);
+ }
+ break;
+ }
}
/**
@@ -229,27 +276,47 @@ public:
template
inline unsigned int deserialize(const Buffer &b,unsigned int startAt = 0)
{
- delete _privateKey;
- _privateKey = (C25519::Private *)0;
-
+ _hasPrivate = false;
unsigned int p = startAt;
+ unsigned int pkl;
_address.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
p += ZT_ADDRESS_LENGTH;
- if (b[p++] != 0)
- throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
-
- memcpy(_publicKey.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN);
- p += ZT_C25519_PUBLIC_KEY_LEN;
-
- unsigned int privateKeyLength = (unsigned int)b[p++];
- if (privateKeyLength) {
- if (privateKeyLength != ZT_C25519_PRIVATE_KEY_LEN)
- throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
- _privateKey = new C25519::Private();
- memcpy(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
- p += ZT_C25519_PRIVATE_KEY_LEN;
+ _type = (Type)b[p++];
+ switch(_type) {
+ case C25519:
+ memcpy(_k.t0.pub.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN);
+ p += ZT_C25519_PUBLIC_KEY_LEN;
+ pkl = (unsigned int)b[p++];
+ if (pkl) {
+ if (pkl != ZT_C25519_PRIVATE_KEY_LEN)
+ throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
+ _hasPrivate = true;
+ memcpy(_k.t0.priv.data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
+ p += ZT_C25519_PRIVATE_KEY_LEN;
+ } else {
+ memset(_k.t0.priv.data,0,ZT_C25519_PRIVATE_KEY_LEN);
+ _hasPrivate = false;
+ }
+ break;
+ case P384:
+ memcpy(_k.t0.pub.data,b.field(p,ZT_ECC384_PUBLIC_KEY_SIZE),ZT_ECC384_PUBLIC_KEY_SIZE);
+ p += ZT_ECC384_PUBLIC_KEY_SIZE;
+ pkl = (unsigned int)b[p++];
+ if (pkl) {
+ if (pkl != ZT_ECC384_PRIVATE_KEY_SIZE)
+ throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
+ _hasPrivate = true;
+ memcpy(_k.t1.priv,b.field(p,ZT_ECC384_PRIVATE_KEY_SIZE),ZT_ECC384_PRIVATE_KEY_SIZE);
+ p += ZT_ECC384_PRIVATE_KEY_SIZE;
+ } else {
+ memset(_k.t1.priv,0,ZT_ECC384_PRIVATE_KEY_SIZE);
+ _hasPrivate = false;
+ }
+ break;
+ default:
+ throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
}
return (p - startAt);
@@ -275,40 +342,64 @@ public:
*/
bool fromString(const char *str);
- /**
- * @return C25519 public key
- */
- inline const C25519::Public &publicKey() const { return _publicKey; }
-
- /**
- * @return C25519 key pair (only returns valid pair if private key is present in this Identity object)
- */
- inline const C25519::Pair privateKeyPair() const
- {
- C25519::Pair pair;
- pair.pub = _publicKey;
- if (_privateKey)
- pair.priv = *_privateKey;
- else memset(pair.priv.data,0,ZT_C25519_PRIVATE_KEY_LEN);
- return pair;
- }
-
/**
* @return True if this identity contains something
*/
inline operator bool() const { return (_address); }
- inline bool operator==(const Identity &id) const { return ((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)); }
- inline bool operator<(const Identity &id) const { return ((_address < id._address)||((_address == id._address)&&(memcmp(_publicKey.data,id._publicKey.data,ZT_C25519_PUBLIC_KEY_LEN) < 0))); }
+ inline bool operator==(const Identity &id) const
+ {
+ if ((_address == id._address)&&(_type == id._type)) {
+ switch(_type) {
+ case C25519:
+ return (memcmp(_k.t0.pub.data,id._k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN) == 0);
+ case P384:
+ return (memcmp(_k.t1.pub,id._k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE) == 0);
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+ inline bool operator<(const Identity &id) const
+ {
+ if (_address < id._address)
+ return true;
+ if (_address == id._address) {
+ if ((int)_type < (int)id._type)
+ return true;
+ if (_type == id._type) {
+ switch(_type) {
+ case C25519:
+ return (memcmp(_k.t0.pub.data,id._k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN) < 0);
+ case P384:
+ return (memcmp(_k.t1.pub,id._k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE) < 0);
+ }
+ }
+ }
+ return false;
+ }
inline bool operator!=(const Identity &id) const { return !(*this == id); }
inline bool operator>(const Identity &id) const { return (id < *this); }
inline bool operator<=(const Identity &id) const { return !(id < *this); }
inline bool operator>=(const Identity &id) const { return !(*this < id); }
+ inline unsigned long hashCode() const { return (unsigned long)_address.toInt(); }
+
private:
Address _address;
- C25519::Public _publicKey;
- C25519::Private *_privateKey;
+ union {
+ struct {
+ C25519::Public pub;
+ C25519::Private priv;
+ } t0;
+ struct {
+ uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE];
+ uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE];
+ } t1;
+ } _k;
+ Type _type;
+ bool _hasPrivate;
};
} // namespace ZeroTier
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index bc2c6a7f2..197bfe225 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -43,7 +43,6 @@
#include "SelfAwareness.hpp"
#include "Salsa20.hpp"
#include "SHA512.hpp"
-#include "World.hpp"
#include "Node.hpp"
#include "CertificateOfMembership.hpp"
#include "Capability.hpp"
@@ -368,30 +367,6 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
RR->sa->iam(tPtr,id.address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now);
}
- // Get primary planet world ID and world timestamp if present
- uint64_t planetWorldId = 0;
- uint64_t planetWorldTimestamp = 0;
- if ((ptr + 16) <= size()) {
- planetWorldId = at(ptr); ptr += 8;
- planetWorldTimestamp = at(ptr); ptr += 8;
- }
-
- std::vector< std::pair > moonIdsAndTimestamps;
- if (ptr < size()) {
- // Remainder of packet, if present, is encrypted
- cryptField(peer->key(),ptr,size() - ptr);
-
- // Get moon IDs and timestamps if present
- if ((ptr + 2) <= size()) {
- const unsigned int numMoons = at(ptr); ptr += 2;
- for(unsigned int i=0;i(at(ptr),at(ptr + 8)));
- ptr += 16;
- }
- }
- }
-
// Send OK(HELLO) with an echo of the packet's timestamp and some of the same
// information about us: version, sent-to address, etc.
@@ -435,25 +410,6 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
tmpa.serialize(outp);
}
- const unsigned int worldUpdateSizeAt = outp.size();
- outp.addSize(2); // make room for 16-bit size field
- if ((planetWorldId)&&(RR->topology->planetWorldTimestamp() > planetWorldTimestamp)&&(planetWorldId == RR->topology->planetWorldId())) {
- RR->topology->planet().serialize(outp,false);
- }
- if (moonIdsAndTimestamps.size() > 0) {
- std::vector moons(RR->topology->moons());
- for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) {
- for(std::vector< std::pair >::const_iterator i(moonIdsAndTimestamps.begin());i!=moonIdsAndTimestamps.end();++i) {
- if (i->first == m->id()) {
- if (m->timestamp() > i->second)
- m->serialize(outp,false);
- break;
- }
- }
- }
- }
- outp.setAt(worldUpdateSizeAt,(uint16_t)(outp.size() - (worldUpdateSizeAt + 2)));
-
outp.armor(peer->key(),true);
_path->send(RR,tPtr,outp.data(),outp.size(),now);
@@ -489,22 +445,6 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
// Get reported external surface address if present
if (ptr < size())
ptr += externalSurfaceAddress.deserialize(*this,ptr);
-
- // Handle planet or moon updates if present
- if ((ptr + 2) <= size()) {
- const unsigned int worldsLen = at(ptr); ptr += 2;
- if (RR->topology->shouldAcceptWorldUpdateFrom(peer->address())) {
- const unsigned int endOfWorlds = ptr + worldsLen;
- while (ptr < endOfWorlds) {
- World w;
- ptr += w.deserialize(*this,ptr);
- RR->topology->addWorld(tPtr,w,false);
- }
- } else {
- ptr += worldsLen;
- }
- }
-
if (!hops()) {
_path->updateLatency((unsigned int)latency,RR->node->now());
}
@@ -575,8 +515,9 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr &peer)
{
- if ((!RR->topology->amUpstream())&&(!peer->rateGateInboundWhoisRequest(RR->node->now())))
- return true;
+ // TODO
+ //if ((!RR->topology->amUpstream())&&(!peer->rateGateInboundWhoisRequest(RR->node->now())))
+ // return true;
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((unsigned char)Packet::VERB_WHOIS);
@@ -772,8 +713,8 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,c
SharedPtr network(RR->node->network(nwid));
if (network)
authorized = network->gate(tPtr,peer);
- if (!authorized)
- authorized = ((RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())));
+ //if (!authorized)
+ // authorized = ((RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())));
}
if (authorized)
RR->mc->add(tPtr,now,nwid,MulticastGroup(MAC(field(ptr + 8,6),6),at(ptr + 14)),peer->address());
@@ -982,7 +923,8 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
}
const int64_t now = RR->node->now();
- if ((gatherLimit > 0)&&((trustEstablished)||(RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())))) {
+ //if ((gatherLimit > 0)&&((trustEstablished)||(RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())))) {
+ if (gatherLimit) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER);
outp.append(packetId());
diff --git a/node/Node.cpp b/node/Node.cpp
index e71e898bd..609795ebb 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -93,7 +93,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
}
if (n <= 0) {
- RR->identity.generate();
+ RR->identity.generate(Identity::C25519);
RR->identity.toString(false,RR->publicIdentityStr);
RR->identity.toString(true,RR->secretIdentityStr);
idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0;
@@ -192,16 +192,17 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
-// Closure used to ping upstream and active/online peers
-class _PingPeersThatNeedPing
+// Function object used to traverse the peer list, check peer status, and ping
+// those that need pinging.
+struct _PingPeersThatNeedPing
{
-public:
_PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector > &alwaysContact,int64_t now) :
RR(renv),
_tPtr(tPtr),
_alwaysContact(alwaysContact),
_now(now),
- _bestCurrentUpstream(RR->topology->getUpstreamPeer())
+ _bestCurrentUpstream(RR->topology->getUpstreamPeer()),
+ online(false)
{
}
@@ -209,6 +210,7 @@ public:
{
const std::vector *const alwaysContactEndpoints = _alwaysContact.get(p->address());
if (alwaysContactEndpoints) {
+ online |= p->isAlive(_now);
const unsigned int sent = p->doPingAndKeepalive(_tPtr,_now);
bool contacted = (sent != 0);
@@ -246,12 +248,13 @@ public:
}
}
-private:
const RuntimeEnvironment *RR;
void *_tPtr;
Hashtable< Address,std::vector > &_alwaysContact;
const int64_t _now;
const SharedPtr _bestCurrentUpstream;
+
+ bool online;
};
ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline)
@@ -265,38 +268,25 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
try {
_lastPingCheck = now;
- // Get designated VL1 upstreams
- Hashtable< Address,std::vector > alwaysContact;
- RR->topology->getUpstreamsToContact(alwaysContact);
-
- // Check last receive time on designated upstreams to see if we seem to be online
- int64_t lastReceivedFromUpstream = 0;
- {
- Hashtable< Address,std::vector >::Iterator i(alwaysContact);
- Address *upstreamAddress = (Address *)0;
- std::vector *upstreamStableEndpoints = (std::vector *)0;
- while (i.next(upstreamAddress,upstreamStableEndpoints)) {
- SharedPtr p(RR->topology->getPeerNoCache(*upstreamAddress));
- if (p)
- lastReceivedFromUpstream = std::max(p->lastReceive(),lastReceivedFromUpstream);
- }
- }
-
- // Clean up any old local controller auth memorizations.
+ // Clean up any old local controller auth memoizations. This is an
+ // optimization for network controllers to know whether to accept
+ // or trust nodes without doing an extra cert check.
{
_localControllerAuthorizations_m.lock();
Hashtable< _LocalControllerAuth,int64_t >::Iterator i(_localControllerAuthorizations);
_LocalControllerAuth *k = (_LocalControllerAuth *)0;
int64_t *v = (int64_t *)0;
while (i.next(k,v)) {
- if ((*v - now) > (ZT_NETWORK_AUTOCONF_DELAY * 3))
+ if ((*v - now) > (ZT_NETWORK_AUTOCONF_DELAY * 3)) {
_localControllerAuthorizations.erase(*k);
+ }
}
_localControllerAuthorizations_m.unlock();
}
- // Get peers we should stay connected to according to network configs
- // Also get networks and whether they need config so we only have to do one pass over networks
+ // (1) Get peers we should remain connected to and (2) get networks that need config.
+ Hashtable< Address,std::vector > alwaysContact;
+ RR->topology->getUpstreamsToContact(alwaysContact);
std::vector< std::pair< SharedPtr,bool > > networkConfigNeeded;
{
Mutex::Lock l(_networks_m);
@@ -331,7 +321,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
// Update online status, post status change as event
const bool oldOnline = _online;
- _online = (((now - lastReceivedFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amUpstream()));
+ _online = pfunc.online;
if (oldOnline != _online)
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
} catch ( ... ) {
@@ -425,18 +415,6 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
-ZT_ResultCode Node::orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed)
-{
- RR->topology->addMoon(tptr,moonWorldId,Address(moonSeed));
- return ZT_RESULT_OK;
-}
-
-ZT_ResultCode Node::deorbit(void *tptr,uint64_t moonWorldId)
-{
- RR->topology->removeMoon(tptr,moonWorldId);
- return ZT_RESULT_OK;
-}
-
uint64_t Node::address() const
{
return RR->identity.address().toInt();
@@ -635,16 +613,6 @@ ZT_ResultCode Node::setPhysicalPathConfiguration(const struct sockaddr_storage *
return ZT_RESULT_OK;
}
-World Node::planet() const
-{
- return RR->topology->planet();
-}
-
-std::vector Node::moons() const
-{
- return RR->topology->moons();
-}
-
void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
{
_localControllerAuthorizations_m.lock();
@@ -682,10 +650,11 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
outp.append((uint32_t)totalSize);
outp.append((uint32_t)chunkIndex);
- C25519::Signature sig(RR->identity.sign(reinterpret_cast(outp.data()) + sigStart,outp.size() - sigStart));
+ uint8_t sig[256];
+ const unsigned int siglen = RR->identity.sign(reinterpret_cast(outp.data()) + sigStart,outp.size() - sigStart,sig,sizeof(sig));
outp.append((uint8_t)1);
- outp.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
- outp.append(sig.data,ZT_C25519_SIGNATURE_LEN);
+ outp.append((uint16_t)siglen);
+ outp.append(sig,siglen);
outp.compress();
RR->sw->send((void *)0,outp,true);
@@ -879,24 +848,6 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint
}
}
-enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,uint64_t moonSeed)
-{
- try {
- return reinterpret_cast(node)->orbit(tptr,moonWorldId,moonSeed);
- } catch ( ... ) {
- return ZT_RESULT_FATAL_ERROR_INTERNAL;
- }
-}
-
-enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId)
-{
- try {
- return reinterpret_cast(node)->deorbit(tptr,moonWorldId);
- } catch ( ... ) {
- return ZT_RESULT_FATAL_ERROR_INTERNAL;
- }
-}
-
uint64_t ZT_Node_address(ZT_Node *node)
{
return reinterpret_cast(node)->address();
diff --git a/node/Node.hpp b/node/Node.hpp
index a6f92eb11..e751b36bf 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -54,8 +54,6 @@
namespace ZeroTier {
-class World;
-
/**
* Implementation of Node object as defined in CAPI
*
@@ -99,8 +97,6 @@ public:
ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
- ZT_ResultCode orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed);
- ZT_ResultCode deorbit(void *tptr,uint64_t moonWorldId);
uint64_t address() const;
void status(ZT_NodeStatus *status) const;
ZT_PeerList *peers() const;
@@ -194,9 +190,6 @@ public:
uint64_t prng();
ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig);
- World planet() const;
- std::vector moons() const;
-
inline const Identity &identity() const { return _RR.identity; }
/**
diff --git a/node/Packet.cpp b/node/Packet.cpp
index 5d0885d37..1c2ac86a7 100644
--- a/node/Packet.cpp
+++ b/node/Packet.cpp
@@ -972,16 +972,6 @@ bool Packet::dearmor(const void *key)
}
}
-void Packet::cryptField(const void *key,unsigned int start,unsigned int len)
-{
- uint8_t *const data = reinterpret_cast(unsafeData());
- uint8_t iv[8];
- for(int i=0;i<8;++i) iv[i] = data[i];
- iv[7] &= 0xf8; // mask off least significant 3 bits of packet ID / IV since this is unset when this function gets called
- Salsa20 s20(key,iv);
- s20.crypt12(data + start,data + start,len);
-}
-
bool Packet::compress()
{
char *const data = reinterpret_cast(unsafeData());
diff --git a/node/Packet.hpp b/node/Packet.hpp
index f35714cc0..426274d77 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -71,6 +71,7 @@
* 10 - 1.4.0 ... CURRENT
* + Multipath capability and load balancing
* + Peer-to-peer multicast replication (optional)
+ * + Old planet/moon stuff is DEAD!
*/
#define ZT_PROTO_VERSION 10
@@ -532,22 +533,9 @@ public:
* <[8] timestamp for determining latency>
* <[...] binary serialized identity (see Identity)>
* <[...] physical destination address of packet>
- * <[8] 64-bit world ID of current planet>
- * <[8] 64-bit timestamp of current planet>
- * [... remainder if packet is encrypted using cryptField() ...]
- * <[2] 16-bit number of moons>
- * [<[1] 8-bit type ID of moon>]
- * [<[8] 64-bit world ID of moon>]
- * [<[8] 64-bit timestamp of moon>]
- * [... additional moon type/ID/timestamp tuples ...]
- *
+ *
* HELLO is sent in the clear as it is how peers share their identity
- * public keys. A few additional fields are sent in the clear too, but
- * these are things that are public info or are easy to determine. As
- * of 1.2.0 we have added a few more fields, but since these could have
- * the potential to be sensitive we introduced the encryption of the
- * remainder of the packet. See cryptField(). Packet MAC is still
- * performed of course, so authentication occurs as normal.
+ * public keys.
*
* Destination address is the actual wire address to which the packet
* was sent. See InetAddress::serialize() for format.
@@ -559,15 +547,10 @@ public:
* <[1] software minor version>
* <[2] software revision>
* <[...] physical destination address of packet>
- * <[2] 16-bit length of world update(s) or 0 if none>
- * [[...] updates to planets and/or moons]
*
* With the exception of the timestamp, the other fields pertain to the
* respondent who is sending OK and are not echoes.
*
- * Note that OK is fully encrypted so no selective cryptField() of
- * potentially sensitive fields is needed.
- *
* ERROR has no payload.
*/
VERB_HELLO = 0x01,
@@ -1268,21 +1251,6 @@ public:
*/
bool dearmor(const void *key);
- /**
- * Encrypt/decrypt a separately armored portion of a packet
- *
- * This is currently only used to mask portions of HELLO as an extra
- * security precaution since most of that message is sent in the clear.
- *
- * This must NEVER be used more than once in the same packet, as doing
- * so will result in re-use of the same key stream.
- *
- * @param key 32-byte key
- * @param start Start of encrypted portion
- * @param len Length of encrypted portion
- */
- void cryptField(const void *key,unsigned int start,unsigned int len);
-
/**
* Attempt to compress payload if not already (must be unencrypted)
*
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 5f5d1462b..4ef481c08 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -711,27 +711,6 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
RR->identity.serialize(outp,false);
atAddress.serialize(outp);
- outp.append((uint64_t)RR->topology->planetWorldId());
- outp.append((uint64_t)RR->topology->planetWorldTimestamp());
-
- const unsigned int startCryptedPortionAt = outp.size();
-
- std::vector moons(RR->topology->moons());
- std::vector moonsWanted(RR->topology->moonsWanted());
- outp.append((uint16_t)(moons.size() + moonsWanted.size()));
- for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) {
- outp.append((uint8_t)m->type());
- outp.append((uint64_t)m->id());
- outp.append((uint64_t)m->timestamp());
- }
- for(std::vector::const_iterator m(moonsWanted.begin());m!=moonsWanted.end();++m) {
- outp.append((uint8_t)World::TYPE_MOON);
- outp.append(*m);
- outp.append((uint64_t)0);
- }
-
- outp.cryptField(_key,startCryptedPortionAt,outp.size() - startCryptedPortionAt);
-
RR->node->expectReplyTo(outp.packetId());
if (atAddress) {
diff --git a/node/Revocation.cpp b/node/Revocation.cpp
index 043425690..75b71e9c5 100644
--- a/node/Revocation.cpp
+++ b/node/Revocation.cpp
@@ -34,6 +34,18 @@
namespace ZeroTier {
+bool Revocation::sign(const Identity &signer)
+{
+ if (signer.hasPrivate()) {
+ Buffer tmp;
+ _signedBy = signer.address();
+ this->serialize(tmp,true);
+ _signatureLength = signer.sign(tmp.data(),tmp.size(),_signature,sizeof(_signature));
+ return true;
+ }
+ return false;
+}
+
int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
@@ -46,7 +58,7 @@ int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
try {
Buffer tmp;
this->serialize(tmp,true);
- return (id.verify(tmp.data(),tmp.size(),_signature) ? 0 : -1);
+ return (id.verify(tmp.data(),tmp.size(),_signature,_signatureLength) ? 0 : -1);
} catch ( ... ) {
return -1;
}
diff --git a/node/Revocation.hpp b/node/Revocation.hpp
index 1d001a405..94ba64596 100644
--- a/node/Revocation.hpp
+++ b/node/Revocation.hpp
@@ -66,9 +66,9 @@ public:
_flags(0),
_target(),
_signedBy(),
- _type(Credential::CREDENTIAL_TYPE_NULL)
+ _type(Credential::CREDENTIAL_TYPE_NULL),
+ _signatureLength(0)
{
- memset(_signature.data,0,sizeof(_signature.data));
}
/**
@@ -88,9 +88,9 @@ public:
_flags(fl),
_target(tgt),
_signedBy(),
- _type(ct)
+ _type(ct),
+ _signatureLength(0)
{
- memset(_signature.data,0,sizeof(_signature.data));
}
inline uint32_t id() const { return _id; }
@@ -107,17 +107,7 @@ public:
* @param signer Signing identity, must have private key
* @return True if signature was successful
*/
- inline bool sign(const Identity &signer)
- {
- if (signer.hasPrivate()) {
- Buffer tmp;
- _signedBy = signer.address();
- this->serialize(tmp,true);
- _signature = signer.sign(tmp.data(),tmp.size());
- return true;
- }
- return false;
- }
+ bool sign(const Identity &signer);
/**
* Verify this revocation's signature
@@ -145,9 +135,9 @@ public:
b.append((uint8_t)_type);
if (!forSign) {
- b.append((uint8_t)1); // 1 == Ed25519 signature
- b.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
- b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+ b.append((uint8_t)1);
+ b.append((uint16_t)_signatureLength);
+ b.append(_signature,_signatureLength);
}
// This is the size of any additional fields, currently 0.
@@ -175,11 +165,10 @@ public:
_type = (Credential::Type)b[p++];
if (b[p++] == 1) {
- if (b.template at(p) == ZT_C25519_SIGNATURE_LEN) {
- p += 2;
- memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
- p += ZT_C25519_SIGNATURE_LEN;
- } else throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
+ _signatureLength = b.template at(p);
+ if (_signatureLength > sizeof(_signature))
+ throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
+ memcpy(_signature,b.field(p,_signatureLength),_signatureLength);
} else {
p += 2 + b.template at(p);
}
@@ -200,7 +189,8 @@ private:
Address _target;
Address _signedBy;
Credential::Type _type;
- C25519::Signature _signature;
+ unsigned int _signatureLength;
+ uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
};
} // namespace ZeroTier
diff --git a/node/Switch.cpp b/node/Switch.cpp
index a6852d9f4..66d5da6d3 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -92,9 +92,6 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
const Address destination(fragment.destination());
if (destination != RR->identity.address()) {
- if ( (!RR->topology->amUpstream()) && (!path->trustEstablished(now)) )
- return;
-
if (fragment.hops() < ZT_RELAY_MAX_HOPS) {
fragment.incrementHops();
@@ -164,11 +161,7 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
return;
if (destination != RR->identity.address()) {
- if ( (!RR->topology->amUpstream()) && (!path->trustEstablished(now)) && (source != RR->identity.address()) )
- return;
-
Packet packet(data,len);
-
if (packet.hops() < ZT_RELAY_MAX_HOPS) {
packet.incrementHops();
SharedPtr relayTo = RR->topology->getPeer(tPtr,destination);
diff --git a/node/Tag.cpp b/node/Tag.cpp
index 6c78f3e48..3ae29319e 100644
--- a/node/Tag.cpp
+++ b/node/Tag.cpp
@@ -34,6 +34,18 @@
namespace ZeroTier {
+bool Tag::sign(const Identity &signer)
+{
+ if (signer.hasPrivate()) {
+ Buffer tmp;
+ _signedBy = signer.address();
+ this->serialize(tmp,true);
+ _signatureLength = signer.sign(tmp.data(),tmp.size(),_signature,sizeof(_signature));
+ return true;
+ }
+ return false;
+}
+
int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
{
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId)))
@@ -46,7 +58,7 @@ int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
try {
Buffer<(sizeof(Tag) * 2)> tmp;
this->serialize(tmp,true);
- return (id.verify(tmp.data(),tmp.size(),_signature) ? 0 : -1);
+ return (id.verify(tmp.data(),tmp.size(),_signature,_signatureLength) ? 0 : -1);
} catch ( ... ) {
return -1;
}
diff --git a/node/Tag.hpp b/node/Tag.hpp
index 3f888ba91..e5ac891bd 100644
--- a/node/Tag.hpp
+++ b/node/Tag.hpp
@@ -69,9 +69,9 @@ public:
_id(0),
_value(0),
_networkId(0),
- _ts(0)
+ _ts(0),
+ _signatureLength(0)
{
- memset(_signature.data,0,sizeof(_signature.data));
}
/**
@@ -87,9 +87,9 @@ public:
_networkId(nwid),
_ts(ts),
_issuedTo(issuedTo),
- _signedBy()
+ _signedBy(),
+ _signatureLength(0)
{
- memset(_signature.data,0,sizeof(_signature.data));
}
inline uint32_t id() const { return _id; }
@@ -105,17 +105,7 @@ public:
* @param signer Signing identity, must have private key
* @return True if signature was successful
*/
- inline bool sign(const Identity &signer)
- {
- if (signer.hasPrivate()) {
- Buffer tmp;
- _signedBy = signer.address();
- this->serialize(tmp,true);
- _signature = signer.sign(tmp.data(),tmp.size());
- return true;
- }
- return false;
- }
+ bool sign(const Identity &signer);
/**
* Check this tag's signature
@@ -139,9 +129,9 @@ public:
_issuedTo.appendTo(b);
_signedBy.appendTo(b);
if (!forSign) {
- b.append((uint8_t)1); // 1 == Ed25519
- b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature
- b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
+ b.append((uint8_t)1);
+ b.append((uint16_t)_signatureLength);
+ b.append(_signature,_signatureLength);
}
b.append((uint16_t)0); // length of additional fields, currently 0
@@ -165,10 +155,11 @@ public:
_issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
if (b[p++] == 1) {
- if (b.template at(p) != ZT_C25519_SIGNATURE_LEN)
+ _signatureLength = b.template at(p);
+ if (_signatureLength > sizeof(_signature))
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
p += 2;
- memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN;
+ memcpy(_signature,b.field(p,_signatureLength),_signatureLength); p += _signatureLength;
} else {
p += 2 + b.template at(p);
}
@@ -207,7 +198,8 @@ private:
int64_t _ts;
Address _issuedTo;
Address _signedBy;
- C25519::Signature _signature;
+ unsigned int _signatureLength;
+ uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
};
} // namespace ZeroTier
diff --git a/node/Topology.cpp b/node/Topology.cpp
index 6d6beda33..985dd5d80 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -35,57 +35,10 @@
namespace ZeroTier {
-/*
- * 2018-07-26 ZeroTier planet definition for the third planet of Sol:
- *
- * There are two roots, each of which is a cluster spread across multiple
- * continents and providers. They are named Alice and Bob after the
- * canonical example names used in cryptography.
- *
- * Alice:
- *
- * root-alice-ams-01: Amsterdam, Netherlands
- * root-alice-joh-01: Johannesburg, South Africa
- * root-alice-nyc-01: New York, New York, USA
- * root-alice-arg-01: Buenos Aires, Argentina
- * root-alice-sfo-01: San Francisco, California, USA
- * root-alice-sgp-01: Singapore
- *
- * Bob:
- *
- * root-bob-dfw-01: Dallas, Texas, USA
- * root-bob-fra-01: Frankfurt, Germany
- * root-bob-par-01: Paris, France
- * root-bob-syd-01: Sydney, Australia
- * root-bob-tok-01: Tokyo, Japan
- * root-bob-tor-01: Toronto, Canada
- */
-#define ZT_DEFAULT_WORLD_LENGTH 634
-static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x00,0x00,0x00,0x00,0x08,0xea,0xc9,0x0a,0x00,0x00,0x01,0x64,0xd3,0x71,0xf0,0x58,0xb8,0xb3,0x88,0xa4,0x69,0x22,0x14,0x91,0xaa,0x9a,0xcd,0x66,0xcc,0x76,0x4c,0xde,0xfd,0x56,0x03,0x9f,0x10,0x67,0xae,0x15,0xe6,0x9c,0x6f,0xb4,0x2d,0x7b,0x55,0x33,0x0e,0x3f,0xda,0xac,0x52,0x9c,0x07,0x92,0xfd,0x73,0x40,0xa6,0xaa,0x21,0xab,0xa8,0xa4,0x89,0xfd,0xae,0xa4,0x4a,0x39,0xbf,0x2d,0x00,0x65,0x9a,0xc9,0xc8,0x18,0xeb,0xbf,0xfd,0xd5,0x32,0xf7,0x15,0x6e,0x02,0x6f,0xb9,0x01,0x0d,0xb5,0x7b,0x04,0xd8,0x3a,0xc5,0x17,0x39,0x04,0x36,0xfd,0x9d,0xc6,0x3d,0xa8,0xf3,0x8e,0x79,0xe7,0xc8,0x77,0x8d,0xcc,0x79,0xb8,0xab,0xc6,0x98,0x7c,0x9f,0x34,0x25,0x14,0xe1,0x2f,0xd7,0x97,0x11,0xec,0x34,0x4c,0x9f,0x0f,0xb4,0x85,0x0d,0x9b,0x11,0xd1,0xc2,0xce,0x00,0xc4,0x0a,0x13,0x4b,0xcb,0xc3,0xae,0x2e,0x16,0x00,0x4b,0xdc,0x90,0x5e,0x7e,0x9b,0x44,0x07,0x15,0x36,0x61,0x3c,0x64,0xaa,0xe9,0x46,0x78,0x3c,0xa7,0x18,0xc8,0xd8,0x02,0x9d,0x21,0x90,0x39,0xf3,0x00,0x01,0xf0,0x92,0x2a,0x98,0xe3,0xb3,0x4e,0xbc,0xbf,0xf3,0x33,0x26,0x9d,0xc2,0x65,0xd7,0xa0,0x20,0xaa,0xb6,0x9d,0x72,0xbe,0x4d,0x4a,0xcc,0x9c,0x8c,0x92,0x94,0x78,0x57,0x71,0x25,0x6c,0xd1,0xd9,0x42,0xa9,0x0d,0x1b,0xd1,0xd2,0xdc,0xa3,0xea,0x84,0xef,0x7d,0x85,0xaf,0xe6,0x61,0x1f,0xb4,0x3f,0xf0,0xb7,0x41,0x26,0xd9,0x0a,0x6e,0x00,0x0c,0x04,0xbc,0xa6,0x5e,0xb1,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x7d,0x00,0x01,0x00,0x00,0x00,0x00,0x27,0x09,0x04,0x9a,0x42,0xc5,0x21,0x27,0x09,0x06,0x2c,0x0f,0xf8,0x50,0x01,0x54,0x01,0x97,0x00,0x33,0xcc,0x08,0xf8,0xfa,0xcc,0x08,0x27,0x09,0x04,0x9f,0xcb,0x61,0xab,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x54,0x60,0x01,0x00,0xfc,0xcc,0x08,0x27,0x09,0x04,0x83,0xff,0x06,0x10,0x27,0x09,0x06,0x28,0x03,0xeb,0x80,0x00,0x00,0x00,0x0e,0x00,0x02,0x60,0x01,0x00,0xfc,0xcc,0x08,0x27,0x09,0x04,0x6b,0xaa,0xc5,0x0e,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x02,0x00,0xe0,0x01,0x08,0xfe,0xcc,0x08,0x27,0x09,0x04,0x80,0xc7,0xc5,0xd9,0x27,0x09,0x06,0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0xb7,0x40,0x01,0x08,0xfe,0xcc,0x08,0x27,0x09,0x88,0x41,0x40,0x8a,0x2e,0x00,0xbb,0x1d,0x31,0xf2,0xc3,0x23,0xe2,0x64,0xe9,0xe6,0x41,0x72,0xc1,0xa7,0x4f,0x77,0x89,0x95,0x55,0xed,0x10,0x75,0x1c,0xd5,0x6e,0x86,0x40,0x5c,0xde,0x11,0x8d,0x02,0xdf,0xfe,0x55,0x5d,0x46,0x2c,0xcf,0x6a,0x85,0xb5,0x63,0x1c,0x12,0x35,0x0c,0x8d,0x5d,0xc4,0x09,0xba,0x10,0xb9,0x02,0x5d,0x0f,0x44,0x5c,0xf4,0x49,0xd9,0x2b,0x1c,0x00,0x0c,0x04,0x2d,0x20,0xc6,0x82,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x64,0x00,0x81,0xc3,0x54,0x00,0x00,0xff,0xfe,0x18,0x1d,0x61,0x27,0x09,0x04,0x2e,0x65,0xa0,0xf9,0x27,0x09,0x06,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x6a,0x30,0x01,0x78,0x00,0xcd,0x08,0x27,0x09,0x04,0x6b,0xbf,0x2e,0xd2,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x68,0x00,0x83,0xa4,0x00,0x64,0xcd,0x08,0x80,0x01,0xcd,0x08,0x27,0x09,0x04,0x2d,0x20,0xf6,0xb3,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x58,0x00,0x8b,0xf8,0x54,0x00,0x00,0xff,0xfe,0x15,0xb3,0x9a,0x27,0x09,0x04,0x2d,0x20,0xf8,0x57,0x27,0x09,0x06,0x20,0x01,0x19,0xf0,0x70,0x00,0x9b,0xc9,0x54,0x00,0x00,0xff,0xfe,0x15,0xc4,0xf5,0x27,0x09,0x04,0x9f,0xcb,0x02,0x9a,0x27,0x09,0x06,0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x26,0x70,0x01,0xfe,0x15,0xc4,0xf5,0x27,0x09};
-
Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
RR(renv),
- _numConfiguredPhysicalPaths(0),
- _amUpstream(false)
+ _numConfiguredPhysicalPaths(0)
{
- uint8_t tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH];
- uint64_t idtmp[2];
- idtmp[0] = 0; idtmp[1] = 0;
- int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PLANET,idtmp,tmp,sizeof(tmp));
- if (n > 0) {
- try {
- World cachedPlanet;
- cachedPlanet.deserialize(Buffer(tmp,(unsigned int)n),0);
- addWorld(tPtr,cachedPlanet,false);
- } catch ( ... ) {} // ignore invalid cached planets
- }
-
- World defaultPlanet;
- {
- Buffer wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH);
- defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top
- }
- addWorld(tPtr,defaultPlanet,false);
}
Topology::~Topology()
@@ -158,224 +111,33 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta)
SharedPtr Topology::getUpstreamPeer()
{
- const int64_t now = RR->node->now();
- unsigned int bestq = ~((unsigned int)0);
- const SharedPtr *best = (const SharedPtr *)0;
-
- Mutex::Lock _l2(_peers_m);
- Mutex::Lock _l1(_upstreams_m);
-
- for(std::vector::const_iterator a(_upstreamAddresses.begin());a!=_upstreamAddresses.end();++a) {
- const SharedPtr *p = _peers.get(*a);
- if (p) {
- const unsigned int q = (*p)->relayQuality(now);
- if (q <= bestq) {
- bestq = q;
- best = p;
- }
- }
- }
-
- if (!best)
- return SharedPtr();
- return *best;
+ return SharedPtr();
}
bool Topology::isUpstream(const Identity &id) const
{
- Mutex::Lock _l(_upstreams_m);
- return (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),id.address()) != _upstreamAddresses.end());
-}
-
-bool Topology::shouldAcceptWorldUpdateFrom(const Address &addr) const
-{
- Mutex::Lock _l(_upstreams_m);
- if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),addr) != _upstreamAddresses.end())
- return true;
- for(std::vector< std::pair< uint64_t,Address> >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) {
- if (s->second == addr)
- return true;
- }
return false;
}
ZT_PeerRole Topology::role(const Address &ztaddr) const
{
- Mutex::Lock _l(_upstreams_m);
- if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) {
- for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
- if (i->identity.address() == ztaddr)
- return ZT_PEER_ROLE_PLANET;
- }
- return ZT_PEER_ROLE_MOON;
- }
return ZT_PEER_ROLE_LEAF;
}
bool Topology::isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const
{
- Mutex::Lock _l(_upstreams_m);
-
- // For roots the only permitted addresses are those defined. This adds just a little
- // bit of extra security against spoofing, replaying, etc.
- if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) {
- for(std::vector::const_iterator r(_planet.roots().begin());r!=_planet.roots().end();++r) {
- if (r->identity.address() == ztaddr) {
- if (r->stableEndpoints.size() == 0)
- return false; // no stable endpoints specified, so allow dynamic paths
- for(std::vector::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) {
- if (ipaddr.ipsEqual(*e))
- return false;
- }
- }
- }
- for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) {
- for(std::vector::const_iterator r(m->roots().begin());r!=m->roots().end();++r) {
- if (r->identity.address() == ztaddr) {
- if (r->stableEndpoints.size() == 0)
- return false; // no stable endpoints specified, so allow dynamic paths
- for(std::vector::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) {
- if (ipaddr.ipsEqual(*e))
- return false;
- }
- }
- }
- }
- return true;
- }
-
return false;
}
-bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
-{
- if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON))
- return false;
-
- Mutex::Lock _l2(_peers_m);
- Mutex::Lock _l1(_upstreams_m);
-
- World *existing = (World *)0;
- switch(newWorld.type()) {
- case World::TYPE_PLANET:
- existing = &_planet;
- break;
- case World::TYPE_MOON:
- for(std::vector< World >::iterator m(_moons.begin());m!=_moons.end();++m) {
- if (m->id() == newWorld.id()) {
- existing = &(*m);
- break;
- }
- }
- break;
- default:
- return false;
- }
-
- if (existing) {
- if (existing->shouldBeReplacedBy(newWorld))
- *existing = newWorld;
- else return false;
- } else if (newWorld.type() == World::TYPE_MOON) {
- if (alwaysAcceptNew) {
- _moons.push_back(newWorld);
- existing = &(_moons.back());
- } else {
- for(std::vector< std::pair >::iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) {
- if (m->first == newWorld.id()) {
- for(std::vector::const_iterator r(newWorld.roots().begin());r!=newWorld.roots().end();++r) {
- if (r->identity.address() == m->second) {
- _moonSeeds.erase(m);
- _moons.push_back(newWorld);
- existing = &(_moons.back());
- break;
- }
- }
- if (existing)
- break;
- }
- }
- }
- if (!existing)
- return false;
- } else {
- return false;
- }
-
- try {
- Buffer sbuf;
- existing->serialize(sbuf,false);
- uint64_t idtmp[2];
- idtmp[0] = existing->id(); idtmp[1] = 0;
- RR->node->stateObjectPut(tPtr,(existing->type() == World::TYPE_PLANET) ? ZT_STATE_OBJECT_PLANET : ZT_STATE_OBJECT_MOON,idtmp,sbuf.data(),sbuf.size());
- } catch ( ... ) {}
-
- _memoizeUpstreams(tPtr);
-
- return true;
-}
-
-void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed)
-{
- char tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH];
- uint64_t idtmp[2];
- idtmp[0] = id; idtmp[1] = 0;
- int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_MOON,idtmp,tmp,sizeof(tmp));
- if (n > 0) {
- try {
- World w;
- w.deserialize(Buffer(tmp,(unsigned int)n));
- if ((w.type() == World::TYPE_MOON)&&(w.id() == id)) {
- addWorld(tPtr,w,true);
- return;
- }
- } catch ( ... ) {}
- }
-
- if (seed) {
- Mutex::Lock _l(_upstreams_m);
- if (std::find(_moonSeeds.begin(),_moonSeeds.end(),std::pair(id,seed)) == _moonSeeds.end())
- _moonSeeds.push_back(std::pair(id,seed));
- }
-}
-
-void Topology::removeMoon(void *tPtr,const uint64_t id)
-{
- Mutex::Lock _l2(_peers_m);
- Mutex::Lock _l1(_upstreams_m);
-
- std::vector nm;
- for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) {
- if (m->id() != id) {
- nm.push_back(*m);
- } else {
- uint64_t idtmp[2];
- idtmp[0] = id; idtmp[1] = 0;
- RR->node->stateObjectDelete(tPtr,ZT_STATE_OBJECT_MOON,idtmp);
- }
- }
- _moons.swap(nm);
-
- std::vector< std::pair > cm;
- for(std::vector< std::pair >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) {
- if (m->first != id)
- cm.push_back(*m);
- }
- _moonSeeds.swap(cm);
-
- _memoizeUpstreams(tPtr);
-}
-
void Topology::doPeriodicTasks(void *tPtr,int64_t now)
{
{
Mutex::Lock _l1(_peers_m);
- Mutex::Lock _l2(_upstreams_m);
Hashtable< Address,SharedPtr >::Iterator i(_peers);
Address *a = (Address *)0;
SharedPtr *p = (SharedPtr *)0;
while (i.next(a,p)) {
- if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) {
+ if (!(*p)->isAlive(now)) {
_savePeer(tPtr,*p);
_peers.erase(*a);
}
@@ -394,39 +156,6 @@ void Topology::doPeriodicTasks(void *tPtr,int64_t now)
}
}
-void Topology::_memoizeUpstreams(void *tPtr)
-{
- // assumes _upstreams_m and _peers_m are locked
- _upstreamAddresses.clear();
- _amUpstream = false;
-
- for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
- if (i->identity == RR->identity) {
- _amUpstream = true;
- } else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) {
- _upstreamAddresses.push_back(i->identity.address());
- SharedPtr &hp = _peers[i->identity.address()];
- if (!hp)
- hp = new Peer(RR,RR->identity,i->identity);
- }
- }
-
- for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) {
- for(std::vector::const_iterator i(m->roots().begin());i!=m->roots().end();++i) {
- if (i->identity == RR->identity) {
- _amUpstream = true;
- } else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) {
- _upstreamAddresses.push_back(i->identity.address());
- SharedPtr &hp = _peers[i->identity.address()];
- if (!hp)
- hp = new Peer(RR,RR->identity,i->identity);
- }
- }
- }
-
- std::sort(_upstreamAddresses.begin(),_upstreamAddresses.end());
-}
-
void Topology::_savePeer(void *tPtr,const SharedPtr &peer)
{
try {
diff --git a/node/Topology.hpp b/node/Topology.hpp
index b6690f580..35c4e7ab3 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -45,7 +45,6 @@
#include "Mutex.hpp"
#include "InetAddress.hpp"
#include "Hashtable.hpp"
-#include "World.hpp"
namespace ZeroTier {
@@ -136,12 +135,6 @@ public:
*/
bool isUpstream(const Identity &id) const;
- /**
- * @param addr Address to check
- * @return True if we should accept a world update from this address
- */
- bool shouldAcceptWorldUpdateFrom(const Address &addr) const;
-
/**
* @param ztaddr ZeroTier address
* @return Peer role for this device
@@ -171,29 +164,6 @@ public:
*/
inline void getUpstreamsToContact(Hashtable< Address,std::vector > &eps) const
{
- Mutex::Lock _l(_upstreams_m);
- for(std::vector::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
- if (i->identity != RR->identity) {
- std::vector &ips = eps[i->identity.address()];
- for(std::vector::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
- if (std::find(ips.begin(),ips.end(),*j) == ips.end())
- ips.push_back(*j);
- }
- }
- }
- for(std::vector::const_iterator m(_moons.begin());m!=_moons.end();++m) {
- for(std::vector::const_iterator i(m->roots().begin());i!=m->roots().end();++i) {
- if (i->identity != RR->identity) {
- std::vector &ips = eps[i->identity.address()];
- for(std::vector::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
- if (std::find(ips.begin(),ips.end(),*j) == ips.end())
- ips.push_back(*j);
- }
- }
- }
- }
- for(std::vector< std::pair >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m)
- eps[m->second];
}
/**
@@ -201,87 +171,9 @@ public:
*/
inline std::vector upstreamAddresses() const
{
- Mutex::Lock _l(_upstreams_m);
- return _upstreamAddresses;
+ return std::vector();
}
- /**
- * @return Current moons
- */
- inline std::vector moons() const
- {
- Mutex::Lock _l(_upstreams_m);
- return _moons;
- }
-
- /**
- * @return Moon IDs we are waiting for from seeds
- */
- inline std::vector moonsWanted() const
- {
- Mutex::Lock _l(_upstreams_m);
- std::vector mw;
- for(std::vector< std::pair >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) {
- if (std::find(mw.begin(),mw.end(),s->first) == mw.end())
- mw.push_back(s->first);
- }
- return mw;
- }
-
- /**
- * @return Current planet
- */
- inline World planet() const
- {
- Mutex::Lock _l(_upstreams_m);
- return _planet;
- }
-
- /**
- * @return Current planet's world ID
- */
- inline uint64_t planetWorldId() const
- {
- return _planet.id(); // safe to read without lock, and used from within eachPeer() so don't lock
- }
-
- /**
- * @return Current planet's world timestamp
- */
- inline uint64_t planetWorldTimestamp() const
- {
- return _planet.timestamp(); // safe to read without lock, and used from within eachPeer() so don't lock
- }
-
- /**
- * Validate new world and update if newer and signature is okay
- *
- * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
- * @param newWorld A new or updated planet or moon to learn
- * @param alwaysAcceptNew If true, always accept new moons even if we're not waiting for one
- * @return True if it was valid and newer than current (or totally new for moons)
- */
- bool addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew);
-
- /**
- * Add a moon
- *
- * This loads it from moons.d if present, and if not adds it to
- * a list of moons that we want to contact.
- *
- * @param id Moon ID
- * @param seed If non-NULL, an address of any member of the moon to contact
- */
- void addMoon(void *tPtr,const uint64_t id,const Address &seed);
-
- /**
- * Remove a moon
- *
- * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
- * @param id Moon's world ID
- */
- void removeMoon(void *tPtr,const uint64_t id);
-
/**
* Clean and flush database
*/
@@ -333,11 +225,6 @@ public:
return _peers.entries();
}
- /**
- * @return True if I am a root server in a planet or moon
- */
- inline bool amUpstream() const { return _amUpstream; }
-
/**
* Get info about a path
*
@@ -455,13 +342,6 @@ private:
Hashtable< Path::HashKey,SharedPtr > _paths;
Mutex _paths_m;
-
- World _planet;
- std::vector _moons;
- std::vector< std::pair > _moonSeeds;
- std::vector _upstreamAddresses;
- bool _amUpstream;
- Mutex _upstreams_m; // locks worlds, upstream info, moon info, etc.
};
} // namespace ZeroTier
diff --git a/node/Utils.hpp b/node/Utils.hpp
index 009866d48..c5fa8756a 100644
--- a/node/Utils.hpp
+++ b/node/Utils.hpp
@@ -453,7 +453,7 @@ public:
out[6] = BASE32CHARS[(in[3] & 0x03) << 3 | (in[4] & 0xe0) >> 5];
out[7] = BASE32CHARS[(in[4] & 0x1f)];
}
-
+
static inline void base328to5(const char *const in,uint8_t *const out)
{
out[0] = ((BASE32BITS[(unsigned int)in[0]]) << 3) | (BASE32BITS[(unsigned int)in[1]] & 0x1C) >> 2;
@@ -462,7 +462,7 @@ public:
out[3] = ((BASE32BITS[(unsigned int)in[4]] & 0x01) << 7) | (BASE32BITS[(unsigned int)in[5]]) << 2 | (BASE32BITS[(unsigned int)in[6]] & 0x18) >> 3;
out[4] = ((BASE32BITS[(unsigned int)in[6]] & 0x07) << 5) | (BASE32BITS[(unsigned int)in[7]]);
}
-
+
/**
* Hexadecimal characters 0-f
*/
diff --git a/node/World.hpp b/node/World.hpp
deleted file mode 100644
index 823d304d8..000000000
--- a/node/World.hpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * --
- *
- * You can be released from the requirements of the license by purchasing
- * a commercial license. Buying such a license is mandatory as soon as you
- * develop commercial closed-source software that incorporates or links
- * directly against ZeroTier software without disclosing the source code
- * of your own application.
- */
-
-#ifndef ZT_WORLD_HPP
-#define ZT_WORLD_HPP
-
-#include
-#include
-
-#include "Constants.hpp"
-#include "InetAddress.hpp"
-#include "Identity.hpp"
-#include "Buffer.hpp"
-#include "C25519.hpp"
-
-/**
- * Maximum number of roots (sanity limit, okay to increase)
- *
- * A given root can (through multi-homing) be distributed across any number of
- * physical endpoints, but having more than one is good to permit total failure
- * of one root or its withdrawal due to compromise without taking the whole net
- * down.
- */
-#define ZT_WORLD_MAX_ROOTS 4
-
-/**
- * Maximum number of stable endpoints per root (sanity limit, okay to increase)
- */
-#define ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT 32
-
-/**
- * The (more than) maximum length of a serialized World
- */
-#define ZT_WORLD_MAX_SERIALIZED_LENGTH (((1024 + (32 * ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT)) * ZT_WORLD_MAX_ROOTS) + ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_SIGNATURE_LEN + 128)
-
-/**
- * World ID for Earth
- *
- * This is the ID for the ZeroTier World used on planet Earth. It is unrelated
- * to the public network 8056c2e21c000001 of the same name. It was chosen
- * from Earth's approximate distance from the sun in kilometers.
- */
-#define ZT_WORLD_ID_EARTH 149604618
-
-/**
- * World ID for Mars -- for future use by SpaceX or others
- */
-#define ZT_WORLD_ID_MARS 227883110
-
-namespace ZeroTier {
-
-/**
- * A world definition (formerly known as a root topology)
- *
- * Think of a World as a single data center. Within this data center a set
- * of distributed fault tolerant root servers provide stable anchor points
- * for a peer to peer network that provides VLAN service. Updates to a world
- * definition can be published by signing them with the previous revision's
- * signing key, and should be very infrequent.
- *
- * The maximum data center size is approximately 2.5 cubic light seconds,
- * since many protocols have issues with >5s RTT latencies.
- *
- * ZeroTier operates a World for Earth capable of encompassing the planet, its
- * orbits, the Moon (about 1.3 light seconds), and nearby Lagrange points. A
- * world ID for Mars and nearby space is defined but not yet used, and a test
- * world ID is provided for testing purposes.
- */
-class World
-{
-public:
- /**
- * World type -- do not change IDs
- */
- enum Type
- {
- TYPE_NULL = 0,
- TYPE_PLANET = 1, // Planets, of which there is currently one (Earth)
- TYPE_MOON = 127 // Moons, which are user-created and many
- };
-
- /**
- * Upstream server definition in world/moon
- */
- struct Root
- {
- Identity identity;
- std::vector stableEndpoints;
-
- inline bool operator==(const Root &r) const { return ((identity == r.identity)&&(stableEndpoints == r.stableEndpoints)); }
- inline bool operator!=(const Root &r) const { return (!(*this == r)); }
- inline bool operator<(const Root &r) const { return (identity < r.identity); } // for sorting
- };
-
- /**
- * Construct an empty / null World
- */
- World() :
- _id(0),
- _ts(0),
- _type(TYPE_NULL) {}
-
- /**
- * @return Root servers for this world and their stable endpoints
- */
- inline const std::vector &roots() const { return _roots; }
-
- /**
- * @return World type: planet or moon
- */
- inline Type type() const { return _type; }
-
- /**
- * @return World unique identifier
- */
- inline uint64_t id() const { return _id; }
-
- /**
- * @return World definition timestamp
- */
- inline uint64_t timestamp() const { return _ts; }
-
- /**
- * @return C25519 signature
- */
- inline const C25519::Signature &signature() const { return _signature; }
-
- /**
- * @return Public key that must sign next update
- */
- inline const C25519::Public &updatesMustBeSignedBy() const { return _updatesMustBeSignedBy; }
-
- /**
- * Check whether a world update should replace this one
- *
- * @param update Candidate update
- * @return True if update is newer than current, matches its ID and type, and is properly signed (or if current is NULL)
- */
- inline bool shouldBeReplacedBy(const World &update)
- {
- if ((_id == 0)||(_type == TYPE_NULL))
- return true;
- if ((_id == update._id)&&(_ts < update._ts)&&(_type == update._type)) {
- Buffer tmp;
- update.serialize(tmp,true);
- return C25519::verify(_updatesMustBeSignedBy,tmp.data(),tmp.size(),update._signature);
- }
- return false;
- }
-
- /**
- * @return True if this World is non-empty
- */
- inline operator bool() const { return (_type != TYPE_NULL); }
-
- template
- inline void serialize(Buffer &b,bool forSign = false) const
- {
- if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
-
- b.append((uint8_t)_type);
- b.append((uint64_t)_id);
- b.append((uint64_t)_ts);
- b.append(_updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN);
- if (!forSign)
- b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
- b.append((uint8_t)_roots.size());
- for(std::vector::const_iterator r(_roots.begin());r!=_roots.end();++r) {
- r->identity.serialize(b);
- b.append((uint8_t)r->stableEndpoints.size());
- for(std::vector::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep)
- ep->serialize(b);
- }
- if (_type == TYPE_MOON)
- b.append((uint16_t)0); // no attached dictionary (for future use)
-
- if (forSign) b.append((uint64_t)0xf7f7f7f7f7f7f7f7ULL);
- }
-
- template
- inline unsigned int deserialize(const Buffer &b,unsigned int startAt = 0)
- {
- unsigned int p = startAt;
-
- _roots.clear();
-
- switch((Type)b[p++]) {
- case TYPE_NULL: _type = TYPE_NULL; break; // shouldn't ever really happen in serialized data but it's not invalid
- case TYPE_PLANET: _type = TYPE_PLANET; break;
- case TYPE_MOON: _type = TYPE_MOON; break;
- default:
- throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
- }
-
- _id = b.template at(p); p += 8;
- _ts = b.template at(p); p += 8;
- memcpy(_updatesMustBeSignedBy.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); p += ZT_C25519_PUBLIC_KEY_LEN;
- memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN;
- const unsigned int numRoots = (unsigned int)b[p++];
- if (numRoots > ZT_WORLD_MAX_ROOTS)
- throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
- for(unsigned int k=0;k ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT)
- throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
- for(unsigned int kk=0;kk(p) + 2;
-
- return (p - startAt);
- }
-
- inline bool operator==(const World &w) const { return ((_id == w._id)&&(_ts == w._ts)&&(memcmp(_updatesMustBeSignedBy.data,w._updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN) == 0)&&(memcmp(_signature.data,w._signature.data,ZT_C25519_SIGNATURE_LEN) == 0)&&(_roots == w._roots)&&(_type == w._type)); }
- inline bool operator!=(const World &w) const { return (!(*this == w)); }
-
- /**
- * Create a World object signed with a key pair
- *
- * @param t World type
- * @param id World ID
- * @param ts World timestamp / revision
- * @param sk Key that must be used to sign the next future update to this world
- * @param roots Roots and their stable endpoints
- * @param signWith Key to sign this World with (can have the same public as the next-update signing key, but doesn't have to)
- * @return Signed World object
- */
- static inline World make(World::Type t,uint64_t id,uint64_t ts,const C25519::Public &sk,const std::vector &roots,const C25519::Pair &signWith)
- {
- World w;
- w._id = id;
- w._ts = ts;
- w._type = t;
- w._updatesMustBeSignedBy = sk;
- w._roots = roots;
-
- Buffer tmp;
- w.serialize(tmp,true);
- w._signature = C25519::sign(signWith,tmp.data(),tmp.size());
-
- return w;
- }
-
-protected:
- uint64_t _id;
- uint64_t _ts;
- Type _type;
- C25519::Public _updatesMustBeSignedBy;
- C25519::Signature _signature;
- std::vector _roots;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/one.cpp b/one.cpp
index 89acaace5..5a148e7ed 100644
--- a/one.cpp
+++ b/one.cpp
@@ -79,7 +79,6 @@
#include "node/Utils.hpp"
#include "node/NetworkController.hpp"
#include "node/Buffer.hpp"
-#include "node/World.hpp"
#include "osdep/OSUtils.hpp"
#include "osdep/Http.hpp"
@@ -136,9 +135,6 @@ static void cliPrintHelp(const char *pn,FILE *out)
fprintf(out," leave - Leave a network" ZT_EOL_S);
fprintf(out," set - Set a network setting" ZT_EOL_S);
fprintf(out," get - Get a network setting" ZT_EOL_S);
- fprintf(out," listmoons - List moons (federated root sets)" ZT_EOL_S);
- fprintf(out," orbit - Join a moon via any member root" ZT_EOL_S);
- fprintf(out," deorbit - Leave a moon" ZT_EOL_S);
fprintf(out,ZT_EOL_S"Available settings:" ZT_EOL_S);
fprintf(out," Settings to use with [get/set] may include property names from " ZT_EOL_S);
fprintf(out," the JSON output of \"zerotier-cli -j listnetworks\". Additionally, " ZT_EOL_S);
@@ -593,80 +589,6 @@ static int cli(int argc,char **argv)
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
- } else if (command == "listmoons") {
- const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/moon",requestHeaders,responseHeaders,responseBody);
-
- if (scode == 0) {
- printf("Error connecting to the ZeroTier service: %s\n\nPlease check that the service is running and that TCP port 9993 can be contacted via 127.0.0.1." ZT_EOL_S, responseBody.c_str());
- return 1;
- }
-
- nlohmann::json j;
- try {
- j = OSUtils::jsonParse(responseBody);
- } catch (std::exception &exc) {
- printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what());
- return 1;
- } catch ( ... ) {
- printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str());
- return 1;
- }
-
- if (scode == 200) {
- printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str());
- return 0;
- } else {
- printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
- return 1;
- }
- } else if (command == "orbit") {
- const uint64_t worldId = Utils::hexStrToU64(arg1.c_str());
- const uint64_t seed = Utils::hexStrToU64(arg2.c_str());
- if ((worldId)&&(seed)) {
- char jsons[1024];
- OSUtils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str());
- char cl[128];
- OSUtils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons));
- requestHeaders["Content-Type"] = "application/json";
- requestHeaders["Content-Length"] = cl;
- unsigned int scode = Http::POST(
- 1024 * 1024 * 16,
- 60000,
- (const struct sockaddr *)&addr,
- (std::string("/moon/") + arg1).c_str(),
- requestHeaders,
- jsons,
- (unsigned long)strlen(jsons),
- responseHeaders,
- responseBody);
- if (scode == 200) {
- printf("200 orbit OK" ZT_EOL_S);
- return 0;
- } else {
- printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
- return 1;
- }
- }
- } else if (command == "deorbit") {
- unsigned int scode = Http::DEL(
- 1024 * 1024 * 16,
- 60000,
- (const struct sockaddr *)&addr,
- (std::string("/moon/") + arg1).c_str(),
- requestHeaders,
- responseHeaders,
- responseBody);
- if (scode == 200) {
- if (json) {
- printf("%s",cliFixJsonCRs(responseBody).c_str());
- } else {
- printf("200 deorbit OK" ZT_EOL_S);
- }
- return 0;
- } else {
- printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
- return 1;
- }
} else if (command == "set") {
if (arg1.length() != 16) {
fprintf(stderr,"invalid format: must be a 16-digit (network) ID\n");
@@ -829,8 +751,6 @@ static void idtoolPrintHelp(FILE *out,const char *pn)
fprintf(out," getpublic " ZT_EOL_S);
fprintf(out," sign " ZT_EOL_S);
fprintf(out," verify " ZT_EOL_S);
- fprintf(out," initmoon " ZT_EOL_S);
- fprintf(out," genmoon " ZT_EOL_S);
}
static Identity getIdFromArg(char *arg)
@@ -872,7 +792,7 @@ static int idtool(int argc,char **argv)
Identity id;
for(;;) {
- id.generate();
+ id.generate(Identity::C25519);
if ((id.address().toInt() >> (40 - vanityBits)) == vanity) {
if (vanityBits > 0) {
fprintf(stderr,"vanity address: found %.10llx !\n",(unsigned long long)id.address().toInt());
@@ -950,9 +870,10 @@ static int idtool(int argc,char **argv)
fprintf(stderr,"%s is not readable" ZT_EOL_S,argv[3]);
return 1;
}
- C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length());
- char hexbuf[1024];
- printf("%s",Utils::hex(signature.data,ZT_C25519_SIGNATURE_LEN,hexbuf));
+ uint8_t signature[ZT_SIGNATURE_BUFFER_SIZE];
+ const unsigned int siglen = id.sign(inf.data(),(unsigned int)inf.length(),signature,sizeof(signature));
+ char hexbuf[256];
+ printf("%s",Utils::hex(signature,siglen,hexbuf));
} else if (!strcmp(argv[1],"verify")) {
if (argc < 5) {
idtoolPrintHelp(stdout,argv[0]);
@@ -990,94 +911,6 @@ static int idtool(int argc,char **argv)
return 1;
}
}
- } else if (!strcmp(argv[1],"initmoon")) {
- if (argc < 3) {
- idtoolPrintHelp(stdout,argv[0]);
- } else {
- const Identity id = getIdFromArg(argv[2]);
- if (!id) {
- fprintf(stderr,"%s is not a valid identity" ZT_EOL_S,argv[2]);
- return 1;
- }
-
- C25519::Pair kp(C25519::generate());
-
- char idtmp[4096];
- nlohmann::json mj;
- mj["objtype"] = "world";
- mj["worldType"] = "moon";
- mj["updatesMustBeSignedBy"] = mj["signingKey"] = Utils::hex(kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN,idtmp);
- mj["signingKey_SECRET"] = Utils::hex(kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN,idtmp);
- mj["id"] = id.address().toString(idtmp);
- nlohmann::json seedj;
- seedj["identity"] = id.toString(false,idtmp);
- seedj["stableEndpoints"] = nlohmann::json::array();
- (mj["roots"] = nlohmann::json::array()).push_back(seedj);
- std::string mjd(OSUtils::jsonDump(mj));
-
- printf("%s" ZT_EOL_S,mjd.c_str());
- }
- } else if (!strcmp(argv[1],"genmoon")) {
- if (argc < 3) {
- idtoolPrintHelp(stdout,argv[0]);
- } else {
- std::string buf;
- if (!OSUtils::readFile(argv[2],buf)) {
- fprintf(stderr,"cannot read %s" ZT_EOL_S,argv[2]);
- return 1;
- }
- nlohmann::json mj(OSUtils::jsonParse(buf));
-
- const uint64_t id = Utils::hexStrToU64(OSUtils::jsonString(mj["id"],"0").c_str());
- if (!id) {
- fprintf(stderr,"ID in %s is invalid" ZT_EOL_S,argv[2]);
- return 1;
- }
-
- World::Type t;
- if (mj["worldType"] == "moon") {
- t = World::TYPE_MOON;
- } else if (mj["worldType"] == "planet") {
- t = World::TYPE_PLANET;
- } else {
- fprintf(stderr,"invalid worldType" ZT_EOL_S);
- return 1;
- }
-
- C25519::Pair signingKey;
- C25519::Public updatesMustBeSignedBy;
- Utils::unhex(OSUtils::jsonString(mj["signingKey"],"").c_str(),signingKey.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
- Utils::unhex(OSUtils::jsonString(mj["signingKey_SECRET"],"").c_str(),signingKey.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
- Utils::unhex(OSUtils::jsonString(mj["updatesMustBeSignedBy"],"").c_str(),updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN);
-
- std::vector roots;
- nlohmann::json &rootsj = mj["roots"];
- if (rootsj.is_array()) {
- for(unsigned long i=0;i<(unsigned long)rootsj.size();++i) {
- nlohmann::json &r = rootsj[i];
- if (r.is_object()) {
- roots.push_back(World::Root());
- roots.back().identity = Identity(OSUtils::jsonString(r["identity"],"").c_str());
- nlohmann::json &stableEndpointsj = r["stableEndpoints"];
- if (stableEndpointsj.is_array()) {
- for(unsigned long k=0;k<(unsigned long)stableEndpointsj.size();++k)
- roots.back().stableEndpoints.push_back(InetAddress(OSUtils::jsonString(stableEndpointsj[k],"").c_str()));
- std::sort(roots.back().stableEndpoints.begin(),roots.back().stableEndpoints.end());
- }
- }
- }
- }
- std::sort(roots.begin(),roots.end());
-
- const int64_t now = OSUtils::now();
- World w(World::make(t,id,now,updatesMustBeSignedBy,roots,signingKey));
- Buffer wbuf;
- w.serialize(wbuf);
- char fn[128];
- OSUtils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id());
- OSUtils::writeFile(fn,wbuf.data(),wbuf.size());
- printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S,fn,(unsigned long long)now);
- }
} else {
idtoolPrintHelp(stdout,argv[0]);
return 1;
diff --git a/selftest.cpp b/selftest.cpp
index 9ddd6953b..4e46ab8fd 100644
--- a/selftest.cpp
+++ b/selftest.cpp
@@ -367,8 +367,8 @@ static int testCrypto()
memcpy(p1.priv.data,C25519_TEST_VECTORS[k].priv1,ZT_C25519_PRIVATE_KEY_LEN);
memcpy(p2.pub.data,C25519_TEST_VECTORS[k].pub2,ZT_C25519_PUBLIC_KEY_LEN);
memcpy(p2.priv.data,C25519_TEST_VECTORS[k].priv2,ZT_C25519_PRIVATE_KEY_LEN);
- C25519::agree(p1,p2.pub,buf1,64);
- C25519::agree(p2,p1.pub,buf2,64);
+ C25519::agree(p1.priv,p2.pub,buf1,64);
+ C25519::agree(p2.priv,p1.pub,buf2,64);
if (memcmp(buf1,buf2,64)) {
std::cout << "FAIL (1)" << std::endl;
return -1;
@@ -398,9 +398,9 @@ static int testCrypto()
C25519::Pair p1 = C25519::generate();
C25519::Pair p2 = C25519::generate();
C25519::Pair p3 = C25519::generate();
- C25519::agree(p1,p2.pub,buf1,64);
- C25519::agree(p2,p1.pub,buf2,64);
- C25519::agree(p3,p1.pub,buf3,64);
+ C25519::agree(p1.priv,p2.pub,buf1,64);
+ C25519::agree(p2.priv,p1.pub,buf2,64);
+ C25519::agree(p3.priv,p1.pub,buf3,64);
// p1<>p2 should equal p1<>p2
if (memcmp(buf1,buf2,64)) {
std::cout << "FAIL (1)" << std::endl;
@@ -420,7 +420,7 @@ static int testCrypto()
bp[k] = C25519::generate();
uint64_t st = OSUtils::now();
for(unsigned int k=0;k<50;++k) {
- C25519::agree(bp[~k & 7],bp[k & 7].pub,buf1,64);
+ C25519::agree(bp[~k & 7].priv,bp[k & 7].pub,buf1,64);
}
uint64_t et = OSUtils::now();
std::cout << ((double)(et - st) / 50.0) << "ms per agreement." << std::endl;
@@ -508,7 +508,7 @@ static int testIdentity()
for(unsigned int k=0;k<4;++k) {
std::cout << "[identity] Generate identity... "; std::cout.flush();
uint64_t genstart = OSUtils::now();
- id.generate();
+ id.generate(Identity::C25519);
uint64_t genend = OSUtils::now();
std::cout << "(took " << (genend - genstart) << "ms): " << id.toString(true,buf2) << std::endl;
std::cout << "[identity] Locally validate identity: ";
@@ -581,13 +581,13 @@ static int testCertificate()
Identity authority;
std::cout << "[certificate] Generating identity to act as authority... "; std::cout.flush();
- authority.generate();
+ authority.generate(Identity::C25519);
std::cout << authority.address().toString(buf) << std::endl;
Identity idA,idB;
std::cout << "[certificate] Generating identities A and B... "; std::cout.flush();
- idA.generate();
- idB.generate();
+ idA.generate(Identity::C25519);
+ idB.generate(Identity::C25519);
std::cout << idA.address().toString(buf) << ", " << idB.address().toString(buf) << std::endl;
std::cout << "[certificate] Generating certificates A and B...";
diff --git a/service/OneService.cpp b/service/OneService.cpp
index 53b3e606f..9dfa8b0f5 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -48,7 +48,6 @@
#include "../node/InetAddress.hpp"
#include "../node/MAC.hpp"
#include "../node/Identity.hpp"
-#include "../node/World.hpp"
#include "../node/Salsa20.hpp"
#include "../node/Poly1305.hpp"
#include "../node/SHA512.hpp"
@@ -346,28 +345,6 @@ static void _peerAggregateLinkToJson(nlohmann::json &pj,const ZT_Peer *peer)
pj["paths"] = pa;
}
-static void _moonToJson(nlohmann::json &mj,const World &world)
-{
- char tmp[4096];
- OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id());
- mj["id"] = tmp;
- mj["timestamp"] = world.timestamp();
- mj["signature"] = Utils::hex(world.signature().data,ZT_C25519_SIGNATURE_LEN,tmp);
- mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data,ZT_C25519_PUBLIC_KEY_LEN,tmp);
- nlohmann::json ra = nlohmann::json::array();
- for(std::vector::const_iterator r(world.roots().begin());r!=world.roots().end();++r) {
- nlohmann::json rj;
- rj["identity"] = r->identity.toString(false,tmp);
- nlohmann::json eps = nlohmann::json::array();
- for(std::vector::const_iterator a(r->stableEndpoints.begin());a!=r->stableEndpoints.end();++a)
- eps.push_back(a->toString(tmp));
- rj["stableEndpoints"] = eps;
- ra.push_back(rj);
- }
- mj["roots"] = ra;
- mj["waiting"] = false;
-}
-
class OneServiceImpl;
static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf);
@@ -780,16 +757,6 @@ public:
}
}
- // Orbit existing moons in moons.d
- {
- std::vector moonsDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "moons.d").c_str()));
- for(std::vector::iterator f(moonsDotD.begin());f!=moonsDotD.end();++f) {
- std::size_t dot = f->find_last_of('.');
- if ((dot == 16)&&(f->substr(16) == ".moon"))
- _node->orbit((void *)0,Utils::hexStrToU64(f->substr(0,dot).c_str()),0);
- }
- }
-
// Main I/O loop
_nextBackgroundTaskDeadline = 0;
int64_t clockShouldBe = OSUtils::now();
@@ -1287,37 +1254,8 @@ public:
settings["softwareUpdate"] = OSUtils::jsonString(settings["softwareUpdate"],ZT_SOFTWARE_UPDATE_DEFAULT);
settings["softwareUpdateChannel"] = OSUtils::jsonString(settings["softwareUpdateChannel"],ZT_SOFTWARE_UPDATE_DEFAULT_CHANNEL);
#endif
- const World planet(_node->planet());
- res["planetWorldId"] = planet.id();
- res["planetWorldTimestamp"] = planet.timestamp();
scode = 200;
- } else if (ps[0] == "moon") {
- std::vector moons(_node->moons());
- if (ps.size() == 1) {
- // Return [array] of all moons
-
- res = json::array();
- for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) {
- json mj;
- _moonToJson(mj,*m);
- res.push_back(mj);
- }
-
- scode = 200;
- } else {
- // Return a single moon by ID
-
- const uint64_t id = Utils::hexStrToU64(ps[1].c_str());
- for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) {
- if (m->id() == id) {
- _moonToJson(res,*m);
- scode = 200;
- break;
- }
- }
-
- }
} else if (ps[0] == "network") {
ZT_VirtualNetworkList *nws = _node->networks();
if (nws) {
@@ -1390,44 +1328,7 @@ public:
} else if ((httpMethod == HTTP_POST)||(httpMethod == HTTP_PUT)) {
if (isAuth) {
- if (ps[0] == "moon") {
- if (ps.size() == 2) {
-
- uint64_t seed = 0;
- try {
- json j(OSUtils::jsonParse(body));
- if (j.is_object()) {
- seed = Utils::hexStrToU64(OSUtils::jsonString(j["seed"],"0").c_str());
- }
- } catch ( ... ) {
- // discard invalid JSON
- }
-
- std::vector moons(_node->moons());
- const uint64_t id = Utils::hexStrToU64(ps[1].c_str());
- for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) {
- if (m->id() == id) {
- _moonToJson(res,*m);
- scode = 200;
- break;
- }
- }
-
- if ((scode != 200)&&(seed != 0)) {
- char tmp[64];
- OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id);
- res["id"] = tmp;
- res["roots"] = json::array();
- res["timestamp"] = 0;
- res["signature"] = json();
- res["updatesMustBeSignedBy"] = json();
- res["waiting"] = true;
- _node->orbit((void *)0,id,seed);
- scode = 200;
- }
-
- } else scode = 404;
- } else if (ps[0] == "network") {
+ if (ps[0] == "network") {
if (ps.size() == 2) {
uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
@@ -1474,13 +1375,7 @@ public:
} else if (httpMethod == HTTP_DELETE) {
if (isAuth) {
- if (ps[0] == "moon") {
- if (ps.size() == 2) {
- _node->deorbit((void *)0,Utils::hexStrToU64(ps[1].c_str()));
- res["result"] = true;
- scode = 200;
- } // else 404
- } else if (ps[0] == "network") {
+ if (ps[0] == "network") {
ZT_VirtualNetworkList *nws = _node->networks();
if (nws) {
if (ps.size() == 2) {
@@ -2370,13 +2265,6 @@ public:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
secure = true;
break;
- case ZT_STATE_OBJECT_PLANET:
- OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
- break;
- case ZT_STATE_OBJECT_MOON:
- OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "moons.d",_homePath.c_str());
- OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.moon",dirname,(unsigned long long)id[0]);
- break;
case ZT_STATE_OBJECT_NETWORK_CONFIG:
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "networks.d",_homePath.c_str());
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.conf",dirname,(unsigned long long)id[0]);
@@ -2522,12 +2410,6 @@ public:
case ZT_STATE_OBJECT_IDENTITY_SECRET:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
break;
- case ZT_STATE_OBJECT_PLANET:
- OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
- break;
- case ZT_STATE_OBJECT_MOON:
- OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]);
- break;
case ZT_STATE_OBJECT_NETWORK_CONFIG:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]);
break;