diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2013-09-16 13:57:57 -0400 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2013-09-16 13:57:57 -0400 |
commit | e376c6f6a989d99d873918b349405302b62403a5 (patch) | |
tree | 446962e3a4d17a6d6aaa2976c2da156f5a5e2a03 | |
parent | ceb024ab03a114c8dadbbd393032231069981c45 (diff) | |
download | infinitytier-e376c6f6a989d99d873918b349405302b62403a5.tar.gz infinitytier-e376c6f6a989d99d873918b349405302b62403a5.zip |
New crypto integrated -- going to be testing new identity address generation algo a bit more before finalizing.
-rw-r--r-- | Makefile.mac | 2 | ||||
-rw-r--r-- | main.cpp | 34 | ||||
-rw-r--r-- | node/Defaults.cpp | 2 | ||||
-rw-r--r-- | node/Identity.cpp | 7 | ||||
-rw-r--r-- | node/Identity.hpp | 42 | ||||
-rw-r--r-- | node/Multicaster.hpp | 59 | ||||
-rw-r--r-- | node/Network.cpp | 2 | ||||
-rw-r--r-- | node/Node.cpp | 10 | ||||
-rw-r--r-- | node/NodeConfig.cpp | 2 | ||||
-rw-r--r-- | node/Peer.hpp | 3 | ||||
-rw-r--r-- | node/Switch.cpp | 10 | ||||
-rw-r--r-- | selftest.cpp | 26 |
12 files changed, 84 insertions, 115 deletions
diff --git a/Makefile.mac b/Makefile.mac index 68f9770f..a6637bf8 100644 --- a/Makefile.mac +++ b/Makefile.mac @@ -13,7 +13,7 @@ STRIP=strip #STRIP=echo CXXFLAGS=$(CFLAGS) -fno-rtti -LIBS=-lcrypto -lm +LIBS=-lm include objects.mk @@ -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] == '-') { diff --git a/node/Defaults.cpp b/node/Defaults.cpp index 9f7d04fe..d50e1840 100644 --- a/node/Defaults.cpp +++ b/node/Defaults.cpp @@ -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; } diff --git a/node/Identity.cpp b/node/Identity.cpp index 5a752e85..67892232 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -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) { diff --git a/node/Identity.hpp b/node/Identity.hpp index de4ad2a0..eb8b19a4 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -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 { /** @@ -149,6 +151,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 * * This identity must have a private key. (Check hasPrivate()) @@ -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; } diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index 58bfeed1..8ff8e65e 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -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; diff --git a/node/Network.cpp b/node/Network.cpp index fa5b86d3..6a28228b 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -30,8 +30,6 @@ #include <stdlib.h> #include <math.h> -#include <openssl/sha.h> - #include "RuntimeEnvironment.hpp" #include "NodeConfig.hpp" #include "Network.hpp" diff --git a/node/Node.cpp b/node/Node.cpp index 590b9662..c3771df0 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -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; diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index 4567d410..823e2798 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -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); } diff --git a/node/Peer.hpp b/node/Peer.hpp index 85f045ef..f1ea653c 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -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) + \ diff --git a/node/Switch.cpp b/node/Switch.cpp index e17f2196..92fb7876 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -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) { diff --git a/selftest.cpp b/selftest.cpp index 1bdb3b05..ecdf51f1 100644 --- a/selftest.cpp +++ b/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) { |