mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-02-20 17:52:46 +00:00
New crypto integrated -- going to be testing new identity address generation algo a bit more before finalizing.
This commit is contained in:
parent
ceb024ab03
commit
e376c6f6a9
@ -13,7 +13,7 @@ STRIP=strip
|
||||
#STRIP=echo
|
||||
|
||||
CXXFLAGS=$(CFLAGS) -fno-rtti
|
||||
LIBS=-lcrypto -lm
|
||||
LIBS=-lm
|
||||
|
||||
include objects.mk
|
||||
|
||||
|
34
main.cpp
34
main.cpp
@ -49,8 +49,6 @@
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "node/Constants.hpp"
|
||||
#include "node/Defaults.hpp"
|
||||
#include "node/Utils.hpp"
|
||||
@ -58,36 +56,6 @@
|
||||
|
||||
using namespace ZeroTier;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Override libcrypto default RAND_ with Utils::getSecureRandom(), which uses
|
||||
// a system strong random source. This is because OpenSSL libcrypto's default
|
||||
// RAND_ implementation uses uninitialized memory as one of its entropy
|
||||
// sources, which plays havoc with all kinds of debuggers and auditing tools.
|
||||
|
||||
static void _zeroTier_rand_cleanup() {}
|
||||
static void _zeroTier_rand_add(const void *buf, int num, double add_entropy) {}
|
||||
static int _zeroTier_rand_status() { return 1; }
|
||||
static void _zeroTier_rand_seed(const void *buf, int num) {}
|
||||
static int _zeroTier_rand_bytes(unsigned char *buf, int num)
|
||||
{
|
||||
Utils::getSecureRandom(buf,num);
|
||||
return 1;
|
||||
}
|
||||
static RAND_METHOD _zeroTierRandMethod = {
|
||||
_zeroTier_rand_seed,
|
||||
_zeroTier_rand_bytes,
|
||||
_zeroTier_rand_cleanup,
|
||||
_zeroTier_rand_add,
|
||||
_zeroTier_rand_bytes,
|
||||
_zeroTier_rand_status
|
||||
};
|
||||
static void _initLibCrypto()
|
||||
{
|
||||
RAND_set_rand_method(&_zeroTierRandMethod);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static Node *node = (Node *)0;
|
||||
|
||||
static void printHelp(const char *cn,FILE *out)
|
||||
@ -145,8 +113,6 @@ int main(int argc,char **argv)
|
||||
SetConsoleCtrlHandler(&_handlerRoutine,TRUE);
|
||||
#endif
|
||||
|
||||
_initLibCrypto();
|
||||
|
||||
const char *homeDir = (const char *)0;
|
||||
for(int i=1;i<argc;++i) {
|
||||
if (argv[i][0] == '-') {
|
||||
|
@ -52,6 +52,7 @@ static inline std::map< Identity,std::vector<InetAddress> > _mkSupernodeMap()
|
||||
// Nothing special about a supernode... except that they are
|
||||
// designated as such.
|
||||
|
||||
#if 0
|
||||
// cthulhu.zerotier.com - New York, New York, USA
|
||||
addrs.clear();
|
||||
if (!id.fromString("271ee006a0:1:AgGXs3I+9CWrEmGMxc50x3E+trwtaa2ZMXDU6ezz92fFJXzlhRKGUY/uAToHDdH9XiLxtcA+kUQAZdC4Dy2xtqXxjw==:QgH5Nlx4oWEGVrwhNocqem+3VNd4qzt7RLrmuvqZvKPRS9R70LJYJQLlKZj0ri55Pzg+Mlwy4a4nAgfnRAWA+TW6R0EjSmq72MG585XGNfWBVk3LxMvxlNWErnVNFr2BQS9yzVp4pRjPLdCW4RB3dwEHBUgJ78rwMxQ6IghVCl8CjkDapg=="))
|
||||
@ -72,6 +73,7 @@ static inline std::map< Identity,std::vector<InetAddress> > _mkSupernodeMap()
|
||||
throw std::runtime_error("invalid identity in Defaults");
|
||||
addrs.push_back(InetAddress("198.211.127.172",ZT_DEFAULT_UDP_PORT));
|
||||
sn[id] = addrs;
|
||||
#endif
|
||||
|
||||
return sn;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Identity.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@ -76,7 +77,7 @@ std::string Identity::toString(bool includePrivate) const
|
||||
r.append(Utils::hex(_signature.data,_signature.size()));
|
||||
if ((_privateKey)&&(includePrivate)) {
|
||||
r.push_back(':');
|
||||
r.append(Utils::hex(_privateKey.data,_privateKey.size()));
|
||||
r.append(Utils::hex(_privateKey->data,_privateKey->size()));
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -129,8 +130,8 @@ bool Identity::fromString(const char *str)
|
||||
|
||||
// These are fixed parameters and can't be changed without a new
|
||||
// identity type.
|
||||
#define ZT_IDENTITY_DERIVEADDRESS_DIGESTS 540672
|
||||
#define ZT_IDENTITY_DERIVEADDRESS_ROUNDS 4
|
||||
#define ZT_IDENTITY_DERIVEADDRESS_DIGESTS 2048
|
||||
#define ZT_IDENTITY_DERIVEADDRESS_ROUNDS 8
|
||||
|
||||
Address Identity::deriveAddress(const void *keyBytes,unsigned int keyLen)
|
||||
{
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include "C25519.hpp"
|
||||
#include "Buffer.hpp"
|
||||
|
||||
#define ZT_IDENTITY_MAX_BINARY_SERIALIZED_LENGTH (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + ZT_C25519_SIGNATURE_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
@ -148,6 +150,36 @@ public:
|
||||
*/
|
||||
inline bool hasPrivate() const throw() { return (_privateKey != (C25519::Private *)0); }
|
||||
|
||||
/**
|
||||
* Sign a message with this identity (private key required)
|
||||
*
|
||||
* @param data Data to sign
|
||||
* @param len Length of data
|
||||
*/
|
||||
inline C25519::Signature sign(const void *data,unsigned int len) const
|
||||
throw(std::runtime_error)
|
||||
{
|
||||
if (_privateKey)
|
||||
return C25519::sign(*_privateKey,_publicKey,data,len);
|
||||
throw std::runtime_error("sign() requires a private key");
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a message signature against this identity
|
||||
*
|
||||
* @param data Data to check
|
||||
* @param len Length of data
|
||||
* @param signature Signature bytes
|
||||
* @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
|
||||
{
|
||||
if (siglen != ZT_C25519_SIGNATURE_LEN)
|
||||
return false;
|
||||
return C25519::verify(_publicKey,data,len,signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method to perform key agreement with another identity
|
||||
*
|
||||
@ -193,8 +225,8 @@ public:
|
||||
b.append(_publicKey.data,_publicKey.size());
|
||||
b.append(_signature.data,_signature.size());
|
||||
if ((_privateKey)&&(includePrivate)) {
|
||||
b.append((unsigned char)_privateKey.size());
|
||||
b.append(_privateKey.data,_privateKey.size());
|
||||
b.append((unsigned char)_privateKey->size());
|
||||
b.append(_privateKey->data,_privateKey->size());
|
||||
} else b.append((unsigned char)0);
|
||||
}
|
||||
|
||||
@ -225,15 +257,15 @@ public:
|
||||
if (b[p++] != IDENTITY_TYPE_C25519)
|
||||
throw std::invalid_argument("Identity: deserialize(): unsupported identity type");
|
||||
|
||||
memcpy(_publicKey.data,field(p,_publicKey.size()),_publicKey.size());
|
||||
memcpy(_publicKey.data,b.field(p,_publicKey.size()),_publicKey.size());
|
||||
p += _publicKey.size();
|
||||
memcpy(_signature.data,field(p,_signature.size()),_signature.size());
|
||||
memcpy(_signature.data,b.field(p,_signature.size()),_signature.size());
|
||||
p += _signature.size();
|
||||
|
||||
unsigned int privateKeyLength = b[p++];
|
||||
if ((privateKeyLength)&&(privateKeyLength == ZT_C25519_PRIVATE_KEY_LEN)) {
|
||||
_privateKey = new C25519::Private();
|
||||
memcpy(_privateKey->data,field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
|
||||
memcpy(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
|
||||
p += ZT_C25519_PRIVATE_KEY_LEN;
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,9 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@ -51,6 +50,7 @@
|
||||
#include "BloomFilter.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "CMWC4096.hpp"
|
||||
#include "C25519.hpp"
|
||||
|
||||
// Maximum sample size to pick during choice of multicast propagation peers
|
||||
#define ZT_MULTICAST_PICK_MAX_SAMPLE_SIZE (ZT_MULTICAST_PROPAGATION_BREADTH * 8)
|
||||
@ -92,13 +92,20 @@ public:
|
||||
* @param etherType 16-bit ethernet type
|
||||
* @param data Ethernet frame data
|
||||
* @param len Length of frame
|
||||
* @return ECDSA signature
|
||||
* @return Signature of packet data and attributes
|
||||
* @throws std::runtime_error Cannot sign, e.g. identity has no private key
|
||||
*/
|
||||
static inline std::string signMulticastPacket(const Identity &id,uint64_t nwid,const MAC &from,const MulticastGroup &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
static inline C25519::Signature signMulticastPacket(const Identity &id,uint64_t nwid,const MAC &from,const MulticastGroup &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
throw(std::runtime_error)
|
||||
{
|
||||
unsigned char digest[32];
|
||||
_hashMulticastPacketForSig(nwid,from,to,etherType,data,len,digest);
|
||||
return id.sign(digest);
|
||||
char tmp[65536];
|
||||
*((uint64_t *)tmp) = Utils::hton(nwid);
|
||||
memcpy(tmp + 8,from.data,6);
|
||||
memcpy(tmp + 14,to.mac().data,6);
|
||||
*((uint32_t *)(tmp + 20)) = Utils::hton(to.adi());
|
||||
*((uint16_t *)(tmp + 24)) = Utils::hton((uint16_t)etherType);
|
||||
memcpy(tmp + 26,data,std::min((unsigned int)(sizeof(tmp) - 26),len)); // min() is a sanity check here, no packet is that big
|
||||
return id.sign(tmp,len + 26);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,15 +118,20 @@ public:
|
||||
* @param etherType 16-bit ethernet type
|
||||
* @param data Ethernet frame data
|
||||
* @param len Length of frame
|
||||
* @param signature ECDSA signature
|
||||
* @param signature Signature
|
||||
* @param siglen Length of signature in bytes
|
||||
* @return ECDSA signature
|
||||
* @return True if signature verification was successful
|
||||
*/
|
||||
static bool verifyMulticastPacket(const Identity &id,uint64_t nwid,const MAC &from,const MulticastGroup &to,unsigned int etherType,const void *data,unsigned int len,const void *signature,unsigned int siglen)
|
||||
{
|
||||
unsigned char digest[32];
|
||||
_hashMulticastPacketForSig(nwid,from,to,etherType,data,len,digest);
|
||||
return id.verifySignature(digest,signature,siglen);
|
||||
char tmp[65536];
|
||||
*((uint64_t *)tmp) = Utils::hton(nwid);
|
||||
memcpy(tmp + 8,from.data,6);
|
||||
memcpy(tmp + 14,to.mac().data,6);
|
||||
*((uint32_t *)(tmp + 20)) = Utils::hton(to.adi());
|
||||
*((uint16_t *)(tmp + 24)) = Utils::hton((uint16_t)etherType);
|
||||
memcpy(tmp + 26,data,std::min((unsigned int)(sizeof(tmp) - 26),len)); // min() is a sanity check here, no packet is that big
|
||||
return id.verify(tmp,len + 26,signature,siglen);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -349,29 +361,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
static inline void _hashMulticastPacketForSig(uint64_t nwid,const MAC &from,const MulticastGroup &to,unsigned int etherType,const void *data,unsigned int len,unsigned char *digest)
|
||||
throw()
|
||||
{
|
||||
unsigned char zero = 0;
|
||||
SHA256_CTX sha;
|
||||
SHA256_Init(&sha);
|
||||
uint64_t _nwid = Utils::hton(nwid);
|
||||
SHA256_Update(&sha,(unsigned char *)&_nwid,sizeof(_nwid));
|
||||
SHA256_Update(&sha,&zero,1);
|
||||
SHA256_Update(&sha,(unsigned char *)from.data,6);
|
||||
SHA256_Update(&sha,&zero,1);
|
||||
SHA256_Update(&sha,(unsigned char *)to.mac().data,6);
|
||||
SHA256_Update(&sha,&zero,1);
|
||||
uint32_t _adi = Utils::hton(to.adi());
|
||||
SHA256_Update(&sha,(unsigned char *)&_adi,sizeof(_adi));
|
||||
SHA256_Update(&sha,&zero,1);
|
||||
uint16_t _etype = Utils::hton((uint16_t)etherType);
|
||||
SHA256_Update(&sha,(unsigned char *)&_etype,sizeof(_etype));
|
||||
SHA256_Update(&sha,&zero,1);
|
||||
SHA256_Update(&sha,(unsigned char *)data,len);
|
||||
SHA256_Final(digest,&sha);
|
||||
}
|
||||
|
||||
// ring buffer: [0] - CRC, [1] - timestamp
|
||||
uint64_t _multicastHistory[ZT_MULTICAST_DEDUP_HISTORY_LENGTH][2];
|
||||
volatile unsigned int _multicastHistoryPtr;
|
||||
|
@ -30,8 +30,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "RuntimeEnvironment.hpp"
|
||||
#include "NodeConfig.hpp"
|
||||
#include "Network.hpp"
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "Mutex.hpp"
|
||||
#include "Multicaster.hpp"
|
||||
#include "CMWC4096.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Service.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
@ -128,10 +129,11 @@ Node::LocalClient::LocalClient(const char *authToken,void (*resultHandler)(void
|
||||
|
||||
// If socket fails to bind, there's a big problem like missing IPv4 stack
|
||||
if (sock) {
|
||||
SHA256_CTX sha;
|
||||
SHA256_Init(&sha);
|
||||
SHA256_Update(&sha,authToken,strlen(authToken));
|
||||
SHA256_Final(impl->key,&sha);
|
||||
{
|
||||
unsigned int csk[64];
|
||||
SHA512::hash(csk,authToken,strlen(authToken));
|
||||
memcpy(impl->key,csk,32);
|
||||
}
|
||||
|
||||
impl->sock = sock;
|
||||
impl->resultHandler = resultHandler;
|
||||
|
@ -69,7 +69,7 @@ NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken)
|
||||
{
|
||||
{
|
||||
unsigned int csk[64];
|
||||
SHA512::hash(authToken,strlen(authToken));
|
||||
SHA512::hash(csk,authToken,strlen(authToken));
|
||||
memcpy(_controlSocketKey,csk,32);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "Demarc.hpp"
|
||||
#include "RuntimeEnvironment.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "EllipticCurveKey.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "AtomicCounter.hpp"
|
||||
@ -54,7 +53,7 @@
|
||||
*/
|
||||
#define ZT_PEER_MAX_SERIALIZED_LENGTH ( \
|
||||
64 + \
|
||||
IDENTITY_MAX_BINARY_SERIALIZED_LENGTH + \
|
||||
ZT_IDENTITY_MAX_BINARY_SERIALIZED_LENGTH + \
|
||||
( ( \
|
||||
(sizeof(uint64_t) * 4) + \
|
||||
sizeof(uint16_t) + \
|
||||
|
@ -135,11 +135,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
std::string signature(Multicaster::signMulticastPacket(_r->identity,network->id(),from,mg,etherType,data.data(),data.size()));
|
||||
if (!signature.length()) {
|
||||
TRACE("failure signing multicast message!");
|
||||
return;
|
||||
}
|
||||
C25519::Signature signature(Multicaster::signMulticastPacket(_r->identity,network->id(),from,mg,etherType,data.data(),data.size()));
|
||||
|
||||
Packet outpTmpl(propPeers[0]->address(),_r->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
||||
outpTmpl.append((uint8_t)0);
|
||||
@ -152,9 +148,9 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
||||
outpTmpl.append((uint8_t)0); // 0 hops
|
||||
outpTmpl.append((uint16_t)etherType);
|
||||
outpTmpl.append((uint16_t)data.size());
|
||||
outpTmpl.append((uint16_t)signature.length());
|
||||
outpTmpl.append((uint16_t)signature.size());
|
||||
outpTmpl.append(data.data(),data.size());
|
||||
outpTmpl.append(signature.data(),(unsigned int)signature.length());
|
||||
outpTmpl.append(signature.data,(unsigned int)signature.size());
|
||||
outpTmpl.compress();
|
||||
send(outpTmpl,true);
|
||||
for(unsigned int i=1;i<np;++i) {
|
||||
|
26
selftest.cpp
26
selftest.cpp
@ -38,13 +38,10 @@
|
||||
#include "node/Constants.hpp"
|
||||
#include "node/RuntimeEnvironment.hpp"
|
||||
#include "node/InetAddress.hpp"
|
||||
#include "node/EllipticCurveKey.hpp"
|
||||
#include "node/EllipticCurveKeyPair.hpp"
|
||||
#include "node/Utils.hpp"
|
||||
#include "node/Identity.hpp"
|
||||
#include "node/Packet.hpp"
|
||||
#include "node/Salsa20.hpp"
|
||||
#include "node/HMAC.hpp"
|
||||
#include "node/MAC.hpp"
|
||||
#include "node/Peer.hpp"
|
||||
#include "node/Condition.hpp"
|
||||
@ -322,9 +319,9 @@ static int testPacket()
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.hmacSet(hmacKey);
|
||||
if (!a.hmacVerify(hmacKey)) {
|
||||
std::cout << "FAIL (hmacVerify)" << std::endl;
|
||||
a.macSet(hmacKey);
|
||||
if (!a.macVerify(hmacKey)) {
|
||||
std::cout << "FAIL (macVerify)" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -334,19 +331,6 @@ static int testPacket()
|
||||
|
||||
static int testOther()
|
||||
{
|
||||
std::cout << "[other] Testing Base64 encode/decode... "; std::cout.flush();
|
||||
for(unsigned int k=0;k<1000;++k) {
|
||||
unsigned int flen = (rand() % 8194) + 1;
|
||||
for(unsigned int i=0;i<flen;++i)
|
||||
fuzzbuf[i] = (unsigned char)(rand() & 0xff);
|
||||
std::string dec = Utils::base64Decode(Utils::base64Encode(fuzzbuf,flen));
|
||||
if ((dec.length() != flen)||(memcmp(dec.data(),fuzzbuf,dec.length()))) {
|
||||
std::cout << "FAILED!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
std::cout << "PASS" << std::endl;
|
||||
|
||||
std::cout << "[other] Testing hex encode/decode... "; std::cout.flush();
|
||||
for(unsigned int k=0;k<1000;++k) {
|
||||
unsigned int flen = (rand() % 8194) + 1;
|
||||
@ -365,7 +349,7 @@ static int testOther()
|
||||
std::cout << "[other] Testing command bus encode/decode... "; std::cout.flush();
|
||||
try {
|
||||
static char key[32] = { 0 };
|
||||
for(unsigned int k=0;k<1000;++k) {
|
||||
for(unsigned int k=0;k<100;++k) {
|
||||
std::vector<std::string> original;
|
||||
for(unsigned int i=0,j=rand() % 256,l=(rand() % 1024)+1;i<j;++i)
|
||||
original.push_back(std::string(l,'x'));
|
||||
@ -395,7 +379,7 @@ static int testOther()
|
||||
std::cout << "PASS" << std::endl;
|
||||
|
||||
std::cout << "[other] Testing Dictionary... "; std::cout.flush();
|
||||
for(int k=0;k<10000;++k) {
|
||||
for(int k=0;k<1000;++k) {
|
||||
Dictionary a,b;
|
||||
int nk = rand() % 32;
|
||||
for(int q=0;q<nk;++q) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user