Переглянути джерело

stuff for speed and stuff (testing)

Adam Ierymenko 6 роки тому
батько
коміт
18d1772bb4
2 змінених файлів з 83 додано та 16 видалено
  1. 1 4
      ext/ed25519-amd64-asm/sign.c
  2. 82 12
      node/C25519.cpp

+ 1 - 4
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;

+ 82 - 12
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,28 @@ 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 {
 
+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;
+
 void C25519::agree(const C25519::Private &mine,const C25519::Public &their,void *keybuf,unsigned int keylen)
 {
 	unsigned char rawkey[32];
@@ -2019,8 +2038,24 @@ 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);
+
+	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;
+	}
+
 #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 +2065,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 +2099,60 @@ 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
+
+/*
+	Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
+	Address *a = (Address *)0;
+	SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
+	while (i.next(a,p))
+		_savePeer((void *)0,*p);
+*/
+	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);
+	}
 }
 
 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;
+
+	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);
+	}
+
 	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;