2
0
Эх сурвалжийг харах

TON of refactoring, moon/planet is DEAD, ECC P-384 is integrated (but not enabled), and multicast work and cleanup. Whew.

Adam Ierymenko 6 жил өмнө
parent
commit
fe2215df00

+ 0 - 162
attic/MTUDPSocket.hpp

@@ -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 <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * 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 <vector>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-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;t<ncores;t++) {
-			int s = socket(bindAddr->sa_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<int> _sockets;
-};
-
-} // namespace ZeroTier
-
-#endif // !__WINDOWS__
-
-#endif

+ 0 - 7
attic/world/README.md

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

+ 0 - 3
attic/world/build.sh

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

+ 0 - 154
attic/world/mkworld.cpp

@@ -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 <http://www.gnu.org/licenses/>.
- */
-
-/*
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-#include <algorithm>
-
-#include <node/Constants.hpp>
-#include <node/World.hpp>
-#include <node/C25519.hpp>
-#include <node/Identity.hpp>
-#include <node/InetAddress.hpp>
-#include <osdep/OSUtils.hpp>
-
-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<World::Root> 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<ZT_WORLD_MAX_SERIALIZED_LENGTH> 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<outtmp.size();++i) {
-		const unsigned char *d = (const unsigned char *)outtmp.data();
-		if (i > 0)
-			fprintf(stdout,",");
-		fprintf(stdout,"0x%.2x",(unsigned int)d[i]);
-	}
-	fprintf(stdout,"};" ZT_EOL_S);
-
-	return 0;
-}

BIN
attic/world/world.bin


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 2
attic/world/world.c


+ 0 - 44
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: <HOME>/planet
-	 * Persistence: recommended
-	 */
-	ZT_STATE_OBJECT_PLANET = 3,
-
-	/**
-	 * A moon (federated root set)
-	 *
-	 * Object ID: world ID of moon
-	 * Canonical path: <HOME>/moons.d/<ID>.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
  *

+ 0 - 2
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

+ 18 - 1
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<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH));++i) {
+			if (!(_custody[i].to)) {
+				Buffer<(sizeof(Capability) * 2)> tmp;
+				this->serialize(tmp,true);
+				_custody[i].to = to;
+				_custody[i].from = from.address();
+				_custody[i].signatureLength = from.sign(tmp.data(),tmp.size(),_custody[i].signature,sizeof(_custody[i].signature));
+				return true;
+			}
+		}
+	} catch ( ... ) {}
+	return false;
+}
+
 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);

+ 9 - 22
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<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH));++i) {
-				if (!(_custody[i].to)) {
-					Buffer<(sizeof(Capability) * 2)> tmp;
-					this->serialize(tmp,true);
-					_custody[i].to = to;
-					_custody[i].from = from.address();
-					_custody[i].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<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN)
+				_custody[i].signatureLength = b.template at<uint16_t>(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<uint16_t>(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];
 };
 

+ 6 - 7
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

+ 21 - 9
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<unsigned int C>
@@ -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

+ 27 - 1
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<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
+		++_thingCount;
+	} else if (ip.ss_family == AF_INET6) {
+		_thingTypes[_thingCount] = THING_IPV6_ADDRESS;
+		memcpy(_thingValues[_thingCount],reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
+		++_thingCount;
+	}
+}
+
+bool CertificateOfOwnership::sign(const Identity &signer)
+{
+	if (signer.hasPrivate()) {
+		Buffer<sizeof(CertificateOfOwnership) + 64> 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;
 	}

+ 10 - 30
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<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
-			++_thingCount;
-		} else if (ip.ss_family == AF_INET6) {
-			_thingTypes[_thingCount] = THING_IPV6_ADDRESS;
-			memcpy(_thingValues[_thingCount],reinterpret_cast<const struct sockaddr_in6 *>(&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<sizeof(CertificateOfOwnership) + 64> 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<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN)
+			_signatureLength = b.template at<uint16_t>(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<uint16_t>(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

+ 5 - 0
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)
  */

+ 34 - 0
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

+ 129 - 55
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;
-
-	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]));
+	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;
+
+		case P384: {
+			return true;
+		}	break;
+	}
+
+	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:

