summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrant Limberg <grant.limberg@zerotier.com>2018-12-06 13:08:39 -0800
committerGrant Limberg <grant.limberg@zerotier.com>2018-12-06 13:08:39 -0800
commit20f02bb772cde179b6d58f33199aaaead3abba87 (patch)
tree65a49e7f4ebb61628e6c29056380f974f54dc3ea
parent1c86f25fab57f4c2bc3f314683a911959f90b9b8 (diff)
parente6f9ab929df19ba667441b005ae2b9771922a92c (diff)
downloadinfinitytier-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.c5
-rw-r--r--make-linux.mk2
-rw-r--r--node/C25519.cpp95
-rw-r--r--node/Multicaster.cpp8
-rw-r--r--node/Multicaster.hpp4
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
};