diff options
author | Grant Limberg <grant.limberg@zerotier.com> | 2018-12-06 13:08:39 -0800 |
---|---|---|
committer | Grant Limberg <grant.limberg@zerotier.com> | 2018-12-06 13:08:39 -0800 |
commit | 20f02bb772cde179b6d58f33199aaaead3abba87 (patch) | |
tree | 65a49e7f4ebb61628e6c29056380f974f54dc3ea | |
parent | 1c86f25fab57f4c2bc3f314683a911959f90b9b8 (diff) | |
parent | e6f9ab929df19ba667441b005ae2b9771922a92c (diff) | |
download | infinitytier-20f02bb772cde179b6d58f33199aaaead3abba87.tar.gz infinitytier-20f02bb772cde179b6d58f33199aaaead3abba87.zip |
Merge branch 'dev' of http://git.int.zerotier.com/ZeroTier/ZeroTierOne into dev
-rw-r--r-- | ext/ed25519-amd64-asm/sign.c | 5 | ||||
-rw-r--r-- | make-linux.mk | 2 | ||||
-rw-r--r-- | node/C25519.cpp | 95 | ||||
-rw-r--r-- | node/Multicaster.cpp | 8 | ||||
-rw-r--r-- | node/Multicaster.hpp | 4 |
5 files changed, 94 insertions, 20 deletions
diff --git a/ext/ed25519-amd64-asm/sign.c b/ext/ed25519-amd64-asm/sign.c index 958e4a14..882ae76f 100644 --- a/ext/ed25519-amd64-asm/sign.c +++ b/ext/ed25519-amd64-asm/sign.c @@ -124,18 +124,15 @@ void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char extern void ZT_sha512internal(void *digest,const void *data,unsigned int len); -extern void ed25519_amd64_asm_sign(const unsigned char *sk,const unsigned char *pk,const unsigned char *m,const unsigned int mlen,unsigned char *sig) +extern void ed25519_amd64_asm_sign(const unsigned char *sk,const unsigned char *pk,const unsigned char *digest,unsigned char *sig) { unsigned char az[64]; unsigned char nonce[64]; unsigned char hram[64]; sc25519 sck, scs, scsk; ge25519 ger; - unsigned char digest[64]; unsigned int i; - ZT_sha512internal(digest,m,mlen); - ZT_sha512internal(az,sk,32); az[0] &= 248; az[31] &= 127; diff --git a/make-linux.mk b/make-linux.mk index 66a6376a..90ec2aac 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -319,7 +319,7 @@ official: FORCE make -j4 ZT_OFFICIAL=1 all central-controller: FORCE - make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq" CXXFLAGS="-I/usr/pgsql-10/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one + make -j4 LDLIBS="-L/usr/pgsql-10/lib/ -lpq" CXXFLAGS="-I/usr/pgsql-10/include -fPIC" DEFS="-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER" ZT_OFFICIAL=1 ZT_USE_X64_ASM_ED25519=1 one central-controller-docker: central-controller docker build -t gcr.io/zerotier-central/ztcentral-controller:${TIMESTAMP} -f docker/Dockerfile . diff --git a/node/C25519.cpp b/node/C25519.cpp index 77084bd8..209ac445 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -15,6 +15,8 @@ Derived from public domain code by D. J. Bernstein. #include "C25519.hpp" #include "SHA512.hpp" #include "Buffer.hpp" +#include "Hashtable.hpp" +#include "Mutex.hpp" #ifdef __WINDOWS__ #pragma warning(disable: 4146) @@ -1996,11 +1998,30 @@ void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char } // anonymous namespace #ifdef ZT_USE_FAST_X64_ED25519 -extern "C" void ed25519_amd64_asm_sign(const unsigned char *sk,const unsigned char *pk,const unsigned char *m,const unsigned int mlen,unsigned char *sig); +extern "C" void ed25519_amd64_asm_sign(const unsigned char *sk,const unsigned char *pk,const unsigned char *digest,unsigned char *sig); #endif namespace ZeroTier { +#ifdef ZT_CONTROLLER +struct C25519CacheKey +{ + uint64_t messageDigest[4]; + uint64_t publicKey[4]; + inline unsigned long hashCode() const { return (unsigned long)(messageDigest[0] ^ publicKey[0]); } + inline bool operator==(const C25519CacheKey &k) const { return (memcmp(this,&k,sizeof(C25519CacheKey)) == 0); } + inline bool operator!=(const C25519CacheKey &k) const { return (memcmp(this,&k,sizeof(C25519CacheKey)) != 0); } +}; +struct C25519CacheValue +{ + uint64_t signature[12]; + uint64_t timestamp; +}; +static uint64_t _ed25519TimestampCounter = 0; +static Hashtable<C25519CacheKey,C25519CacheValue> _ed25519Cache; +static Mutex _ed25519CacheLock; +#endif + void C25519::agree(const C25519::Private &mine,const C25519::Public &their,void *keybuf,unsigned int keylen) { unsigned char rawkey[32]; @@ -2019,8 +2040,26 @@ void C25519::agree(const C25519::Private &mine,const C25519::Public &their,void void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPublic,const void *msg,unsigned int len,void *signature) { + unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg) + SHA512::hash(digest,msg,len); + +#ifdef ZT_CONTROLLER + C25519CacheKey ck; + ZT_FAST_MEMCPY(ck.messageDigest,digest,32); + ZT_FAST_MEMCPY(ck.publicKey,myPublic.data + 32,32); + C25519CacheValue *cv = (C25519CacheValue *)0; + { + Mutex::Lock l(_ed25519CacheLock); + cv = _ed25519Cache.get(ck); + } + if (cv) { + ZT_FAST_MEMCPY(signature,cv->signature,ZT_C25519_SIGNATURE_LEN); + return; + } +#endif + #ifdef ZT_USE_FAST_X64_ED25519 - ed25519_amd64_asm_sign(myPrivate.data + 32,myPublic.data + 32,(const unsigned char *)msg,len,(unsigned char *)signature); + ed25519_amd64_asm_sign(myPrivate.data + 32,myPublic.data + 32,digest,(unsigned char *)signature); #else sc25519 sck, scs, scsk; ge25519 ger; @@ -2030,9 +2069,6 @@ void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPubli unsigned char hmg[crypto_hash_sha512_BYTES]; unsigned char hram[crypto_hash_sha512_BYTES]; unsigned char *sig = (unsigned char *)signature; - unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg) - - SHA512::hash(digest,msg,len); SHA512::hash(extsk,myPrivate.data + 32,32); extsk[0] &= 248; @@ -2067,22 +2103,57 @@ void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPubli for(unsigned int i=0;i<32;i++) sig[32 + i] = s[i]; #endif + +#ifdef ZT_CONTROLLER + C25519CacheValue cvn; + memcpy(cvn.signature,signature,ZT_C25519_SIGNATURE_LEN); + { + Mutex::Lock l(_ed25519CacheLock); + + if (_ed25519Cache.size() > 1048576) { + const uint64_t before = _ed25519TimestampCounter - ((1048576 / 3) * 2); + Hashtable< C25519CacheKey,C25519CacheValue >::Iterator i(_ed25519Cache); + C25519CacheKey *ik = (C25519CacheKey *)0; + C25519CacheValue *iv = (C25519CacheValue *)0; + while (i.next(ik,iv)) { + if (iv->timestamp < before) + _ed25519Cache.erase(*ik); + } + } + + cvn.timestamp = ++_ed25519TimestampCounter; + _ed25519Cache.set(ck,cvn); + } +#endif } bool C25519::verify(const C25519::Public &their,const void *msg,unsigned int len,const void *signature) { + const unsigned char *const sig = (const unsigned char *)signature; + unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg) + SHA512::hash(digest,msg,len); + if (!Utils::secureEq(sig + 64,digest,32)) + return false; + +#ifdef ZT_CONTROLLER + C25519CacheKey ck; + ZT_FAST_MEMCPY(ck.messageDigest,digest,32); + ZT_FAST_MEMCPY(ck.publicKey,their.data + 32,32); + C25519CacheValue *cv = (C25519CacheValue *)0; + { + Mutex::Lock l(_ed25519CacheLock); + cv = _ed25519Cache.get(ck); + } + if (cv) { + return Utils::secureEq(cv->signature,signature,ZT_C25519_SIGNATURE_LEN); + } +#endif + unsigned char t2[32]; ge25519 get1, get2; sc25519 schram, scs; unsigned char hram[crypto_hash_sha512_BYTES]; unsigned char m[96]; - unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg) - const unsigned char *sig = (const unsigned char *)signature; - - // First check the message's integrity - SHA512::hash(digest,msg,len); - if (!Utils::secureEq(sig + 64,digest,32)) - return false; if (ge25519_unpackneg_vartime(&get1,their.data + 32)) return false; diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index b2a5a205..2b5fb041 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -444,15 +444,17 @@ void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup if (member == RR->identity.address()) return; - for(std::vector<MulticastGroupMember>::iterator m(gs.members.begin());m!=gs.members.end();++m) { + std::vector<MulticastGroupMember>::iterator m(std::lower_bound(gs.members.begin(),gs.members.end(),member)); + if (m != gs.members.end()) { if (m->address == member) { m->timestamp = now; return; } + gs.members.insert(m,MulticastGroupMember(member,now)); + } else { + gs.members.push_back(MulticastGroupMember(member,now)); } - gs.members.push_back(MulticastGroupMember(member,now)); - for(std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { if (tx->atLimit()) gs.txQueue.erase(tx++); diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp index e57f81fe..c6c2a209 100644 --- a/node/Multicaster.hpp +++ b/node/Multicaster.hpp @@ -203,6 +203,10 @@ private: MulticastGroupMember() {} MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {} + inline bool operator<(const Address &a) const { return (address < a); } + inline bool operator==(const Address &a) const { return (address == a); } + inline bool operator!=(const Address &a) const { return (address != a); } + Address address; uint64_t timestamp; // time of last notification }; |