+ 191 - 100
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<void *>(this),0,sizeof(Identity)); }
+	Identity(const Identity &id) { memcpy(reinterpret_cast<void *>(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<unsigned int C>
-	Identity(const Buffer<C> &b,unsigned int startAt = 0) :
-		_privateKey((C25519::Private *)0)
-	{
-		deserialize(b,startAt);
-	}
+	Identity(const Buffer<C> &b,unsigned int startAt = 0) { deserialize(b,startAt); }
 
-	~Identity()
-	{
-		if (_privateKey) {
-			Utils::burn(_privateKey,sizeof(C25519::Private));
-			delete _privateKey;
-		}
-	}
+	~Identity() { Utils::burn(reinterpret_cast<void *>(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<void *>(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<klen;++i) {
+						if (hi == 64) {
+							hi = 0;
+							SHA512::hash(h,h,64);
+						}
+						((uint8_t *)key)[i] = h[hi++];
+					}
+					return true;
+			}
 		}
 		return false;
 	}
@@ -206,12 +237,28 @@ public:
 	inline void serialize(Buffer<C> &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<unsigned int C>
 	inline unsigned int deserialize(const Buffer<C> &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

+ 7 - 65
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<uint64_t>(ptr); ptr += 8;
-		planetWorldTimestamp = at<uint64_t>(ptr); ptr += 8;
-	}
-
-	std::vector< std::pair<uint64_t,uint64_t> > 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<uint16_t>(ptr); ptr += 2;
-			for(unsigned int i=0;i<numMoons;++i) {
-				if ((World::Type)(*this)[ptr++] == World::TYPE_MOON)
-					moonIdsAndTimestamps.push_back(std::pair<uint64_t,uint64_t>(at<uint64_t>(ptr),at<uint64_t>(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<World> moons(RR->topology->moons());
-		for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) {
-			for(std::vector< std::pair<uint64_t,uint64_t> >::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<uint16_t>(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<uint16_t>(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> &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> 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<uint32_t>(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());

+ 22 - 71
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<InetAddress> > &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<InetAddress> *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<InetAddress> > &_alwaysContact;
 	const int64_t _now;
 	const SharedPtr<Peer> _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<InetAddress> > 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<InetAddress> >::Iterator i(alwaysContact);
-				Address *upstreamAddress = (Address *)0;
-				std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
-				while (i.next(upstreamAddress,upstreamStableEndpoints)) {
-					SharedPtr<Peer> 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<InetAddress> > alwaysContact;
+			RR->topology->getUpstreamsToContact(alwaysContact);
 			std::vector< std::pair< SharedPtr<Network>,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<World> 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<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart));
+					uint8_t sig[256];
+					const unsigned int siglen = RR->identity.sign(reinterpret_cast<const uint8_t *>(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<ZeroTier::Node *>(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<ZeroTier::Node *>(node)->deorbit(tptr,moonWorldId);
-	} catch ( ... ) {
-		return ZT_RESULT_FATAL_ERROR_INTERNAL;
-	}
-}
-
 uint64_t ZT_Node_address(ZT_Node *node)
 {
 	return reinterpret_cast<ZeroTier::Node *>(node)->address();

+ 0 - 7
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<World> moons() const;
-
 	inline const Identity &identity() const { return _RR.identity; }
 
 	/**

+ 0 - 10
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<uint8_t *>(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<char *>(unsafeData());

+ 3 - 35
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)
 	 *

+ 0 - 21
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<World> moons(RR->topology->moons());
-	std::vector<uint64_t> moonsWanted(RR->topology->moonsWanted());
-	outp.append((uint16_t)(moons.size() + moonsWanted.size()));
-	for(std::vector<World>::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<uint64_t>::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) {

+ 13 - 1
node/Revocation.cpp

@@ -34,6 +34,18 @@
 
 namespace ZeroTier {
 
+bool Revocation::sign(const Identity &signer)
+{
+	if (signer.hasPrivate()) {
+		Buffer<sizeof(Revocation) + 64> 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<sizeof(Revocation) + 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;
 	}

+ 14 - 24
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<sizeof(Revocation) + 64> 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<uint16_t>(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<uint16_t>(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<uint16_t>(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

+ 0 - 7
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<Peer> relayTo = RR->topology->getPeer(tPtr,destination);

+ 13 - 1
node/Tag.cpp

@@ -34,6 +34,18 @@
 
 namespace ZeroTier {
 
+bool Tag::sign(const Identity &signer)
+{
+	if (signer.hasPrivate()) {
+		Buffer<sizeof(Tag) + 64> 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;
 	}

+ 13 - 21
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<sizeof(Tag) + 64> 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<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN)
+			_signatureLength = b.template at<uint16_t>(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<uint16_t>(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

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 26
node/Topology.cpp


+ 1 - 121
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<InetAddress> > &eps) const
 	{
-		Mutex::Lock _l(_upstreams_m);
-		for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
-			if (i->identity != RR->identity) {
-				std::vector<InetAddress> &ips = eps[i->identity.address()];
-				for(std::vector<InetAddress>::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<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) {
-			for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) {
-				if (i->identity != RR->identity) {
-					std::vector<InetAddress> &ips = eps[i->identity.address()];
-					for(std::vector<InetAddress>::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<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m)
-			eps[m->second];
 	}
 
 	/**
@@ -201,87 +171,9 @@ public:
 	 */
 	inline std::vector<Address> upstreamAddresses() const
 	{
-		Mutex::Lock _l(_upstreams_m);
-		return _upstreamAddresses;
-	}
-
-	/**
-	 * @return Current moons
-	 */
-	inline std::vector<World> moons() const
-	{
-		Mutex::Lock _l(_upstreams_m);
-		return _moons;
-	}
-
-	/**
-	 * @return Moon IDs we are waiting for from seeds
-	 */
-	inline std::vector<uint64_t> moonsWanted() const
-	{
-		Mutex::Lock _l(_upstreams_m);
-		std::vector<uint64_t> mw;
-		for(std::vector< std::pair<uint64_t,Address> >::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
+		return std::vector<Address>();
 	}
 
-	/**
-	 * 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<Path> > _paths;
 	Mutex _paths_m;
-
-	World _planet;
-	std::vector<World> _moons;
-	std::vector< std::pair<uint64_t,Address> > _moonSeeds;
-	std::vector<Address> _upstreamAddresses;
-	bool _amUpstream;
-	Mutex _upstreams_m; // locks worlds, upstream info, moon info, etc.
 };
 
 } // namespace ZeroTier

+ 2 - 2
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
 	 */

+ 0 - 284
node/World.hpp

@@ -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 <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * 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 <vector>
-#include <string>
-
-#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<InetAddress> 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<World::Root> &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<ZT_WORLD_MAX_SERIALIZED_LENGTH> 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<unsigned int C>
-	inline void serialize(Buffer<C> &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<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
-			r->identity.serialize(b);
-			b.append((uint8_t)r->stableEndpoints.size());
-			for(std::vector<InetAddress>::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<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &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<uint64_t>(p); p += 8;
-		_ts = b.template at<uint64_t>(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<numRoots;++k) {
-			_roots.push_back(Root());
-			Root &r = _roots.back();
-			p += r.identity.deserialize(b,p);
-			unsigned int numStableEndpoints = b[p++];
-			if (numStableEndpoints > ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT)
-				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
-			for(unsigned int kk=0;kk<numStableEndpoints;++kk) {
-				r.stableEndpoints.push_back(InetAddress());
-				p += r.stableEndpoints.back().deserialize(b,p);
-			}
-		}
-		if (_type == TYPE_MOON)
-			p += b.template at<uint16_t>(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<World::Root> &roots,const C25519::Pair &signWith)
-	{
-		World w;
-		w._id = id;
-		w._ts = ts;
-		w._type = t;
-		w._updatesMustBeSignedBy = sk;
-		w._roots = roots;
-
-		Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> 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<Root> _roots;
-};
-
-} // namespace ZeroTier
-
-#endif

+ 5 - 172
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 <network>         - Leave a network" ZT_EOL_S);
 	fprintf(out,"  set <network> <setting> - Set a network setting" ZT_EOL_S);
 	fprintf(out,"  get <network> <setting> - Get a network setting" ZT_EOL_S);
-	fprintf(out,"  listmoons               - List moons (federated root sets)" ZT_EOL_S);
-	fprintf(out,"  orbit <world ID> <seed> - Join a moon via any member root" ZT_EOL_S);
-	fprintf(out,"  deorbit <world ID>      - 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 <identity.secret>" ZT_EOL_S);
 	fprintf(out,"  sign <identity.secret> <file>" ZT_EOL_S);
 	fprintf(out,"  verify <identity.secret/public> <file> <signature>" ZT_EOL_S);
-	fprintf(out,"  initmoon <identity.public of first seed>" ZT_EOL_S);
-	fprintf(out,"  genmoon <moon json>" 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<World::Root> 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<ZT_WORLD_MAX_SERIALIZED_LENGTH> 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;

+ 10 - 10
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...";

+ 2 - 120
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<World::Root>::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<InetAddress>::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<std::string> moonsDotD(OSUtils::listDirectory((_homePath + ZT_PATH_SEPARATOR_S "moons.d").c_str()));
-				for(std::vector<std::string>::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<World> moons(_node->moons());
-					if (ps.size() == 1) {
-						// Return [array] of all moons
-
-						res = json::array();
-						for(std::vector<World>::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<World>::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<World> moons(_node->moons());
-						const uint64_t id = Utils::hexStrToU64(ps[1].c_str());
-						for(std::vector<World>::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;

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно